/* This file has been prepared for Doxygen automatic documentation generation.*/ /*! \file ********************************************************************* * * \brief This files implements a very simple serial communication link between * two nodes. * * \section wireless_uart The Simple Wireless Uart Example * This particular example implements a very simple and crude wireless uart. * It does not use any of the mechanisms described by the IEEE 802.15.4 * standard. It will simply send the last message received on the serial * interface, and not check for a busy channel or wait for an * acknowledgement. This is just to show how simple it can be to * communicate with the AT86RF230 radio transceiver. Data received on the * air interface will be pushed onto the serial stream (USB or RS232). * * \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 #include "config_uart.h" // See this file for all project options. #include "compiler.h" #include "at86rf230_registermap.h" #include "hal.h" #include "tat.h" #include "com.h" /*============================ MACROS ========================================*/ /*============================ TYPEDEFS ======================================*/ /*============================ VARIABLES =====================================*/ static hal_rx_frame_t rx_pool[ RX_POOL_SIZE ]; //!< Pool of hal_rx_frame_t's. static hal_rx_frame_t *rx_pool_start; //!< Pointer to start of pool. static hal_rx_frame_t *rx_pool_end; //!< Pointer to end of pool. static hal_rx_frame_t *rx_pool_head; //!< Pointer to next hal_rx_frame_t it is possible to write. static hal_rx_frame_t *rx_pool_tail; //!< Pointer to next hal_rx_frame_t that can be read from the pool. static uint8_t rx_pool_items_free; //!< Number of free items (hal_rx_frame_t) in the pool. static uint8_t rx_pool_items_used; // !< Number of used items. static bool rx_pool_overflow_flag; //!< Flag that is used to signal a pool overflow. static bool rx_flag; //!< Flag used to mask between the two possible TRX_END events. static uint8_t debug_pll_transition[] = "State transition failed\r\n"; //!< Debug Text. static uint8_t debug_type_message[] = "\r<---Type Message:\r\n"; //!< Debug Text. static uint8_t debug_data_sent[] = "<---TX OK.\r\n"; //!< Debug Text. static uint8_t debug_data_received[] = "\r--->Rx:\r"; //!< Debug Text. static uint8_t debug_lqi[] = "LQI: "; //!< Debug Text. static uint8_t debug_rx_pool_overflow[] = "RX Buffer Overflow!\r\n"; //!< Debug Text. static uint8_t debug_transmission_failed[] = "TX Failed!\r\n"; //!< Debug Text. static uint8_t debug_transmission_length[] = "Typed Message too long!!\r\n"; //!< Debug Text. static uint8_t debug_fatal_error[] = "A fatal error. System must be reset.\r\n"; //!< Debug Text. /*============================ PROTOTYPES ====================================*/ static bool trx_init( void ); static void avr_init( void ); static void trx_end_handler( uint32_t time_stamp ); static void rx_pool_init( void ); /*! \brief This function is used to initialize the TRX. * * \retval true if the TRX was successfully configured. * \retval false if the TRX was not configured properly. */ static bool trx_init( void ){ static bool status; if (tat_init( ) != TAT_SUCCESS) { status = false; } else if (tat_set_operating_channel( OPERATING_CHANNEL ) != TAT_SUCCESS) { status = false; } else if (tat_set_clock_speed( true, CLKM_DISABLED ) != TAT_SUCCESS) { status = false; } else{ tat_use_auto_tx_crc( true ); //Automatic CRC must be enabled. hal_set_trx_end_event_handler( trx_end_handler ); // Event handler for TRX_END events. status = true; } // end: if (tat_init( ) != TAT_SUCCESS) ... return status; } /*! \brief This function configure the necessary IO modules on the AVR. */ static void avr_init( void ){ com_init( BR_38400 ); } /*! \brief This function initialize the rx_pool. The rx_pool is in essence a FIFO. */ static void rx_pool_init( void ){ rx_pool_start = rx_pool; rx_pool_end = &rx_pool[ RX_POOL_SIZE - 1 ]; rx_pool_head = rx_pool_start; rx_pool_tail = rx_pool_end; rx_pool_items_free = RX_POOL_SIZE; rx_pool_items_used = 0; rx_pool_overflow_flag = false; } /*! \brief This function is the TRX_END event handler that is called from the * TRX isr if assigned. * * \param[in] time_stamp Interrupt timestamp in IEEE 802.15.4 symbols. */ static void trx_end_handler( uint32_t time_stamp ){ if (rx_flag == true) { //Check if these is space left in the rx_pool. if (rx_pool_items_free == 0) { rx_pool_overflow_flag = true; } else { //Space left, so upload the received frame. hal_frame_read( rx_pool_head ); //Then check the CRC. Will not store frames with invalid CRC. if (rx_pool_head->crc == true) { //Handle wrapping of rx_pool. if (rx_pool_head == rx_pool_end) { rx_pool_head = rx_pool_start; } else { ++rx_pool_head; } // end: if (rx_pool_head == rx_pool_end) ... --rx_pool_items_free; ++rx_pool_items_used; } // end: if (rx_pool_head->crc == true) ... } // end: if (rx_pool_items_free == 0) ... } // end: if (rx_flag == true) ... } void main( void ){ static uint8_t length_of_received_data = 0; rx_flag = true; rx_pool_init( ); avr_init( ); trx_init( ); //Set system state to RX_ON if (tat_set_trx_state( RX_ON ) != TAT_SUCCESS) { com_send_string( debug_fatal_error, sizeof( debug_fatal_error ) ); } // end: if (tat_set_trx_state( RX_ON ) != TAT_SUCCESS) ... sei( ); //Give the user an indication that the system is ready. com_send_string( debug_type_message, sizeof( debug_type_message ) ); /*Enter Normal Program Flow: - Check for newly received frames. Print them if something is received. - Notify on rx_pool overflow. - Try to send data on air interface, if something is received on UART/USB. - Notify if the typed message was too long. */ while (true) { //Check if we have received something on the air interface. if (rx_pool_items_used != 0) { //Handle wrapping of rx_pool. if (rx_pool_tail == rx_pool_end) { rx_pool_tail = rx_pool_start; } else { ++rx_pool_tail; } // end: if (rx_pool_tail == rx_pool_end) ... //Turn interrupts off for a short while to protect when status //information about the rx_pool is updated. cli( ); ++rx_pool_items_free; --rx_pool_items_used; sei( ); //Send the frame to the user: com_send_string( debug_data_received, sizeof( debug_data_received ) ); com_send_string( rx_pool_tail->data, ((rx_pool_tail->length) - 2 ) ); com_send_string( debug_lqi, sizeof( debug_lqi ) ); com_send_hex( rx_pool_tail->lqi ); com_send_string( debug_type_message, sizeof( debug_type_message ) ); } // end: if (rx_pool_items_used != 0) ... //Check for rx_pool overflow. if (rx_pool_overflow_flag == true) { cli(); rx_pool_init( ); com_send_string( debug_rx_pool_overflow, sizeof( debug_rx_pool_overflow ) ); sei(); } // end: if (rx_pool_overflow_flag == true) ... //Check for new data on the serial interface. //Check if data is ready to be sent. length_of_received_data = com_get_number_of_received_bytes( ); if (length_of_received_data == 1) { //length_of_received_data == 1 indicates a buffer overflow. Received data too long. com_send_string( debug_transmission_length, sizeof( debug_transmission_length ) ); com_reset_receiver( ); } else { if ((length_of_received_data >= 3) && (length_of_received_data <= COM_RX_BUFFER_SIZE)) { //Change state to PLL_ON and send data if the state transition was successful. if (tat_set_trx_state( PLL_ON ) == TAT_SUCCESS) { uint8_t *rx_frame = com_get_received_data( ); rx_flag = false; // Set the flag false, so that the TRX_END event is not misinterpreted. if (tat_send_data( length_of_received_data, rx_frame ) == TAT_SUCCESS) { com_send_string( debug_data_sent, sizeof( debug_data_sent ) ); } else { com_send_string( debug_transmission_failed, sizeof( debug_transmission_failed ) ); } // end: if (tat_send_data_with_retry( tx_frame_length, tx_frame, 1 ) ... //Wait for the TRX FSM to go back to PLL_ON. while (tat_get_trx_state( ) != PLL_ON) {;} } else { com_send_string( debug_pll_transition, sizeof( debug_pll_transition ) ); } // end: if (tat_set_trx_state( PLL_ON ) == TAT_SUCCESS) ... if (tat_set_trx_state( RX_ON ) != TAT_SUCCESS) { com_send_string( debug_fatal_error, sizeof( debug_fatal_error ) ); } // end: if (tat_set_trx_state( RX_ON ) != TAT_SUCCESS) ... rx_flag = true; // Set the flag back again. Only used to protec the frame transmission. com_reset_receiver( ); com_send_string( debug_type_message, sizeof( debug_type_message ) ); } // end: } // end: if (length_of_received_data == 1) ... } // emd: while (true) ... } /*EOF*/