// ----------------------------------------------------------------------------------------
//
//  avr/device/uart.h
//    
//  Bob Cook Development, Robotics Library
//  http://www.bobcookdev.com/rl/
//    
//  This file provides the interface for the UART library.
//
//  Copyright (C) 2008 Bob Cook
//
//      This program is free software; you can redistribute it and/or modify it
//      under the terms of the GNU General Public License as published by the
//      Free Software Foundation; either version 2 of the License, or (at your
//      option) any later version.
//    
//      This program is distributed in the hope that it will be useful, but 
//      WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
//      or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
//      for more details.
//    
//      You should have received a copy of the GNU General Public License along
//      with this program; if not, write to the Free Software Foundation, Inc., 
//      51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// ----------------------------------------------------------------------------------------


#if !defined( BCDRL_AVR_DEVICE_UART_H )
#define BCDRL_AVR_DEVICE_UART_H


#include <stdint.h>
#include <avr/pgmspace.h>


// ----------------------------------------------------------------------------------------
//  definitions from "project_defs.h"
//
//  enable uart0 by using one (and only one) of:
//  
//      + PRJ_UART0_USE_INTERRUPT_MODE
//      + PRJ_UART0_USE_POLLED_MODE
//
//  enable uart1 by using one (and only one) of:
//
//      + PRJ_UART1_USE_INTERRUPT_MODE
//      + PRJ_UART1_USE_POLLED_MODE
//
//  optionally set an initial baud rate with:
//  
//      + PRJ_UART0_INITIAL_BAUDRATE
//      + PRJ_UART1_INITIAL_BAUDRATE
//
//  enable the "extended" read and write modes with:
//
//      + PRJ_UART0_EXTENDED_READ_WRITE
//      + PRJ_UART1_EXTENDED_READ_WRITE
//
//  if using INTERRUPT_MODE then optionally define:
//
//      + PRJ_UART0_BUFFER_SIZE <int>
//      + PRJ_UART1_BUFFER_SIZE <int>
//
// ----------------------------------------------------------------------------------------


// ----------------------------------------------------------------------------------------
//  uart*_init
//
//      Initialize the specified UART h/w; call this once, before doing any serial i/o.
//
//      If PRJ_UART*_INITIAL_BAUDRATE is defined then the intial baudrate will be set by
//      this function. If not set, the caller is responsible for setting a proper value.
//

void uart0_init();
void uart1_init();


// ----------------------------------------------------------------------------------------
//  uart*_set_baudrate
//
//      Use this macro to set the desired baud rate for a specified UART. Everything else
//      is computed at compile-time for you.
//
//      Example: uart0_set_baudrate( 9600 );
//

#define uart0_set_baudrate( baudrate ) \
            uart0_set_baudregisters( \
            ( ( ( PRJ_CPU_FREQ / ( (baudrate) * 16L ) - 1 ) >> 8 ) & 0x0F ), \
            ( ( ( PRJ_CPU_FREQ / ( (baudrate) * 16L ) - 1 ) ) ) & 0xFF )

#define uart1_set_baudrate( baudrate ) \
            uart1_set_baudregisters( \
            ( ( ( PRJ_CPU_FREQ / ( (baudrate) * 16L ) - 1 ) >> 8 ) & 0x0F ), \
            ( ( ( PRJ_CPU_FREQ / ( (baudrate) * 16L ) - 1 ) ) ) & 0xFF )


// ----------------------------------------------------------------------------------------
//  uart*_set_baudregisters
//
//      Set the high and low bytes of the UART baud rate registers. Either compute them
//      directly (correctly masking the high byte to account for only modifying the low
//      four bits) or use the set_baudrate macro defined above.
//

void uart0_set_baudregisters( uint8_t highbyte, uint8_t lowbyte );
void uart1_set_baudregisters( uint8_t highbyte, uint8_t lowbyte );


// ----------------------------------------------------------------------------------------
//  uart*_is_char_available
//
//      Returns true if a character is available.
//

bool uart0_is_char_available();
bool uart1_is_char_available();


// ----------------------------------------------------------------------------------------
//  uart*_read
//
//      Read a character from the UART. Blocks until a character is available.
//

uint8_t uart0_read();
uint8_t uart1_read();


// ----------------------------------------------------------------------------------------
//  uart*_read
//
//      These functions are only available if PRJ_UART*_EXTENDED_READ_WRITE is defined.
//      

void uart0_read( const uint8_t* data, uint8_t len );
void uart1_read( const uint8_t* data, uint8_t len );


// ----------------------------------------------------------------------------------------
//  uart*_write
//
//      Write a character to the UART buffer. In "polled" mode this function blocks
//      until the character can be written to the h/w buffe. In "interrupt" mode this
//      function blocks only if there is no buffer space available.
//

void uart0_write( uint8_t data );
void uart1_write( uint8_t data );


// ----------------------------------------------------------------------------------------
//  uart*_write
//
//      These functions are only available if PRJ_UART*_EXTENDED_READ_WRITE is defined.
//      

void uart0_write( const uint8_t* data, uint8_t len );
void uart0_write( const char* str );

void uart1_write( const uint8_t* data, uint8_t len );
void uart1_write( const char* str );


// ----------------------------------------------------------------------------------------
//  uart*_write_pgm
//
//      Write bytes stored in "program memory" to the UART buffer. These functions can
//      only access the lower 64k of memory, see the implementation for details.
//
//      These functions are only available if PRJ_UART*_EXTENDED_READ_WRITE is defined.
//

void uart0_write_pgm( const prog_uint8_t* data, uint8_t len );
void uart0_write_pgm( const prog_char* str );

void uart1_write_pgm( const prog_uint8_t* data, uint8_t len );
void uart1_write_pgm( const prog_char* str );


#endif  // #if !defined( BCDRL_AVR_DEVICE_UART_H )
// ----------------------------------------------------------------------------------------
//  end of uart.h
// ----------------------------------------------------------------------------------------

