/* This file has been prepared for Doxygen automatic documentation generation.*/ /*! \file ********************************************************************* * * \brief This files implements a communications library for the FTDI chip on the * STK541 board and the AVR USART used for the RZ502 version. * * \note The code must be compiled with either STK541 (USB) or RZ502 (RS232) defined. * * \par Application note: * AVR2001: Transceiver Access Toolbox for the AT86RF230 * * \par Documentation * For comprehensive code documentation, supported compilers, compiler * settings and supported devices see readme.html * * \author * Atmel Corporation: http://www.atmel.com \n * Support email: avr@atmel.com * * $Name$ * $Revision: 613 $ * $RCSfile$ * $Date: 2006-04-07 14:40:07 +0200 (fr, 07 apr 2006) $ \n * * Copyright (c) 2006, Atmel Corporation All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The name of ATMEL may not be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ /*============================ INCLDUE =======================================*/ #include #include #define UART_EXTENDED #ifdef UART_EXTENDED #include "config_uart_extended.h" #else #include "config_uart.h" #endif #include "compiler.h" #include "com.h" /*============================ MACROS ========================================*/ #define COM_RX_MAX_BYTES (COM_RX_BUFFER_SIZE - 2) //!< Maximal number of bytes that one message can contain (PSDU_LENGTH - CRC_LENGTH). /*============================ TYPEDEFS ======================================*/ /*============================ VARIABLES =====================================*/ static uint8_t com_buffer[ COM_RX_BUFFER_SIZE ]; //!< Array storing rx data. static uint8_t com_number_of_received_bytes; //!< Number of bytes in com_buffer. static bool com_data_reception_finished; //!< Flag indicating EOT (That "\r\n is received.") static uint8_t hex_lookup[ ] = "0123456789ABCDEF"; //!< Look up table for hexadecimal number conversion. /*============================ PROTOTYPES ====================================*/ /*! \brief This function initializes the chosen communication interface (USB or USART). * * \param[in] rate Baudrate used by the AVR's USART. */ void com_init( baud_rate_t rate ){ #if defined( RZ502 ) //Initialize USART module. UBRR0H = 0x00; UBRR0L = rate; //Enable USART transmitter module. Always on. ENABLE_RECEIVER; ENABLE_TRANSMITTER; //8-N-1. UCSR0C |= ( 1 << UCSZ01 ) | ( 1 << UCSZ00 ); com_number_of_received_bytes = 0; com_data_reception_finished = false; ENABLE_RECEIVE_COMPLETE_INTERRUPT; #elif defined( STK541 ) XRAM_ENABLE( ); /* make sure USB_RXF and USB_TXE are inputs */ FTDI_ENABLE_TX( ); //Enable external interrupt on FTDI_RX pin. FTDI_CONFIGURE_PIN_CHANGE_INTERRUPT( ); FTDI_ENABLE_RECEIVER( ); #else #error "Board Option Not Supported." #endif } /*! \brief This function sends data on the chosen communication interface (USB or USART). * * \param[in] data Pointer to data that is to be sent on the communication interface. * \param[in] data_length Number of bytes to read from the array pointed to by data. */ void com_send_string( uint8_t *data, uint8_t data_length ){ while (--data_length > 0) { #if defined( RZ502 ) for(; !(UCSR0A & (1 << UDRE0));) {;} UDR0 = *data++; //Put symbol in data register. #elif defined( STK541 ) //Wait until the fifo is ready. while((FTDI_TX_MASK & FTDI_PIN) != LOW){;} //Write symbol to memory address. *FTDI_Fifo = ( *data++ ); #else #error "Board Option Not Supported." #endif } } /*! \brief This function prints the supplied argument as a hex number. * * \param[in] nmbr Number to be printed as a hexadescimal number. */ void com_send_hex( uint8_t nmbr ){ #if defined( RZ502 ) for(; !(UCSR0A & (1 << UDRE0));) {;} UDR0 = '0'; //Put symbol in data register. for(; !(UCSR0A & (1 << UDRE0));) {;} UDR0 = 'x'; //Put symbol in data register. for(; !(UCSR0A & (1 << UDRE0));) {;} UDR0 = hex_lookup[ ( nmbr >> 4 ) & 0x0F ]; for(; !(UCSR0A & (1 << UDRE0));) {;} UDR0 = hex_lookup[ ( nmbr & 0x0F ) ]; #elif defined( STK541 ) //Wait until the fifo is ready. while((FTDI_TX_MASK & FTDI_PIN) != LOW){;} *FTDI_Fifo = '0'; //Put symbol in data register. while((FTDI_TX_MASK & FTDI_PIN) != LOW){;} *FTDI_Fifo = 'x'; //Put symbol in data register. while((FTDI_TX_MASK & FTDI_PIN) != LOW){;} *FTDI_Fifo = hex_lookup[ ( nmbr >> 4 ) & 0x0F ]; while((FTDI_TX_MASK & FTDI_PIN) != LOW){;} *FTDI_Fifo = hex_lookup[ ( nmbr & 0x0F ) ]; #else #error "Board Option Not Supported." #endif } /*! \brief This function retruns the address to the first byte in the buffer where received data is stored3. * * \note This function should only be called after it has been verified that the * data reception is done (com_get_number_of_received_bytes() != 0). * \return Pointer to the first byte in the array of received data. */ uint8_t * com_get_received_data( void ){ return &com_buffer[0]; } /*! \brief This function returns number of bytes received during last data reception. * * \retval 0 No data is available. Data reception is not done. * \retval 1 Error: Typed Frame Too Long. * \return Any non zero value returned indicatest that data is available and should be read. */ uint8_t com_get_number_of_received_bytes( void ){ if (com_data_reception_finished == true) { return com_number_of_received_bytes; } else { return 0; } } /*! \brief This function is used to reset the commuincation interface after each * data reception is done, and the end-user has read data. * */ void com_reset_receiver( void ){ #if defined( RZ502 ) DISABLE_RECEIVE_COMPLETE_INTERRUPT; com_number_of_received_bytes = 0; com_data_reception_finished = false; uint8_t dummy = 0; //Following loop is used to ensure that the rx FIFO is flushed. //Sometimes it gets cloged up with old data. for( ; UCSR0A & ( 1 << RXC0 ); ){ dummy = UDR0; } ENABLE_RECEIVE_COMPLETE_INTERRUPT; #elif defined( STK541 ) FTDI_DISABLE_RECEIVER( ); com_number_of_received_bytes = 0; com_data_reception_finished = false; FTDI_ENABLE_RECEIVER( ); #else #error "Board Option Not Supported." #endif } /*! \brief Universal receive interrupt service routine for both USART0 and the FTDI USB chip. * * This routine is called whenever a new byte is available to be read. This service routine * does also implement a sort of pre parsing of the incoming data stream. The stream is * terminated when the EOT character is detected ('\n'). The serial interface will be * stoped and the since the com_data_reception_finished flag set to true. * The routine appends two characters at */ #ifdef RZ502 ISR( USART0_RX_vect ){ uint8_t receivedData; receivedData = ( uint8_t )UDR0; //Collect data. #else ISR( INT7_vect ){ uint8_t receivedData; receivedData = ( uint8_t )*FTDI_Fifo; //Collect data. #endif if (com_number_of_received_bytes < COM_RX_MAX_BYTES) { //End of data stream. if (receivedData == '\n') { #if defined( RZ502 ) DISABLE_RECEIVE_COMPLETE_INTERRUPT; #elif defined( STK541 ) FTDI_DISABLE_RECEIVER( ); #else #error "Board Option Not Supported." #endif com_buffer[com_number_of_received_bytes++] = receivedData; com_buffer[com_number_of_received_bytes++] = 0x00; com_buffer[com_number_of_received_bytes++] = 0x00; com_data_reception_finished = true; } else { com_buffer[com_number_of_received_bytes++] = receivedData; } } else{ #if defined( RZ502 ) DISABLE_RECEIVE_COMPLETE_INTERRUPT; #elif defined( STK541 ) FTDI_DISABLE_RECEIVER( ); #else #error "Board Option Not Supported." #endif com_number_of_received_bytes = 1; com_data_reception_finished = true; } }