AVR Z-LINKŪ


hal_avr.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00056 /*============================ INCLUDE =======================================*/
00057 #include "at86rf230_registermap.h"
00058 
00059 #include "compiler.h"
00060 #include "hal.h"
00061 /*============================ MACROS ========================================*/
00062 
00063 /*
00064  * Macros defined for the radio transceiver's access modes.
00065  *
00066  * These functions are implemented as macros since they are used very often and
00067  * we want to remove the function call overhead.
00068  */
00069 #define HAL_DUMMY_READ         ( 0x00 ) 
00070 
00071 #define HAL_TRX_CMD_RW         ( 0xC0 ) 
00072 #define HAL_TRX_CMD_RR         ( 0x80 ) 
00073 #define HAL_TRX_CMD_FW         ( 0x60 ) 
00074 #define HAL_TRX_CMD_FR         ( 0x20 ) 
00075 #define HAL_TRX_CMD_SW         ( 0x40 ) 
00076 #define HAL_TRX_CMD_SR         ( 0x00 ) 
00077 #define HAL_TRX_CMD_RADDRM     ( 0x7F ) 
00078 
00079 #define HAL_CALCULATED_CRC_OK   ( 0 ) 
00080 /*============================ TYPDEFS =======================================*/
00081 /*============================ VARIABLES =====================================*/
00093 static uint16_t hal_system_time;
00094 
00095 /*Flag section.*/
00096 static uint8_t volatile hal_bat_low_flag; 
00097 static uint8_t volatile hal_trx_ur_flag; 
00098 static uint8_t volatile hal_trx_end_flag; 
00099 static uint8_t volatile hal_rx_start_flag; 
00100 static uint8_t volatile hal_unknown_isr_flag; 
00101 static uint8_t volatile hal_pll_unlock_flag; 
00102 static uint8_t volatile hal_pll_lock_flag;   
00103 
00104 /*Callbacks.*/
00105 
00117 static hal_trx_isr_event_handler_t rx_start_callback;
00118 
00130 static hal_trx_isr_event_handler_t trx_end_callback;
00131 /*============================ PROTOTYPES ====================================*/
00132 /*============================ IMPLEMENTATION ================================*/
00133 
00138 void hal_init( void ){
00139     
00140     /*Reset variables used in file.*/
00141     hal_system_time = 0;
00142     hal_reset_flags( );
00143     
00144     /*IO Specific Initialization.*/
00145     DDR_SLP_TR |= (1 << SLP_TR); //Enable SLP_TR as output.
00146     DDR_RST    |= (1 << RST);    //Enable RST as output.
00147     
00148     /*SPI Specific Initialization.*/    
00149     //Set SS, CLK and MOSI as output.
00150     HAL_DDR_SPI  |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI);
00151     HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); //Set SS and CLK high
00152     SPCR         = (1 << SPE) | (1 << MSTR); //Enable SPI module and master operation.
00153     SPSR         = (1 << SPI2X); //Enable doubled SPI speed in master mode.
00154 
00155     /*TIMER1 Specific Initialization.*/    
00156     TCCR1B = HAL_TCCR1B_CONFIG;       //Set clock prescaler  
00157     TIFR1 |= (1 << ICF1);             //Clear Input Capture Flag.
00158     HAL_ENABLE_OVERFLOW_INTERRUPT( ); //Enable Timer1 overflow interrupt. 
00159     hal_enable_trx_interrupt( );    //Enable interrupts from the radio transceiver.
00160 }
00161 
00167 void hal_reset_flags( void ){
00168     
00169     AVR_ENTER_CRITICAL_REGION( );
00170     
00171     //Reset Flags.
00172     hal_bat_low_flag     = 0;
00173     hal_trx_ur_flag      = 0;
00174     hal_trx_end_flag     = 0;
00175     hal_rx_start_flag    = 0;  
00176     hal_unknown_isr_flag = 0;
00177     hal_pll_unlock_flag  = 0;
00178     hal_pll_lock_flag    = 0;
00179     
00180     //Reset Associated Event Handlers.
00181     rx_start_callback = NULL;
00182     trx_end_callback  = NULL;
00183     
00184     AVR_LEAVE_CRITICAL_REGION( )
00185 }
00186 
00195 uint8_t hal_get_bat_low_flag( void ){
00196     return hal_bat_low_flag;
00197 }
00198 
00203 void hal_clear_bat_low_flag( void ){
00204     
00205     AVR_ENTER_CRITICAL_REGION( );
00206     hal_bat_low_flag = 0;
00207     AVR_LEAVE_CRITICAL_REGION( );
00208 }
00209 
00218 uint8_t hal_get_trx_ur_flag( void ){
00219     return hal_trx_ur_flag;
00220 }
00221 
00226 void hal_clear_trx_ur_flag( void ){
00227     
00228     AVR_ENTER_CRITICAL_REGION( );
00229     hal_trx_ur_flag = 0;
00230     AVR_LEAVE_CRITICAL_REGION( );
00231 }
00232 
00241 uint8_t hal_get_trx_end_flag( void ){
00242     return hal_trx_end_flag;
00243 }
00244 
00249 void hal_clear_trx_end_flag( void ){
00250     
00251     AVR_ENTER_CRITICAL_REGION( );
00252     hal_trx_end_flag = 0;
00253     AVR_LEAVE_CRITICAL_REGION( );
00254 }
00255 
00261 void hal_set_trx_end_event_handler( hal_trx_isr_event_handler_t trx_end_callback_handle ){
00262     
00263     AVR_ENTER_CRITICAL_REGION( );
00264     trx_end_callback = trx_end_callback_handle;
00265     AVR_LEAVE_CRITICAL_REGION( );
00266 }
00267 
00272 void hal_clear_trx_end_event_handler( void ){
00273     
00274     AVR_ENTER_CRITICAL_REGION( );
00275     trx_end_callback = NULL;
00276     AVR_LEAVE_CRITICAL_REGION( );
00277 }
00278 
00287 uint8_t hal_get_rx_start_flag( void ){
00288     return hal_rx_start_flag;
00289 }
00290 
00295 void hal_clear_rx_start_flag( void ){
00296     
00297     AVR_ENTER_CRITICAL_REGION( );
00298     hal_rx_start_flag = 0;
00299     AVR_LEAVE_CRITICAL_REGION( );
00300 }
00301 
00307 void hal_set_rx_start_event_handler( hal_trx_isr_event_handler_t rx_start_callback_handle ){
00308     
00309     AVR_ENTER_CRITICAL_REGION( );
00310     rx_start_callback = rx_start_callback_handle;
00311     AVR_LEAVE_CRITICAL_REGION( );
00312 }
00313 
00318 void hal_clear_rx_start_event_handler( void ){
00319     
00320     AVR_ENTER_CRITICAL_REGION( );
00321     rx_start_callback = NULL;
00322     AVR_LEAVE_CRITICAL_REGION( );
00323 }
00324 
00333 uint8_t hal_get_unknown_isr_flag( void ){
00334     return hal_unknown_isr_flag;
00335 }
00336 
00341 void hal_clear_unknown_isr_flag( void ){
00342     
00343     AVR_ENTER_CRITICAL_REGION( );
00344     hal_unknown_isr_flag = 0;
00345     AVR_LEAVE_CRITICAL_REGION( );
00346 }
00347 
00356 uint8_t hal_get_pll_unlock_flag( void ){
00357     return hal_pll_unlock_flag;
00358 }
00359 
00364 void hal_clear_pll_unlock_flag( void ){
00365     
00366     AVR_ENTER_CRITICAL_REGION( );
00367     hal_pll_unlock_flag = 0;
00368     AVR_LEAVE_CRITICAL_REGION( );
00369 }
00370 
00379 uint8_t hal_get_pll_lock_flag( void ){
00380     return hal_pll_lock_flag;
00381 }
00382 
00387 void hal_clear_pll_lock_flag( void ){
00388     
00389     AVR_ENTER_CRITICAL_REGION( );
00390     hal_pll_lock_flag = 0;
00391     AVR_LEAVE_CRITICAL_REGION( );
00392 }
00393 
00405 uint8_t hal_register_read( uint8_t address ){
00406     
00407     //Add the register read command to the register address.
00408     address &= HAL_TRX_CMD_RADDRM;
00409     address |= HAL_TRX_CMD_RR;
00410     
00411     AVR_ENTER_CRITICAL_REGION( );
00412     
00413     HAL_SS_LOW( ); //Start the SPI transaction by pulling the Slave Select low.
00414     
00415     /*Send Register address and read register content.*/
00416     SPDR = address;
00417     while ((SPSR & (1 << SPIF)) == 0) {;}
00418     uint8_t register_value = SPDR;
00419     
00420     SPDR = HAL_DUMMY_READ;
00421     while ((SPSR & (1 << SPIF)) == 0) {;}
00422     register_value = SPDR;
00423 
00424     HAL_SS_HIGH( ); //End the transaction by pulling the Slave Select High.  
00425     
00426     AVR_LEAVE_CRITICAL_REGION( );
00427     
00428     return register_value;
00429 }
00430 
00441 void hal_register_write( uint8_t address, uint8_t value ){
00442                                        
00443     //Add the Register Write command to the address.
00444     address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address);
00445     
00446     AVR_ENTER_CRITICAL_REGION( );    
00447     
00448     HAL_SS_LOW( ); //Start the SPI transaction by pulling the Slave Select low.
00449     
00450     /*Send Register address and write register content.*/
00451     SPDR = address;
00452     while ((SPSR & (1 << SPIF)) == 0) {;}
00453     uint8_t dummy_read = SPDR;
00454     
00455     SPDR = value;
00456     while ((SPSR & (1 << SPIF)) == 0) {;}
00457     dummy_read = SPDR;
00458     
00459     HAL_SS_HIGH( ); //End the transaction by pulling the Slave Slect High.
00460     
00461     AVR_LEAVE_CRITICAL_REGION( );
00462 }
00463 
00476 uint8_t hal_subregister_read( uint8_t address, uint8_t mask, uint8_t position ){
00477     
00478     //Read current register value and mask out subregister.
00479     uint8_t register_value = hal_register_read( address );
00480     register_value &= mask;
00481     register_value >>= position; //Align subregister value.
00482     
00483     return register_value;
00484 }
00485 
00499 void hal_subregister_write( uint8_t address, uint8_t mask, uint8_t position, 
00500                             uint8_t value ){
00501     
00502     //Read current register value and mask area outside the subregister.
00503     uint8_t register_value = hal_register_read( address );
00504     register_value &= ~mask;
00505     
00506     //Start preparing the new subregister value. shift in place and mask.
00507     value <<= position;
00508     value &= mask;
00509     
00510     value |= register_value; //Set the new subregister value.
00511 
00512     //Write the modified register value.
00513     hal_register_write( address, value );
00514 }
00515 
00527 __z void hal_frame_read( hal_rx_frame_t *rx_frame ){
00528     
00529     AVR_ENTER_CRITICAL_REGION( );
00530     
00531     HAL_SS_LOW( );
00532     
00533     /*Send frame read command.*/
00534     SPDR = HAL_TRX_CMD_FR;
00535     while ((SPSR & (1 << SPIF)) == 0) {;}
00536     uint8_t frame_length = SPDR;
00537     
00538     /*Read frame length.*/    
00539     SPDR = HAL_DUMMY_READ;
00540     while ((SPSR & (1 << SPIF)) == 0) {;}
00541     frame_length = SPDR;
00542     
00543     /*Check for correct frame length.*/
00544     if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)) {
00545         
00546         /*Initialize some local variables.*/
00547         uint16_t crc = 0;
00548         uint8_t *rx_data = (rx_frame->data);
00549         
00550         rx_frame->length = frame_length; //Store frame length.
00551         
00552         /*Upload frame buffer to data pointer. Calculate CRC.*/
00553         do {
00554             
00555             SPDR = HAL_DUMMY_READ;
00556             while ((SPSR & (1 << SPIF)) == 0) {;}
00557             *rx_data = SPDR;
00558             crc = crc_ccitt_update( crc, *rx_data++ );
00559         } while (--frame_length > 0);
00560         
00561         /*Read LQI value for this frame.*/
00562         SPDR = HAL_DUMMY_READ;
00563         while ((SPSR & (1 << SPIF)) == 0) {;}
00564         rx_frame->lqi = SPDR;
00565         
00566         HAL_SS_HIGH( );
00567         
00568         /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/
00569         if (crc == HAL_CALCULATED_CRC_OK) { 
00570             rx_frame->crc = true; 
00571         } else { rx_frame->crc = false; }
00572     } else {
00573         
00574         rx_frame->length = 0;
00575         rx_frame->lqi    = 0;
00576         rx_frame->crc    = false;
00577         
00578         HAL_SS_HIGH( );    
00579     }
00580     
00581     AVR_LEAVE_CRITICAL_REGION( );
00582 }
00583 
00592 __z void hal_frame_write( uint8_t *write_buffer, uint8_t length ){
00593     
00594     length &= HAL_TRX_CMD_RADDRM; //Truncate length to maximum frame length.
00595     
00596     AVR_ENTER_CRITICAL_REGION( );
00597     
00598     HAL_SS_LOW( ); //Initiate the SPI transaction.
00599     
00600     /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/
00601     SPDR = HAL_TRX_CMD_FW;
00602     while ((SPSR & (1 << SPIF)) == 0) {;}
00603     uint8_t dummy_read = SPDR;
00604         
00605     SPDR = length;
00606     while ((SPSR & (1 << SPIF)) == 0) {;}
00607     dummy_read = SPDR;
00608     
00609     //Download to the Frame Buffer.
00610     do {
00611         
00612         SPDR = *write_buffer++;
00613         while ((SPSR & (1 << SPIF)) == 0) {;}
00614         dummy_read = SPDR;
00615     } while (--length > 0);
00616     
00617     HAL_SS_HIGH( ); //Terminate SPI transaction.
00618     
00619     AVR_LEAVE_CRITICAL_REGION( );
00620 }
00621 
00632 __z void hal_sram_read( uint8_t address, uint8_t length, uint8_t *data ){
00633     
00634     AVR_ENTER_CRITICAL_REGION( );
00635     
00636     HAL_SS_LOW( ); //Initiate the SPI transaction.
00637     
00638     /*Send SRAM read command.*/
00639     SPDR = HAL_TRX_CMD_SR;
00640     while ((SPSR & (1 << SPIF)) == 0) {;}
00641     uint8_t dummy_read = SPDR;
00642     
00643     /*Send address where to start reading.*/    
00644     SPDR = address;
00645     while ((SPSR & (1 << SPIF)) == 0) {;}
00646     dummy_read = SPDR;
00647     
00648     /*Upload the chosen memory area.*/
00649     do {
00650         
00651         SPDR = HAL_DUMMY_READ;
00652         while ((SPSR & (1 << SPIF)) == 0) {;}
00653         *data++ = SPDR;
00654     } while (--length > 0);
00655 
00656     HAL_SS_HIGH( );
00657     
00658     AVR_LEAVE_CRITICAL_REGION( );
00659 }
00660 
00671 __z void hal_sram_write( uint8_t address, uint8_t length, uint8_t *data ){
00672     
00673     AVR_ENTER_CRITICAL_REGION( );
00674         
00675     HAL_SS_LOW( );
00676     
00677     /*Send SRAM write command.*/
00678     SPDR = HAL_TRX_CMD_SW;
00679     while ((SPSR & (1 << SPIF)) == 0) {;}
00680     uint8_t dummy_read = SPDR;
00681     
00682     /*Send address where to start writing to.*/
00683     SPDR = address;
00684     while ((SPSR & (1 << SPIF)) == 0) {;}
00685     dummy_read = SPDR;
00686     
00687     /*Upload the chosen memory area.*/
00688     do {
00689         
00690         SPDR = *data++;
00691         while ((SPSR & (1 << SPIF)) == 0) {;}
00692         dummy_read = SPDR;
00693     } while (--length > 0);
00694     
00695     HAL_SS_HIGH( );
00696     
00697     AVR_LEAVE_CRITICAL_REGION( );
00698 }
00699 
00707 uint32_t hal_get_system_time( void ){
00708     
00709     uint32_t system_time = hal_system_time; //Read current system time (MSB).
00710     system_time <<= 16;
00711     
00712     /*Disable interrupts. This is done since the TCNT1 value should not 
00713       be read when the timer is running.*/
00714     AVR_ENTER_CRITICAL_REGION( );
00715     
00716     system_time |= TCNT1; //Add 16 LSB. 
00717     
00718     AVR_LEAVE_CRITICAL_REGION( );
00719     
00720     //Return the system time in symbols.
00721     return ((system_time / HAL_US_PER_SYMBOL) & HAL_SYMBOL_MASK);
00722 }
00723 
00724 //This #if compile switch is used to provide a "standard" function body for the 
00725 //doxygen documentation.
00726 #if defined( DOXYGEN )
00727 
00731 void TIMER1_CAPT_vect( void );
00732 #else  /* !DOXYGEN */
00733 ISR( TIMER1_CAPT_vect ){
00734     
00735     /*Read current system time so that RX_START and TRX_END interrupts can be timestamped.*/
00736     uint32_t isr_timestamp = hal_system_time; //Read 16 MSB.
00737     isr_timestamp <<= 16; //Shift in place.
00738     isr_timestamp |= TCNT1; //Add 16 LSB. 
00739     isr_timestamp /= HAL_US_PER_SYMBOL; //Divide so that we get time in 16us resolution.
00740     isr_timestamp &= HAL_SYMBOL_MASK;
00741     
00742     /*Read Interrupt source.*/
00743     HAL_SS_LOW( );
00744     
00745     /*Send Register address and read register content.*/
00746     SPDR = RG_IRQ_STATUS | HAL_TRX_CMD_RR;
00747     while ((SPSR & (1 << SPIF)) == 0) {;}
00748     uint8_t register_value = SPDR;
00749     
00750     SPDR = HAL_DUMMY_READ;
00751     while ((SPSR & (1 << SPIF)) == 0) {;}
00752     uint8_t interrupt_source = SPDR;
00753 
00754     HAL_SS_HIGH( );
00755     
00756     /*Handle the incomming interrupt.*/
00757     if ((interrupt_source & HAL_RX_START_MASK)) {
00758         
00759         hal_rx_start_flag++; //Increment RX_START flag.
00760         
00761         if( rx_start_callback != NULL ){
00762             
00763             /*Read Frame length and call rx_start callback.*/
00764             HAL_SS_LOW( );
00765     
00766             SPDR = HAL_TRX_CMD_FR;
00767             while ((SPSR & (1 << SPIF)) == 0) {;}
00768             uint8_t dummy_read = SPDR;
00769         
00770             SPDR = HAL_DUMMY_READ;
00771             while ((SPSR & (1 << SPIF)) == 0) {;}
00772             uint8_t frame_length = SPDR;
00773             
00774             HAL_SS_HIGH( );
00775                     
00776             rx_start_callback( isr_timestamp, frame_length );
00777         }
00778     } else if (interrupt_source & HAL_TRX_END_MASK) {
00779         
00780         hal_trx_end_flag++; //Increment TRX_END flag.
00781         
00782         if( trx_end_callback != NULL ){
00783             
00784             /*Read Frame length and call rx_start callback.*/
00785             HAL_SS_LOW( );
00786     
00787             SPDR = HAL_TRX_CMD_FR;
00788             while ((SPSR & (1 << SPIF)) == 0) {;}
00789             uint8_t dummy_read = SPDR;
00790         
00791             SPDR = HAL_DUMMY_READ;
00792             while ((SPSR & (1 << SPIF)) == 0) {;}
00793             uint8_t frame_length = SPDR;
00794             
00795             HAL_SS_HIGH( );
00796             
00797             trx_end_callback( isr_timestamp, frame_length );
00798         }
00799     } else if (interrupt_source & HAL_TRX_UR_MASK) {
00800         hal_trx_ur_flag++; //Increment TRX_UR flag.    
00801     } else if (interrupt_source & HAL_PLL_UNLOCK_MASK) {
00802         hal_pll_unlock_flag++; //Increment PLL_UNLOCK flag.   
00803     } else if (interrupt_source & HAL_PLL_LOCK_MASK) {
00804         hal_pll_lock_flag++; //Increment PLL_LOCK flag.
00805     } else if (interrupt_source & HAL_BAT_LOW_MASK) {
00806 
00807         //Disable BAT_LOW interrupt to prevent interrupt storm. The interrupt 
00808         //will continously be signaled when the supply voltage is less than the 
00809         //user defined voltage threshold.
00810         uint8_t trx_isr_mask = hal_register_read( RG_IRQ_MASK );
00811         trx_isr_mask &= ~HAL_BAT_LOW_MASK;
00812         hal_register_write( RG_IRQ_MASK, trx_isr_mask );
00813         hal_bat_low_flag++; //Increment BAT_LOW flag.
00814     } else {
00815         hal_unknown_isr_flag++;  //Increment UNKNOWN_ISR flag.
00816     } 
00817 }
00818 #   endif /* defined(DOXYGEN) */
00819 
00820 //This #if compile switch is used to provide a "standard" function body for the 
00821 //doxygen documentation.
00822 #if defined( DOXYGEN )
00823 
00826 void TIMER1_OVF_vect( void );
00827 #else  /* !DOXYGEN */
00828 ISR( TIMER1_OVF_vect ){
00829     hal_system_time++;
00830 }
00831 #endif
00832 /*EOF*/
@DOC_TITLE@
Generated on Wed Jul 11 18:16:31 2007 for AVR2001 AT86RF230 Software Programmer's Manual by doxygen 1.4.7