00001 /* Copyright (c) 2008, Swedish Institute of Computer Science 00002 * All rights reserved. 00003 * 00004 * Additional fixes for AVR contributed by: 00005 * 00006 * Colin O'Flynn coflynn@newae.com 00007 * Eric Gnoske egnoske@gmail.com 00008 * Blake Leverett bleverett@gmail.com 00009 * Mike Vidales mavida404@gmail.com 00010 * Kevin Brown kbrown3@uccs.edu 00011 * Nate Bohlmann nate@elfwerks.com 00012 * 00013 * All rights reserved. 00014 * 00015 * Redistribution and use in source and binary forms, with or without 00016 * modification, are permitted provided that the following conditions are met: 00017 * 00018 * * Redistributions of source code must retain the above copyright 00019 * notice, this list of conditions and the following disclaimer. 00020 * * Redistributions in binary form must reproduce the above copyright 00021 * notice, this list of conditions and the following disclaimer in 00022 * the documentation and/or other materials provided with the 00023 * distribution. 00024 * * Neither the name of the copyright holders nor the names of 00025 * contributors may be used to endorse or promote products derived 00026 * from this software without specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00029 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00030 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00031 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00032 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00033 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00034 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00035 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00036 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00037 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 * 00040 * $Id: hal.c,v 1.2 2008/10/14 18:37:28 c_oflynn Exp $ 00041 */ 00042 00043 /** 00044 * \addtogroup wireless 00045 * @{ 00046 */ 00047 00048 /** 00049 * \defgroup hal RF230 hardware level drivers 00050 * @{ 00051 */ 00052 00053 /** 00054 * \file 00055 * This file contains low-level radio driver code. 00056 */ 00057 00058 00059 00060 /*============================ INCLUDE =======================================*/ 00061 #include <stdlib.h> 00062 00063 #include "hal.h" 00064 #include "at86rf230_registermap.h" 00065 /*============================ MACROS ========================================*/ 00066 00067 /* 00068 * Macros defined for the radio transceiver's access modes. 00069 * 00070 * These functions are implemented as macros since they are used very often. 00071 */ 00072 #define HAL_DUMMY_READ (0x00) /**< Dummy value for the SPI. */ 00073 00074 #define HAL_TRX_CMD_RW (0xC0) /**< Register Write (short mode). */ 00075 #define HAL_TRX_CMD_RR (0x80) /**< Register Read (short mode). */ 00076 #define HAL_TRX_CMD_FW (0x60) /**< Frame Transmit Mode (long mode). */ 00077 #define HAL_TRX_CMD_FR (0x20) /**< Frame Receive Mode (long mode). */ 00078 #define HAL_TRX_CMD_SW (0x40) /**< SRAM Write. */ 00079 #define HAL_TRX_CMD_SR (0x00) /**< SRAM Read. */ 00080 #define HAL_TRX_CMD_RADDRM (0x7F) /**< Register Address Mask. */ 00081 00082 #define HAL_CALCULATED_CRC_OK (0) /**< CRC calculated over the frame including the CRC field should be 0. */ 00083 /*============================ TYPDEFS =======================================*/ 00084 /*============================ VARIABLES =====================================*/ 00085 /** \brief This is a file internal variable that contains the 16 MSB of the 00086 * system time. 00087 * 00088 * The system time (32-bit) is the current time in microseconds. For the 00089 * AVR microcontroller implementation this is solved by using a 16-bit 00090 * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is 00091 * incremented when the 16-bit timer overflows, representing the 16 MSB. 00092 * The timer value it self (TCNT1) is then the 16 LSB. 00093 * 00094 * \see hal_get_system_time 00095 */ 00096 static uint16_t hal_system_time = 0; 00097 00098 /*Flag section.*/ 00099 static uint8_t volatile hal_bat_low_flag; /**< BAT_LOW flag. */ 00100 static uint8_t volatile hal_pll_lock_flag; /**< PLL_LOCK flag. */ 00101 00102 /*Callbacks.*/ 00103 00104 /** \brief This function is called when a rx_start interrupt is signaled. 00105 * 00106 * If this function pointer is set to something else than NULL, it will 00107 * be called when a RX_START event is signaled. The function takes two 00108 * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and 00109 * frame length. The event handler will be called in the interrupt domain, 00110 * so the function must be kept short and not be blocking! Otherwise the 00111 * system performance will be greatly degraded. 00112 * 00113 * \see hal_set_rx_start_event_handler 00114 */ 00115 static hal_rx_start_isr_event_handler_t rx_start_callback; 00116 00117 /** \brief This function is called when a trx_end interrupt is signaled. 00118 * 00119 * If this function pointer is set to something else than NULL, it will 00120 * be called when a TRX_END event is signaled. The function takes one 00121 * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution). 00122 * The event handler will be called in the interrupt domain, 00123 * so the function must not block! 00124 * 00125 * \see hal_set_trx_end_event_handler 00126 */ 00127 static hal_trx_end_isr_event_handler_t trx_end_callback; 00128 /*============================ PROTOTYPES ====================================*/ 00129 /*============================ IMPLEMENTATION ================================*/ 00130 00131 /** \brief This function initializes the Hardware Abstraction Layer. 00132 */ 00133 void 00134 hal_init(void) 00135 { 00136 /*Reset variables used in file.*/ 00137 hal_system_time = 0; 00138 hal_reset_flags(); 00139 00140 /*IO Specific Initialization.*/ 00141 DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */ 00142 DDR_RST |= (1 << RST); /* Enable RST as output. */ 00143 00144 /*SPI Specific Initialization.*/ 00145 /* Set SS, CLK and MOSI as output. */ 00146 HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI); 00147 HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */ 00148 /* Run SPI at max speed */ 00149 SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */ 00150 SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */ 00151 00152 /*TIMER1 Specific Initialization.*/ 00153 TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */ 00154 TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */ 00155 HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */ 00156 hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */ 00157 } 00158 00159 /*----------------------------------------------------------------------------*/ 00160 /** \brief This function reset the interrupt flags and interrupt event handlers 00161 * (Callbacks) to their default value. 00162 */ 00163 void 00164 hal_reset_flags(void) 00165 { 00166 AVR_ENTER_CRITICAL_REGION(); 00167 00168 /* Reset Flags. */ 00169 hal_bat_low_flag = 0; 00170 hal_pll_lock_flag = 0; 00171 00172 /* Reset Associated Event Handlers. */ 00173 rx_start_callback = NULL; 00174 trx_end_callback = NULL; 00175 00176 AVR_LEAVE_CRITICAL_REGION(); 00177 } 00178 00179 /*----------------------------------------------------------------------------*/ 00180 /** \brief This function returns the current value of the BAT_LOW flag. 00181 * 00182 * The BAT_LOW flag is incremented each time a BAT_LOW event is signaled from the 00183 * radio transceiver. This way it is possible for the end user to poll the flag 00184 * for new event occurances. 00185 */ 00186 uint8_t 00187 hal_get_bat_low_flag(void) 00188 { 00189 return hal_bat_low_flag; 00190 } 00191 00192 /*----------------------------------------------------------------------------*/ 00193 /** \brief This function clears the BAT_LOW flag. 00194 */ 00195 void 00196 hal_clear_bat_low_flag(void) 00197 { 00198 AVR_ENTER_CRITICAL_REGION(); 00199 hal_bat_low_flag = 0; 00200 AVR_LEAVE_CRITICAL_REGION(); 00201 } 00202 00203 /*----------------------------------------------------------------------------*/ 00204 /** \brief This function is used to set new TRX_END event handler, overriding 00205 * old handler reference. 00206 */ 00207 hal_trx_end_isr_event_handler_t 00208 hal_get_trx_end_event_handler(void) 00209 { 00210 return trx_end_callback; 00211 } 00212 00213 /*----------------------------------------------------------------------------*/ 00214 /** \brief This function is used to set new TRX_END event handler, overriding 00215 * old handler reference. 00216 */ 00217 void 00218 hal_set_trx_end_event_handler(hal_trx_end_isr_event_handler_t trx_end_callback_handle) 00219 { 00220 AVR_ENTER_CRITICAL_REGION(); 00221 trx_end_callback = trx_end_callback_handle; 00222 AVR_LEAVE_CRITICAL_REGION(); 00223 } 00224 00225 /*----------------------------------------------------------------------------*/ 00226 /** \brief Remove event handler reference. 00227 */ 00228 void 00229 hal_clear_trx_end_event_handler(void) 00230 { 00231 AVR_ENTER_CRITICAL_REGION(); 00232 trx_end_callback = NULL; 00233 AVR_LEAVE_CRITICAL_REGION(); 00234 } 00235 00236 /*----------------------------------------------------------------------------*/ 00237 /** \brief This function returns the active RX_START event handler 00238 * 00239 * \return Current RX_START event handler registered. 00240 */ 00241 hal_rx_start_isr_event_handler_t 00242 hal_get_rx_start_event_handler(void) 00243 { 00244 return rx_start_callback; 00245 } 00246 00247 /*----------------------------------------------------------------------------*/ 00248 /** \brief This function is used to set new RX_START event handler, overriding 00249 * old handler reference. 00250 */ 00251 void 00252 hal_set_rx_start_event_handler(hal_rx_start_isr_event_handler_t rx_start_callback_handle) 00253 { 00254 AVR_ENTER_CRITICAL_REGION(); 00255 rx_start_callback = rx_start_callback_handle; 00256 AVR_LEAVE_CRITICAL_REGION(); 00257 } 00258 00259 /*----------------------------------------------------------------------------*/ 00260 /** \brief Remove event handler reference. 00261 */ 00262 void 00263 hal_clear_rx_start_event_handler(void) 00264 { 00265 AVR_ENTER_CRITICAL_REGION(); 00266 rx_start_callback = NULL; 00267 AVR_LEAVE_CRITICAL_REGION(); 00268 } 00269 00270 /*----------------------------------------------------------------------------*/ 00271 /** \brief This function returns the current value of the PLL_LOCK flag. 00272 * 00273 * The PLL_LOCK flag is incremented each time a PLL_LOCK event is signaled from the 00274 * radio transceiver. This way it is possible for the end user to poll the flag 00275 * for new event occurances. 00276 */ 00277 uint8_t 00278 hal_get_pll_lock_flag(void) 00279 { 00280 return hal_pll_lock_flag; 00281 } 00282 00283 /*----------------------------------------------------------------------------*/ 00284 /** \brief This function clears the PLL_LOCK flag. 00285 */ 00286 void 00287 hal_clear_pll_lock_flag(void) 00288 { 00289 AVR_ENTER_CRITICAL_REGION(); 00290 hal_pll_lock_flag = 0; 00291 AVR_LEAVE_CRITICAL_REGION(); 00292 } 00293 00294 /*----------------------------------------------------------------------------*/ 00295 /** \brief This function reads data from one of the radio transceiver's registers. 00296 * 00297 * \param address Register address to read from. See datasheet for register 00298 * map. 00299 * 00300 * \see Look at the at86rf230_registermap.h file for register address definitions. 00301 * 00302 * \returns The actual value of the read register. 00303 */ 00304 uint8_t 00305 hal_register_read(uint8_t address) 00306 { 00307 /* Add the register read command to the register address. */ 00308 address &= HAL_TRX_CMD_RADDRM; 00309 address |= HAL_TRX_CMD_RR; 00310 00311 uint8_t register_value = 0; 00312 00313 AVR_ENTER_CRITICAL_REGION(); 00314 00315 HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ 00316 00317 /*Send Register address and read register content.*/ 00318 SPDR = address; 00319 while ((SPSR & (1 << SPIF)) == 0) {;} 00320 register_value = SPDR; 00321 00322 SPDR = register_value; 00323 while ((SPSR & (1 << SPIF)) == 0) {;} 00324 register_value = SPDR; 00325 00326 HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ 00327 00328 AVR_LEAVE_CRITICAL_REGION(); 00329 00330 return register_value; 00331 } 00332 00333 /*----------------------------------------------------------------------------*/ 00334 /** \brief This function writes a new value to one of the radio transceiver's 00335 * registers. 00336 * 00337 * \see Look at the at86rf230_registermap.h file for register address definitions. 00338 * 00339 * \param address Address of register to write. 00340 * \param value Value to write. 00341 */ 00342 void 00343 hal_register_write(uint8_t address, uint8_t value) 00344 { 00345 /* Add the Register Write command to the address. */ 00346 address = HAL_TRX_CMD_RW | (HAL_TRX_CMD_RADDRM & address); 00347 00348 AVR_ENTER_CRITICAL_REGION(); 00349 00350 HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ 00351 00352 /*Send Register address and write register content.*/ 00353 SPDR = address; 00354 while ((SPSR & (1 << SPIF)) == 0) {;} 00355 uint8_t dummy_read = SPDR; 00356 00357 SPDR = value; 00358 while ((SPSR & (1 << SPIF)) == 0) {;} 00359 dummy_read = SPDR; 00360 00361 HAL_SS_HIGH(); /* End the transaction by pulling the Slave Slect High. */ 00362 00363 AVR_LEAVE_CRITICAL_REGION(); 00364 } 00365 00366 /*----------------------------------------------------------------------------*/ 00367 /** \brief This function reads the value of a specific subregister. 00368 * 00369 * \see Look at the at86rf230_registermap.h file for register and subregister 00370 * definitions. 00371 * 00372 * \param address Main register's address. 00373 * \param mask Bit mask of the subregister. 00374 * \param position Bit position of the subregister 00375 * \retval Value of the read subregister. 00376 */ 00377 uint8_t 00378 hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position) 00379 { 00380 /* Read current register value and mask out subregister. */ 00381 uint8_t register_value = hal_register_read(address); 00382 register_value &= mask; 00383 register_value >>= position; /* Align subregister value. */ 00384 00385 return register_value; 00386 } 00387 00388 /*----------------------------------------------------------------------------*/ 00389 /** \brief This function writes a new value to one of the radio transceiver's 00390 * subregisters. 00391 * 00392 * \see Look at the at86rf230_registermap.h file for register and subregister 00393 * definitions. 00394 * 00395 * \param address Main register's address. 00396 * \param mask Bit mask of the subregister. 00397 * \param position Bit position of the subregister 00398 * \param value Value to write into the subregister. 00399 */ 00400 void 00401 hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, 00402 uint8_t value) 00403 { 00404 /* Read current register value and mask area outside the subregister. */ 00405 uint8_t register_value = hal_register_read(address); 00406 register_value &= ~mask; 00407 00408 /* Start preparing the new subregister value. shift in place and mask. */ 00409 value <<= position; 00410 value &= mask; 00411 00412 value |= register_value; /* Set the new subregister value. */ 00413 00414 /* Write the modified register value. */ 00415 hal_register_write(address, value); 00416 } 00417 00418 /*----------------------------------------------------------------------------*/ 00419 /** \brief This function will upload a frame from the radio transceiver's frame 00420 * buffer. 00421 * 00422 * If the frame currently available in the radio transceiver's frame buffer 00423 * is out of the defined bounds. Then the frame length, lqi value and crc 00424 * be set to zero. This is done to indicate an error. 00425 * 00426 * \param rx_frame Pointer to the data structure where the frame is stored. 00427 * \param rx_callback Pointer to callback function for receiving one byte at a time. 00428 */ 00429 void 00430 hal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback) 00431 { 00432 uint8_t *rx_data=0; 00433 00434 /* check that we have either valid frame pointer or callback pointer */ 00435 if (!rx_frame && !rx_callback) 00436 return; 00437 00438 AVR_ENTER_CRITICAL_REGION(); 00439 00440 HAL_SS_LOW(); 00441 00442 /*Send frame read command.*/ 00443 SPDR = HAL_TRX_CMD_FR; 00444 while ((SPSR & (1 << SPIF)) == 0) {;} 00445 uint8_t frame_length = SPDR; 00446 00447 /*Read frame length.*/ 00448 SPDR = frame_length; 00449 while ((SPSR & (1 << SPIF)) == 0) {;} 00450 frame_length = SPDR; 00451 00452 /*Check for correct frame length.*/ 00453 if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){ 00454 uint16_t crc = 0; 00455 if (rx_frame){ 00456 rx_data = (rx_frame->data); 00457 rx_frame->length = frame_length; /* Store frame length. */ 00458 } else { 00459 rx_callback(frame_length); 00460 } 00461 /*Upload frame buffer to data pointer. Calculate CRC.*/ 00462 SPDR = frame_length; 00463 while ((SPSR & (1 << SPIF)) == 0) {;} 00464 00465 do{ 00466 uint8_t tempData = SPDR; 00467 SPDR = 0; /* dummy write */ 00468 00469 if (rx_frame){ 00470 *rx_data++ = tempData; 00471 } else { 00472 rx_callback(tempData); 00473 } 00474 00475 crc = _crc_ccitt_update(crc, tempData); 00476 00477 while ((SPSR & (1 << SPIF)) == 0) {;} 00478 00479 } while (--frame_length > 0); 00480 00481 /*Read LQI value for this frame.*/ 00482 if (rx_frame){ 00483 rx_frame->lqi = SPDR; 00484 } else { 00485 rx_callback(SPDR); 00486 } 00487 00488 HAL_SS_HIGH(); 00489 00490 /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/ 00491 if (rx_frame){ 00492 rx_frame->crc = (crc == HAL_CALCULATED_CRC_OK); 00493 } else { 00494 rx_callback(crc != HAL_CALCULATED_CRC_OK); 00495 } 00496 } else { 00497 HAL_SS_HIGH(); 00498 00499 if (rx_frame){ 00500 rx_frame->length = 0; 00501 rx_frame->lqi = 0; 00502 rx_frame->crc = false; 00503 } 00504 } 00505 00506 AVR_LEAVE_CRITICAL_REGION(); 00507 } 00508 00509 /*----------------------------------------------------------------------------*/ 00510 /** \brief This function will download a frame to the radio transceiver's frame 00511 * buffer. 00512 * 00513 * \param write_buffer Pointer to data that is to be written to frame buffer. 00514 * \param length Length of data. The maximum length is 127 bytes. 00515 */ 00516 void 00517 hal_frame_write(uint8_t *write_buffer, uint8_t length) 00518 { 00519 length &= HAL_TRX_CMD_RADDRM; /* Truncate length to maximum frame length. */ 00520 00521 AVR_ENTER_CRITICAL_REGION(); 00522 00523 HAL_SS_LOW(); /* Initiate the SPI transaction. */ 00524 00525 /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/ 00526 SPDR = HAL_TRX_CMD_FW; 00527 while ((SPSR & (1 << SPIF)) == 0) {;} 00528 uint8_t dummy_read = SPDR; 00529 00530 SPDR = length; 00531 while ((SPSR & (1 << SPIF)) == 0) {;} 00532 dummy_read = SPDR; 00533 00534 /* Download to the Frame Buffer. */ 00535 do{ 00536 SPDR = *write_buffer++; 00537 --length; 00538 00539 while ((SPSR & (1 << SPIF)) == 0) {;} 00540 00541 dummy_read = SPDR; 00542 } while (length > 0); 00543 00544 HAL_SS_HIGH(); /* Terminate SPI transaction. */ 00545 00546 AVR_LEAVE_CRITICAL_REGION(); 00547 } 00548 00549 /*----------------------------------------------------------------------------*/ 00550 /** \brief Read SRAM 00551 * 00552 * This function reads from the SRAM of the radio transceiver. 00553 * 00554 * \param address Address in the TRX's SRAM where the read burst should start 00555 * \param length Length of the read burst 00556 * \param data Pointer to buffer where data is stored. 00557 */ 00558 void 00559 hal_sram_read(uint8_t address, uint8_t length, uint8_t *data) 00560 { 00561 AVR_ENTER_CRITICAL_REGION(); 00562 00563 HAL_SS_LOW(); /* Initiate the SPI transaction. */ 00564 00565 /*Send SRAM read command.*/ 00566 SPDR = HAL_TRX_CMD_SR; 00567 while ((SPSR & (1 << SPIF)) == 0) {;} 00568 uint8_t dummy_read = SPDR; 00569 00570 /*Send address where to start reading.*/ 00571 SPDR = address; 00572 while ((SPSR & (1 << SPIF)) == 0) {;} 00573 00574 dummy_read = SPDR; 00575 00576 /*Upload the chosen memory area.*/ 00577 do{ 00578 SPDR = HAL_DUMMY_READ; 00579 while ((SPSR & (1 << SPIF)) == 0) {;} 00580 *data++ = SPDR; 00581 } while (--length > 0); 00582 00583 HAL_SS_HIGH(); 00584 00585 AVR_LEAVE_CRITICAL_REGION(); 00586 } 00587 00588 /*----------------------------------------------------------------------------*/ 00589 /** \brief Write SRAM 00590 * 00591 * This function writes into the SRAM of the radio transceiver. 00592 * 00593 * \param address Address in the TRX's SRAM where the write burst should start 00594 * \param length Length of the write burst 00595 * \param data Pointer to an array of bytes that should be written 00596 */ 00597 void 00598 hal_sram_write(uint8_t address, uint8_t length, uint8_t *data) 00599 { 00600 AVR_ENTER_CRITICAL_REGION(); 00601 00602 HAL_SS_LOW(); 00603 00604 /*Send SRAM write command.*/ 00605 SPDR = HAL_TRX_CMD_SW; 00606 while ((SPSR & (1 << SPIF)) == 0) {;} 00607 uint8_t dummy_read = SPDR; 00608 00609 /*Send address where to start writing to.*/ 00610 SPDR = address; 00611 while ((SPSR & (1 << SPIF)) == 0) {;} 00612 dummy_read = SPDR; 00613 00614 /*Upload the chosen memory area.*/ 00615 do{ 00616 SPDR = *data++; 00617 while ((SPSR & (1 << SPIF)) == 0) {;} 00618 dummy_read = SPDR; 00619 } while (--length > 0); 00620 00621 HAL_SS_HIGH(); 00622 00623 AVR_LEAVE_CRITICAL_REGION(); 00624 } 00625 00626 /*----------------------------------------------------------------------------*/ 00627 /* This #if compile switch is used to provide a "standard" function body for the */ 00628 /* doxygen documentation. */ 00629 #if defined(DOXYGEN) 00630 /** \brief ISR for the radio IRQ line, triggered by the input capture. 00631 * This is the interrupt service routine for timer1.ICIE1 input capture. 00632 * It is triggered of a rising edge on the radio transceivers IRQ line. 00633 */ 00634 void RADIO_VECT(void); 00635 #else /* !DOXYGEN */ 00636 ISR(RADIO_VECT) 00637 { 00638 /*The following code reads the current system time. This is done by first 00639 reading the hal_system_time and then adding the 16 LSB directly from the 00640 TCNT1 register. 00641 */ 00642 uint32_t isr_timestamp = hal_system_time; 00643 isr_timestamp <<= 16; 00644 isr_timestamp |= TCNT1; 00645 00646 /*Read Interrupt source.*/ 00647 HAL_SS_LOW(); 00648 00649 /*Send Register address and read register content.*/ 00650 SPDR = RG_IRQ_STATUS | HAL_TRX_CMD_RR; 00651 00652 /* This is the second part of the convertion of system time to a 16 us time 00653 base. The division is moved here so we can spend less time waiting for SPI 00654 data. 00655 */ 00656 isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */ 00657 isr_timestamp &= HAL_SYMBOL_MASK; 00658 00659 while ((SPSR & (1 << SPIF)) == 0) {;} 00660 uint8_t interrupt_source = SPDR; /* The interrupt variable is used as a dummy read. */ 00661 00662 SPDR = interrupt_source; 00663 while ((SPSR & (1 << SPIF)) == 0) {;} 00664 interrupt_source = SPDR; /* The interrupt source is read. */ 00665 00666 HAL_SS_HIGH(); 00667 00668 /*Handle the incomming interrupt. Prioritized.*/ 00669 if ((interrupt_source & HAL_RX_START_MASK)){ 00670 if(rx_start_callback != NULL){ 00671 /* Read Frame length and call rx_start callback. */ 00672 HAL_SS_LOW(); 00673 00674 SPDR = HAL_TRX_CMD_FR; 00675 while ((SPSR & (1 << SPIF)) == 0) {;} 00676 uint8_t frame_length = SPDR; 00677 00678 SPDR = frame_length; /* frame_length used for dummy data */ 00679 while ((SPSR & (1 << SPIF)) == 0) {;} 00680 frame_length = SPDR; 00681 00682 HAL_SS_HIGH(); 00683 00684 rx_start_callback(isr_timestamp, frame_length); 00685 } 00686 } else if (interrupt_source & HAL_TRX_END_MASK){ 00687 if(trx_end_callback != NULL){ 00688 trx_end_callback(isr_timestamp); 00689 } 00690 } else if (interrupt_source & HAL_TRX_UR_MASK){ 00691 ; 00692 } else if (interrupt_source & HAL_PLL_UNLOCK_MASK){ 00693 ; 00694 } else if (interrupt_source & HAL_PLL_LOCK_MASK){ 00695 hal_pll_lock_flag++; 00696 ; 00697 } else if (interrupt_source & HAL_BAT_LOW_MASK){ 00698 /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */ 00699 /* will continously be asserted while the supply voltage is less than the */ 00700 /* user-defined voltage threshold. */ 00701 uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK); 00702 trx_isr_mask &= ~HAL_BAT_LOW_MASK; 00703 hal_register_write(RG_IRQ_MASK, trx_isr_mask); 00704 hal_bat_low_flag++; /* Increment BAT_LOW flag. */ 00705 } else { 00706 ; 00707 } 00708 } 00709 # endif /* defined(DOXYGEN) */ 00710 00711 /*----------------------------------------------------------------------------*/ 00712 /* This #if compile switch is used to provide a "standard" function body for the */ 00713 /* doxygen documentation. */ 00714 #if defined(DOXYGEN) 00715 /** \brief Timer Overflow ISR 00716 * This is the interrupt service routine for timer1 overflow. 00717 */ 00718 void TIMER1_OVF_vect(void); 00719 #else /* !DOXYGEN */ 00720 ISR(TIMER1_OVF_vect) 00721 { 00722 hal_system_time++; 00723 } 00724 #endif 00725 00726 /** @} */ 00727 /** @} */ 00728 00729 /*EOF*/