Contiki 2.6
|
00001 /* Copyright (c) 2009, 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 * David Kopf dak664@embarqmail.com 00013 * 00014 * All rights reserved. 00015 * 00016 * Redistribution and use in source and binary forms, with or without 00017 * modification, are permitted provided that the following conditions are met: 00018 * 00019 * * Redistributions of source code must retain the above copyright 00020 * notice, this list of conditions and the following disclaimer. 00021 * * Redistributions in binary form must reproduce the above copyright 00022 * notice, this list of conditions and the following disclaimer in 00023 * the documentation and/or other materials provided with the 00024 * distribution. 00025 * * Neither the name of the copyright holders nor the names of 00026 * contributors may be used to endorse or promote products derived 00027 * from this software without specific prior written permission. 00028 * 00029 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00030 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00031 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00032 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00033 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00034 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00035 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00036 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00037 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00038 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00039 * POSSIBILITY OF SUCH DAMAGE. 00040 * 00041 * 00042 */ 00043 00044 /** 00045 * \addtogroup wireless 00046 * @{ 00047 */ 00048 00049 /** 00050 * \defgroup hal RF230 hardware level drivers 00051 * @{ 00052 */ 00053 00054 /** 00055 * \file 00056 * This file contains low-level radio driver code. 00057 * This version is optimized for use with the "barebones" RF230bb driver, 00058 * which communicates directly with the contiki core MAC layer. 00059 * It is optimized for speed at the expense of generality. 00060 */ 00061 #include "contiki-conf.h" 00062 #if DEBUGFLOWSIZE 00063 extern uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE]; 00064 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c 00065 #else 00066 #define DEBUGFLOW(c) 00067 #endif 00068 00069 00070 /*============================ INCLUDE =======================================*/ 00071 #include <stdlib.h> 00072 00073 #include "hal.h" 00074 00075 #if defined(__AVR_ATmega128RFA1__) 00076 #include <avr/io.h> 00077 #include "atmega128rfa1_registermap.h" 00078 #else 00079 #include "at86rf230_registermap.h" 00080 #endif 00081 00082 /*============================ VARIABLES =====================================*/ 00083 /** \brief This is a file internal variable that contains the 16 MSB of the 00084 * system time. 00085 * 00086 * The system time (32-bit) is the current time in microseconds. For the 00087 * AVR microcontroller implementation this is solved by using a 16-bit 00088 * timer (Timer1) with a clock frequency of 1MHz. The hal_system_time is 00089 * incremented when the 16-bit timer overflows, representing the 16 MSB. 00090 * The timer value it self (TCNT1) is then the 16 LSB. 00091 * 00092 * \see hal_get_system_time 00093 */ 00094 static uint16_t hal_system_time = 0; 00095 volatile extern signed char rf230_last_rssi; 00096 00097 //static uint8_t volatile hal_bat_low_flag; 00098 //static uint8_t volatile hal_pll_lock_flag; 00099 00100 /*============================ CALLBACKS =====================================*/ 00101 00102 /** \brief This function is called when a rx_start interrupt is signaled. 00103 * 00104 * If this function pointer is set to something else than NULL, it will 00105 * be called when a RX_START event is signaled. The function takes two 00106 * parameters: timestamp in IEEE 802.15.4 symbols (16 us resolution) and 00107 * frame length. The event handler will be called in the interrupt domain, 00108 * so the function must be kept short and not be blocking! Otherwise the 00109 * system performance will be greatly degraded. 00110 * 00111 * \see hal_set_rx_start_event_handler 00112 */ 00113 //static hal_rx_start_isr_event_handler_t rx_start_callback; 00114 00115 /** \brief This function is called when a trx_end interrupt is signaled. 00116 * 00117 * If this function pointer is set to something else than NULL, it will 00118 * be called when a TRX_END event is signaled. The function takes one 00119 * parameter: timestamp in IEEE 802.15.4 symbols (16 us resolution). 00120 * The event handler will be called in the interrupt domain, 00121 * so the function must not block! 00122 * 00123 * \see hal_set_trx_end_event_handler 00124 */ 00125 //static hal_trx_end_isr_event_handler_t trx_end_callback; 00126 00127 /*============================ IMPLEMENTATION ================================*/ 00128 #if defined(__AVR_ATmega128RFA1__) 00129 //#include <avr/io.h> 00130 #include <avr/interrupt.h> 00131 /* AVR1281 with internal RF231 radio */ 00132 #define HAL_SPI_TRANSFER_OPEN() 00133 //#define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write)) 00134 #define HAL_SPI_TRANSFER_WAIT() 00135 #define HAL_SPI_TRANSFER_READ() (SPDR) 00136 #define HAL_SPI_TRANSFER_CLOSE() 00137 #if 0 00138 #define HAL_SPI_TRANSFER(to_write) ( \ 00139 HAL_SPI_TRANSFER_WRITE(to_write), \ 00140 HAL_SPI_TRANSFER_WAIT(), \ 00141 HAL_SPI_TRANSFER_READ() ) 00142 #endif 00143 #elif defined(__AVR__) 00144 /* 00145 * AVR with hardware SPI tranfers (TODO: move to hw spi hal for avr cpu) 00146 */ 00147 #include <avr/io.h> 00148 #include <avr/interrupt.h> 00149 00150 #define HAL_SPI_TRANSFER_OPEN() { \ 00151 HAL_ENTER_CRITICAL_REGION(); \ 00152 HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ 00153 #define HAL_SPI_TRANSFER_WRITE(to_write) (SPDR = (to_write)) 00154 #define HAL_SPI_TRANSFER_WAIT() ({while ((SPSR & (1 << SPIF)) == 0) {;}}) /* gcc extension, alternative inline function */ 00155 #define HAL_SPI_TRANSFER_READ() (SPDR) 00156 #define HAL_SPI_TRANSFER_CLOSE() \ 00157 HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \ 00158 HAL_LEAVE_CRITICAL_REGION(); \ 00159 } 00160 #define HAL_SPI_TRANSFER(to_write) ( \ 00161 HAL_SPI_TRANSFER_WRITE(to_write), \ 00162 HAL_SPI_TRANSFER_WAIT(), \ 00163 HAL_SPI_TRANSFER_READ() ) 00164 00165 #else /* __AVR__ */ 00166 /* 00167 * Other SPI architecture (parts to core, parts to m16c6Xp 00168 */ 00169 #include "contiki-mulle.h" // MULLE_ENTER_CRITICAL_REGION 00170 00171 // Software SPI transfers 00172 #define HAL_SPI_TRANSFER_OPEN() { uint8_t spiTemp; \ 00173 HAL_ENTER_CRITICAL_REGION(); \ 00174 HAL_SS_LOW(); /* Start the SPI transaction by pulling the Slave Select low. */ 00175 #define HAL_SPI_TRANSFER_WRITE(to_write) (spiTemp = spiWrite(to_write)) 00176 #define HAL_SPI_TRANSFER_WAIT() ({0;}) 00177 #define HAL_SPI_TRANSFER_READ() (spiTemp) 00178 #define HAL_SPI_TRANSFER_CLOSE() \ 00179 HAL_SS_HIGH(); /* End the transaction by pulling the Slave Select High. */ \ 00180 HAL_LEAVE_CRITICAL_REGION(); \ 00181 } 00182 #define HAL_SPI_TRANSFER(to_write) (spiTemp = spiWrite(to_write)) 00183 00184 inline uint8_t spiWrite(uint8_t byte) 00185 { 00186 uint8_t data = 0; 00187 uint8_t mask = 0x80; 00188 do 00189 { 00190 if( (byte & mask) != 0 ) 00191 HAL_PORT_MOSI |= (1 << HAL_MOSI_PIN); //call MOSI.set(); 00192 else 00193 HAL_PORT_MOSI &= ~(1 << HAL_MOSI_PIN); //call MOSI.clr(); 00194 00195 if( (HAL_PORT_MISO & (1 << HAL_MISO_PIN)) > 0) //call MISO.get() ) 00196 data |= mask; 00197 00198 HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); //call SCLK.clr(); 00199 HAL_PORT_SCK |= (1 << HAL_SCK_PIN); //call SCLK.set(); 00200 } while( (mask >>= 1) != 0 ); 00201 return data; 00202 } 00203 00204 #endif /* !__AVR__ */ 00205 00206 /** \brief This function initializes the Hardware Abstraction Layer. 00207 */ 00208 #if defined(__AVR_ATmega128RFA1__) 00209 //#define HAL_RF230_ISR() ISR(RADIO_VECT) 00210 #define HAL_TIME_ISR() ISR(TIMER1_OVF_vect) 00211 #define HAL_TICK_UPCNT() (TCNT1) 00212 void 00213 hal_init(void) 00214 { 00215 /*Reset variables used in file.*/ 00216 hal_system_time = 0; 00217 // TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */ 00218 // TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */ 00219 // HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */ 00220 //hal_enable_trx_interrupt(); /* NOT USED: Enable interrupt pin from the radio transceiver. */ 00221 } 00222 00223 #elif defined(__AVR__) 00224 #define HAL_RF230_ISR() ISR(RADIO_VECT) 00225 #define HAL_TIME_ISR() ISR(TIMER1_OVF_vect) 00226 #define HAL_TICK_UPCNT() (TCNT1) 00227 void 00228 hal_init(void) 00229 { 00230 /*Reset variables used in file.*/ 00231 hal_system_time = 0; 00232 // hal_reset_flags(); 00233 00234 /*IO Specific Initialization - sleep and reset pins. */ 00235 /* Set pins low before they are initialized as output? Does not seem to matter */ 00236 // hal_set_rst_low(); 00237 // hal_set_slptr_low(); 00238 DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */ 00239 DDR_RST |= (1 << RST); /* Enable RST as output. */ 00240 00241 /*SPI Specific Initialization.*/ 00242 /* Set SS, CLK and MOSI as output. */ 00243 /* To avoid a SPI glitch, the port register shall be set before the DDR register */ 00244 HAL_PORT_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK); /* Set SS and CLK high */ 00245 HAL_DDR_SPI |= (1 << HAL_DD_SS) | (1 << HAL_DD_SCK) | (1 << HAL_DD_MOSI); 00246 HAL_DDR_SPI &=~ (1<< HAL_DD_MISO); /* MISO input */ 00247 00248 /* Run SPI at max speed */ 00249 SPCR = (1 << SPE) | (1 << MSTR); /* Enable SPI module and master operation. */ 00250 SPSR = (1 << SPI2X); /* Enable doubled SPI speed in master mode. */ 00251 00252 /*TIMER1 Specific Initialization.*/ 00253 TCCR1B = HAL_TCCR1B_CONFIG; /* Set clock prescaler */ 00254 TIFR1 |= (1 << ICF1); /* Clear Input Capture Flag. */ 00255 HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer1 overflow interrupt. */ 00256 hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */ 00257 } 00258 00259 #else /* __AVR__ */ 00260 00261 #define HAL_RF230_ISR() M16C_INTERRUPT(M16C_INT1) 00262 #define HAL_TIME_ISR() M16C_INTERRUPT(M16C_TMRB4) 00263 #define HAL_TICK_UPCNT() (0xFFFF-TB4) // TB4 counts down so we need to convert it to upcounting 00264 00265 void 00266 hal_init(void) 00267 { 00268 /*Reset variables used in file.*/ 00269 hal_system_time = 0; 00270 // hal_reset_flags(); 00271 00272 /*IO Specific Initialization - sleep and reset pins. */ 00273 DDR_SLP_TR |= (1 << SLP_TR); /* Enable SLP_TR as output. */ 00274 DDR_RST |= (1 << RST); /* Enable RST as output. */ 00275 00276 /*SPI Specific Initialization.*/ 00277 /* Set SS, CLK and MOSI as output. */ 00278 HAL_DDR_SS |= (1 << HAL_SS_PIN); 00279 HAL_DDR_SCK |= (1 << HAL_SCK_PIN); 00280 HAL_DDR_MOSI |= (1 << HAL_MOSI_PIN); 00281 HAL_DDR_MISO &= ~(1 << HAL_MISO_PIN); 00282 00283 /* Set SS */ 00284 HAL_PORT_SS |= (1 << HAL_SS_PIN); // HAL_SS_HIGH() 00285 HAL_PORT_SCK &= ~(1 << HAL_SCK_PIN); // SCLK.clr() 00286 00287 /*TIMER Specific Initialization.*/ 00288 // Init count source (Timer B3) 00289 TB3 = ((16*10) - 1); // 16 us ticks 00290 TB3MR.BYTE = 0b00000000; // Timer mode, F1 00291 TBSR.BIT.TB3S = 1; // Start Timer B3 00292 00293 TB4 = 0xFFFF; // 00294 TB4MR.BYTE = 0b10000001; // Counter mode, count TB3 00295 TBSR.BIT.TB4S = 1; // Start Timer B4 00296 INT1IC.BIT.POL = 1; // Select rising edge 00297 HAL_ENABLE_OVERFLOW_INTERRUPT(); /* Enable Timer overflow interrupt. */ 00298 hal_enable_trx_interrupt(); /* Enable interrupts from the radio transceiver. */ 00299 } 00300 #endif /* !__AVR__ */ 00301 00302 /*----------------------------------------------------------------------------*/ 00303 /** \brief This function reset the interrupt flags and interrupt event handlers 00304 * (Callbacks) to their default value. 00305 */ 00306 //void 00307 //hal_reset_flags(void) 00308 //{ 00309 // HAL_ENTER_CRITICAL_REGION(); 00310 00311 /* Reset Flags. */ 00312 // hal_bat_low_flag = 0; 00313 // hal_pll_lock_flag = 0; 00314 00315 /* Reset Associated Event Handlers. */ 00316 // rx_start_callback = NULL; 00317 // trx_end_callback = NULL; 00318 00319 // HAL_LEAVE_CRITICAL_REGION(); 00320 //} 00321 00322 /*----------------------------------------------------------------------------*/ 00323 /** \brief This function returns the current value of the BAT_LOW flag. 00324 * 00325 * The BAT_LOW flag is incremented each time a BAT_LOW event is signaled from the 00326 * radio transceiver. This way it is possible for the end user to poll the flag 00327 * for new event occurances. 00328 */ 00329 //uint8_t 00330 //hal_get_bat_low_flag(void) 00331 //{ 00332 // return hal_bat_low_flag; 00333 //} 00334 00335 /*----------------------------------------------------------------------------*/ 00336 /** \brief This function clears the BAT_LOW flag. 00337 */ 00338 //void 00339 //hal_clear_bat_low_flag(void) 00340 //{ 00341 // HAL_ENTER_CRITICAL_REGION(); 00342 // hal_bat_low_flag = 0; 00343 // HAL_LEAVE_CRITICAL_REGION(); 00344 //} 00345 00346 /*----------------------------------------------------------------------------*/ 00347 /** \brief This function is used to set new TRX_END event handler, overriding 00348 * old handler reference. 00349 */ 00350 //hal_trx_end_isr_event_handler_t 00351 //hal_get_trx_end_event_handler(void) 00352 //{ 00353 // return trx_end_callback; 00354 //} 00355 00356 /*----------------------------------------------------------------------------*/ 00357 /** \brief This function is used to set new TRX_END event handler, overriding 00358 * old handler reference. 00359 */ 00360 //void 00361 //hal_set_trx_end_event_handler(hal_trx_end_isr_event_handler_t trx_end_callback_handle) 00362 //{ 00363 // HAL_ENTER_CRITICAL_REGION(); 00364 // trx_end_callback = trx_end_callback_handle; 00365 // HAL_LEAVE_CRITICAL_REGION(); 00366 //} 00367 00368 /*----------------------------------------------------------------------------*/ 00369 /** \brief Remove event handler reference. 00370 */ 00371 //void 00372 //hal_clear_trx_end_event_handler(void) 00373 //{ 00374 // HAL_ENTER_CRITICAL_REGION(); 00375 // trx_end_callback = NULL; 00376 // HAL_LEAVE_CRITICAL_REGION(); 00377 //} 00378 00379 /*----------------------------------------------------------------------------*/ 00380 /** \brief This function returns the active RX_START event handler 00381 * 00382 * \return Current RX_START event handler registered. 00383 */ 00384 //hal_rx_start_isr_event_handler_t 00385 //hal_get_rx_start_event_handler(void) 00386 //{ 00387 // return rx_start_callback; 00388 //} 00389 00390 /*----------------------------------------------------------------------------*/ 00391 /** \brief This function is used to set new RX_START event handler, overriding 00392 * old handler reference. 00393 */ 00394 //void 00395 //hal_set_rx_start_event_handler(hal_rx_start_isr_event_handler_t rx_start_callback_handle) 00396 //{ 00397 // HAL_ENTER_CRITICAL_REGION(); 00398 // rx_start_callback = rx_start_callback_handle; 00399 // HAL_LEAVE_CRITICAL_REGION(); 00400 //} 00401 00402 /*----------------------------------------------------------------------------*/ 00403 /** \brief Remove event handler reference. 00404 */ 00405 //void 00406 //hal_clear_rx_start_event_handler(void) 00407 //{ 00408 // HAL_ENTER_CRITICAL_REGION(); 00409 // rx_start_callback = NULL; 00410 // HAL_LEAVE_CRITICAL_REGION(); 00411 //} 00412 00413 /*----------------------------------------------------------------------------*/ 00414 /** \brief This function returns the current value of the PLL_LOCK flag. 00415 * 00416 * The PLL_LOCK flag is incremented each time a PLL_LOCK event is signaled from the 00417 * radio transceiver. This way it is possible for the end user to poll the flag 00418 * for new event occurances. 00419 */ 00420 //uint8_t 00421 //hal_get_pll_lock_flag(void) 00422 //{ 00423 // return hal_pll_lock_flag; 00424 //} 00425 00426 /*----------------------------------------------------------------------------*/ 00427 /** \brief This function clears the PLL_LOCK flag. 00428 */ 00429 //void 00430 //hal_clear_pll_lock_flag(void) 00431 //{ 00432 // HAL_ENTER_CRITICAL_REGION(); 00433 // hal_pll_lock_flag = 0; 00434 // HAL_LEAVE_CRITICAL_REGION(); 00435 //} 00436 00437 #if defined(__AVR_ATmega128RFA1__) 00438 /* Hack for internal radio registers. hal_register_read and hal_register_write are 00439 handled through defines, but the preprocesser can't parse a macro containing 00440 another #define with multiple arguments, e.g. using 00441 #define hal_subregister_read( address, mask, position ) (address&mask)>>position 00442 #define SR_TRX_STATUS TRX_STATUS, 0x1f, 0 00443 the following only sees 1 argument to the macro 00444 return hal_subregister_read(SR_TRX_STATUS); 00445 00446 Possible fix is through two defines: 00447 #define x_hal_subregister_read(x) hal_subregister_read(x); 00448 #define hal_subregister_read( address, mask, position ) (address&mask)>>position 00449 but the subregister defines in atmega128rfa1_registermap.h are currently set up without 00450 the _SFR_MEM8 attribute, for use by hal_subregister_write. 00451 00452 */ 00453 uint8_t 00454 hal_subregister_read(uint16_t address, uint8_t mask, uint8_t position) 00455 { 00456 return (_SFR_MEM8(address)&mask)>>position; 00457 } 00458 void 00459 hal_subregister_write(uint16_t address, uint8_t mask, uint8_t position, 00460 uint8_t value) 00461 { 00462 cli(); 00463 uint8_t register_value = _SFR_MEM8(address); 00464 register_value &= ~mask; 00465 value <<= position; 00466 value &= mask; 00467 value |= register_value; 00468 _SFR_MEM8(address) = value; 00469 sei(); 00470 } 00471 00472 #else /* defined(__AVR_ATmega128RFA1__) */ 00473 /*----------------------------------------------------------------------------*/ 00474 /** \brief This function reads data from one of the radio transceiver's registers. 00475 * 00476 * \param address Register address to read from. See datasheet for register 00477 * map. 00478 * 00479 * \see Look at the at86rf230_registermap.h file for register address definitions. 00480 * 00481 * \returns The actual value of the read register. 00482 */ 00483 uint8_t 00484 hal_register_read(uint8_t address) 00485 { 00486 uint8_t register_value; 00487 /* Add the register read command to the register address. */ 00488 /* Address should be < 0x2f so no need to mask */ 00489 // address &= 0x3f; 00490 address |= 0x80; 00491 00492 HAL_SPI_TRANSFER_OPEN(); 00493 00494 /*Send Register address and read register content.*/ 00495 HAL_SPI_TRANSFER(address); 00496 register_value = HAL_SPI_TRANSFER(0); 00497 00498 HAL_SPI_TRANSFER_CLOSE(); 00499 00500 return register_value; 00501 } 00502 00503 /*----------------------------------------------------------------------------*/ 00504 /** \brief This function writes a new value to one of the radio transceiver's 00505 * registers. 00506 * 00507 * \see Look at the at86rf230_registermap.h file for register address definitions. 00508 * 00509 * \param address Address of register to write. 00510 * \param value Value to write. 00511 */ 00512 void 00513 hal_register_write(uint8_t address, uint8_t value) 00514 { 00515 /* Add the Register Write (short mode) command to the address. */ 00516 address = 0xc0 | address; 00517 00518 HAL_SPI_TRANSFER_OPEN(); 00519 00520 /*Send Register address and write register content.*/ 00521 HAL_SPI_TRANSFER(address); 00522 HAL_SPI_TRANSFER(value); 00523 00524 HAL_SPI_TRANSFER_CLOSE(); 00525 } 00526 /*----------------------------------------------------------------------------*/ 00527 /** \brief This function reads the value of a specific subregister. 00528 * 00529 * \see Look at the at86rf230_registermap.h file for register and subregister 00530 * definitions. 00531 * 00532 * \param address Main register's address. 00533 * \param mask Bit mask of the subregister. 00534 * \param position Bit position of the subregister 00535 * \retval Value of the read subregister. 00536 */ 00537 uint8_t 00538 hal_subregister_read(uint8_t address, uint8_t mask, uint8_t position) 00539 { 00540 /* Read current register value and mask out subregister. */ 00541 uint8_t register_value = hal_register_read(address); 00542 register_value &= mask; 00543 register_value >>= position; /* Align subregister value. */ 00544 00545 return register_value; 00546 } 00547 /*----------------------------------------------------------------------------*/ 00548 /** \brief This function writes a new value to one of the radio transceiver's 00549 * subregisters. 00550 * 00551 * \see Look at the at86rf230_registermap.h file for register and subregister 00552 * definitions. 00553 * 00554 * \param address Main register's address. 00555 * \param mask Bit mask of the subregister. 00556 * \param position Bit position of the subregister 00557 * \param value Value to write into the subregister. 00558 */ 00559 void 00560 hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, 00561 uint8_t value) 00562 { 00563 /* Read current register value and mask area outside the subregister. */ 00564 volatile uint8_t register_value = hal_register_read(address); 00565 register_value &= ~mask; 00566 00567 /* Start preparing the new subregister value. shift in place and mask. */ 00568 value <<= position; 00569 value &= mask; 00570 00571 value |= register_value; /* Set the new subregister value. */ 00572 00573 /* Write the modified register value. */ 00574 hal_register_write(address, value); 00575 } 00576 #endif /* defined(__AVR_ATmega128RFA1__) */ 00577 /*----------------------------------------------------------------------------*/ 00578 /** \brief Transfer a frame from the radio transceiver to a RAM buffer 00579 * 00580 * This version is optimized for use with contiki RF230BB driver. 00581 * The callback routine and CRC are left out for speed in reading the rx buffer. 00582 * Any delays here can lead to overwrites by the next packet! 00583 * 00584 * If the frame length is out of the defined bounds, the length, lqi and crc 00585 * are set to zero. 00586 * 00587 * \param rx_frame Pointer to the data structure where the frame is stored. 00588 */ 00589 void 00590 hal_frame_read(hal_rx_frame_t *rx_frame) 00591 { 00592 #if defined(__AVR_ATmega128RFA1__) 00593 00594 uint8_t frame_length,*rx_data,*rx_buffer; 00595 00596 /* Get length from the TXT_RX_LENGTH register, not including LQI 00597 * Bypassing the length check can result in overrun if buffer is < 256 bytes. 00598 */ 00599 frame_length = TST_RX_LENGTH; 00600 if ( 0 || ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH))) { 00601 rx_frame->length = frame_length; 00602 00603 /* Start of buffer in I/O space, pointer to RAM buffer */ 00604 rx_buffer=(uint8_t *)0x180; 00605 rx_data = (rx_frame->data); 00606 00607 do{ 00608 *rx_data++ = _SFR_MEM8(rx_buffer++); 00609 } while (--frame_length > 0); 00610 00611 /*Read LQI value for this frame.*/ 00612 rx_frame->lqi = *rx_buffer; 00613 00614 #else /* defined(__AVR_ATmega128RFA1__) */ 00615 00616 uint8_t *rx_data; 00617 00618 /*Send frame read (long mode) command.*/ 00619 HAL_SPI_TRANSFER_OPEN(); 00620 HAL_SPI_TRANSFER(0x20); 00621 00622 /*Read frame length. This includes the checksum. */ 00623 uint8_t frame_length = HAL_SPI_TRANSFER(0); 00624 00625 /*Check for correct frame length. Bypassing this test can result in a buffer overrun! */ 00626 if ( 0 || ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH))) { 00627 00628 rx_data = (rx_frame->data); 00629 rx_frame->length = frame_length; 00630 00631 /*Transfer frame buffer to RAM buffer */ 00632 00633 HAL_SPI_TRANSFER_WRITE(0); 00634 HAL_SPI_TRANSFER_WAIT(); 00635 do{ 00636 *rx_data++ = HAL_SPI_TRANSFER_READ(); 00637 HAL_SPI_TRANSFER_WRITE(0); 00638 00639 /* CRC was checked in hardware, but redoing the checksum here ensures the rx buffer 00640 * is not being overwritten by the next packet. Since that lengthy computation makes 00641 * such overwrites more likely, we skip it and hope for the best. 00642 * Without the check a full buffer is read in 320us at 2x spi clocking. 00643 * The 802.15.4 standard requires 640us after a greater than 18 byte frame. 00644 * With a low interrupt latency overwrites should never occur. 00645 */ 00646 // crc = _crc_ccitt_update(crc, tempData); 00647 00648 HAL_SPI_TRANSFER_WAIT(); 00649 00650 } while (--frame_length > 0); 00651 00652 00653 /*Read LQI value for this frame.*/ 00654 rx_frame->lqi = HAL_SPI_TRANSFER_READ(); 00655 00656 #endif /* defined(__AVR_ATmega128RFA1__) */ 00657 00658 /* If crc was calculated set crc field in hal_rx_frame_t accordingly. 00659 * Else show the crc has passed the hardware check. 00660 */ 00661 rx_frame->crc = true; 00662 00663 } else { 00664 /* Length test failed */ 00665 rx_frame->length = 0; 00666 rx_frame->lqi = 0; 00667 rx_frame->crc = false; 00668 } 00669 00670 HAL_SPI_TRANSFER_CLOSE(); 00671 } 00672 00673 /*----------------------------------------------------------------------------*/ 00674 /** \brief This function will download a frame to the radio transceiver's frame 00675 * buffer. 00676 * 00677 * \param write_buffer Pointer to data that is to be written to frame buffer. 00678 * \param length Length of data. The maximum length is 127 bytes. 00679 */ 00680 void 00681 hal_frame_write(uint8_t *write_buffer, uint8_t length) 00682 { 00683 #if defined(__AVR_ATmega128RFA1__) 00684 uint8_t *tx_buffer; 00685 tx_buffer=(uint8_t *)0x180; //start of fifo in i/o space 00686 /* Write frame length, including the two byte checksum */ 00687 /* The top bit of the length field shall be set to 0 for IEEE 802.15.4 compliant frames */ 00688 /* It should already be clear, so bypassing the masking is sanity check of the uip stack */ 00689 // length &= 0x7f; 00690 _SFR_MEM8(tx_buffer++) = length; 00691 00692 /* Download to the Frame Buffer. 00693 * When the FCS is autogenerated there is no need to transfer the last two bytes 00694 * since they will be overwritten. 00695 */ 00696 #if !RF230_CONF_CHECKSUM 00697 length -= 2; 00698 #endif 00699 do _SFR_MEM8(tx_buffer++)= *write_buffer++; while (--length); 00700 00701 #else /* defined(__AVR_ATmega128RFA1__) */ 00702 /* Optionally truncate length to maximum frame length. 00703 * Not doing this is a fast way to know when the application needs fixing! 00704 */ 00705 // length &= 0x7f; 00706 00707 HAL_SPI_TRANSFER_OPEN(); 00708 00709 /* Send Frame Transmit (long mode) command and frame length */ 00710 HAL_SPI_TRANSFER(0x60); 00711 HAL_SPI_TRANSFER(length); 00712 00713 /* Download to the Frame Buffer. 00714 * When the FCS is autogenerated there is no need to transfer the last two bytes 00715 * since they will be overwritten. 00716 */ 00717 #if !RF230_CONF_CHECKSUM 00718 length -= 2; 00719 #endif 00720 do HAL_SPI_TRANSFER(*write_buffer++); while (--length); 00721 00722 HAL_SPI_TRANSFER_CLOSE(); 00723 #endif /* defined(__AVR_ATmega128RFA1__) */ 00724 } 00725 00726 /*----------------------------------------------------------------------------*/ 00727 /** \brief Read SRAM 00728 * 00729 * This function reads from the SRAM of the radio transceiver. 00730 * 00731 * \param address Address in the TRX's SRAM where the read burst should start 00732 * \param length Length of the read burst 00733 * \param data Pointer to buffer where data is stored. 00734 */ 00735 #if 0 //Uses 80 bytes (on Raven) omit unless needed 00736 void 00737 hal_sram_read(uint8_t address, uint8_t length, uint8_t *data) 00738 { 00739 HAL_SPI_TRANSFER_OPEN(); 00740 00741 /*Send SRAM read command and address to start*/ 00742 HAL_SPI_TRANSFER(0x00); 00743 HAL_SPI_TRANSFER(address); 00744 00745 HAL_SPI_TRANSFER_WRITE(0); 00746 HAL_SPI_TRANSFER_WAIT(); 00747 00748 /*Upload the chosen memory area.*/ 00749 do{ 00750 *data++ = HAL_SPI_TRANSFER_READ(); 00751 HAL_SPI_TRANSFER_WRITE(0); 00752 HAL_SPI_TRANSFER_WAIT(); 00753 } while (--length > 0); 00754 00755 HAL_SPI_TRANSFER_CLOSE(); 00756 } 00757 #endif 00758 /*----------------------------------------------------------------------------*/ 00759 /** \brief Write SRAM 00760 * 00761 * This function writes into the SRAM of the radio transceiver. It can reduce 00762 * SPI transfers if only part of a frame is to be changed before retransmission. 00763 * 00764 * \param address Address in the TRX's SRAM where the write burst should start 00765 * \param length Length of the write burst 00766 * \param data Pointer to an array of bytes that should be written 00767 */ 00768 //void 00769 //hal_sram_write(uint8_t address, uint8_t length, uint8_t *data) 00770 //{ 00771 // HAL_SPI_TRANSFER_OPEN(); 00772 00773 /*Send SRAM write command.*/ 00774 // HAL_SPI_TRANSFER(0x40); 00775 00776 /*Send address where to start writing to.*/ 00777 // HAL_SPI_TRANSFER(address); 00778 00779 /*Upload the chosen memory area.*/ 00780 // do{ 00781 // HAL_SPI_TRANSFER(*data++); 00782 // } while (--length > 0); 00783 00784 // HAL_SPI_TRANSFER_CLOSE(); 00785 00786 //} 00787 00788 /*----------------------------------------------------------------------------*/ 00789 /* This #if compile switch is used to provide a "standard" function body for the */ 00790 /* doxygen documentation. */ 00791 #if defined(DOXYGEN) 00792 /** \brief ISR for the radio IRQ line, triggered by the input capture. 00793 * This is the interrupt service routine for timer1.ICIE1 input capture. 00794 * It is triggered of a rising edge on the radio transceivers IRQ line. 00795 */ 00796 void RADIO_VECT(void); 00797 #else /* !DOXYGEN */ 00798 /* These link to the RF230BB driver in rf230.c */ 00799 void rf230_interrupt(void); 00800 00801 extern hal_rx_frame_t rxframe[RF230_CONF_RX_BUFFERS]; 00802 extern uint8_t rxframe_head,rxframe_tail; 00803 00804 /* rf230interruptflag can be printed in the main idle loop for debugging */ 00805 #define DEBUG 0 00806 #if DEBUG 00807 volatile char rf230interruptflag; 00808 #define INTERRUPTDEBUG(arg) rf230interruptflag=arg 00809 #else 00810 #define INTERRUPTDEBUG(arg) 00811 #endif 00812 00813 #if defined(__AVR_ATmega128RFA1__) 00814 /* The atmega128rfa1 has individual interrupts for the integrated radio' 00815 * Whichever are enabled by the RF230 driver must be present even if not used! 00816 */ 00817 /* Received packet interrupt */ 00818 ISR(TRX24_RX_END_vect) 00819 { 00820 /* Get the rssi from ED if extended mode */ 00821 #if RF230_CONF_AUTOACK 00822 rf230_last_rssi=hal_register_read(RG_PHY_ED_LEVEL); 00823 #endif 00824 00825 /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */ 00826 /* Is a ram buffer available? */ 00827 if (rxframe[rxframe_tail].length) {DEBUGFLOW('0');} else /*DEBUGFLOW('1')*/; 00828 00829 #ifdef RF230_MIN_RX_POWER 00830 /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes */ 00831 /* This does not prevent an autoack. TODO:rfa1 radio can be set up to not autoack weak packets */ 00832 if (rf230_last_rssi >= RF230_MIN_RX_POWER) { 00833 #else 00834 if (1) { 00835 #endif 00836 // DEBUGFLOW('2'); 00837 hal_frame_read(&rxframe[rxframe_tail]); 00838 rxframe_tail++;if (rxframe_tail >= RF230_CONF_RX_BUFFERS) rxframe_tail=0; 00839 rf230_interrupt(); 00840 } 00841 } 00842 /* Preamble detected, starting frame reception */ 00843 ISR(TRX24_RX_START_vect) 00844 { 00845 // DEBUGFLOW('3'); 00846 /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */ 00847 #if !RF230_CONF_AUTOACK 00848 rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI); 00849 #endif 00850 00851 } 00852 00853 /* PLL has locked, either from a transition out of TRX_OFF or a channel change while on */ 00854 ISR(TRX24_PLL_LOCK_vect) 00855 { 00856 // DEBUGFLOW('4'); 00857 } 00858 00859 /* PLL has unexpectedly unlocked */ 00860 ISR(TRX24_PLL_UNLOCK_vect) 00861 { 00862 DEBUGFLOW('5'); 00863 } 00864 /* Flag is set by the following interrupts */ 00865 extern volatile uint8_t rf230_interruptwait,rf230_ccawait; 00866 00867 /* Wake has finished */ 00868 ISR(TRX24_AWAKE_vect) 00869 { 00870 // DEBUGFLOW('6'); 00871 rf230_interruptwait=0; 00872 } 00873 00874 /* Transmission has ended */ 00875 ISR(TRX24_TX_END_vect) 00876 { 00877 // DEBUGFLOW('7'); 00878 rf230_interruptwait=0; 00879 } 00880 00881 /* Frame address has matched ours */ 00882 extern volatile uint8_t rf230_pending; 00883 ISR(TRX24_XAH_AMI_vect) 00884 { 00885 // DEBUGFLOW('8'); 00886 rf230_pending=1; 00887 } 00888 00889 /* CCAED measurement has completed */ 00890 ISR(TRX24_CCA_ED_DONE_vect) 00891 { 00892 DEBUGFLOW('4'); 00893 rf230_ccawait=0; 00894 } 00895 00896 #else /* defined(__AVR_ATmega128RFA1__) */ 00897 /* Separate RF230 has a single radio interrupt and the source must be read from the IRQ_STATUS register */ 00898 HAL_RF230_ISR() 00899 { 00900 /*The following code reads the current system time. This is done by first 00901 reading the hal_system_time and then adding the 16 LSB directly from the 00902 hardware counter. 00903 */ 00904 // uint32_t isr_timestamp = hal_system_time; 00905 // isr_timestamp <<= 16; 00906 // isr_timestamp |= HAL_TICK_UPCNT(); // TODO: what if this wraps after reading hal_system_time? 00907 00908 volatile uint8_t state; 00909 uint8_t interrupt_source; /* used after HAL_SPI_TRANSFER_OPEN/CLOSE block */ 00910 00911 INTERRUPTDEBUG(1); 00912 00913 00914 /* Using SPI bus from ISR is generally a bad idea... */ 00915 /* Note: all IRQ are not always automatically disabled when running in ISR */ 00916 HAL_SPI_TRANSFER_OPEN(); 00917 00918 /*Read Interrupt source.*/ 00919 /*Send Register address and read register content.*/ 00920 HAL_SPI_TRANSFER_WRITE(0x80 | RG_IRQ_STATUS); 00921 00922 /* This is the second part of the convertion of system time to a 16 us time 00923 base. The division is moved here so we can spend less time waiting for SPI 00924 data. 00925 */ 00926 // isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */ 00927 // isr_timestamp &= HAL_SYMBOL_MASK; 00928 00929 HAL_SPI_TRANSFER_WAIT(); /* AFTER possible interleaved processing */ 00930 00931 #if 0 //dak 00932 interrupt_source = HAL_SPI_TRANSFER_READ(); /* The interrupt variable is used as a dummy read. */ 00933 00934 interrupt_source = HAL_SPI_TRANSFER(interrupt_source); 00935 #else 00936 interrupt_source = HAL_SPI_TRANSFER(0); 00937 #endif 00938 HAL_SPI_TRANSFER_CLOSE(); 00939 00940 /*Handle the incomming interrupt. Prioritized.*/ 00941 if ((interrupt_source & HAL_RX_START_MASK)){ 00942 INTERRUPTDEBUG(10); 00943 /* Save RSSI for this packet if not in extended mode, scaling to 1dB resolution */ 00944 #if !RF230_CONF_AUTOACK 00945 #if 0 // 3-clock shift and add is faster on machines with no hardware multiply 00946 // With -Os avr-gcc saves a byte by using the general routine for multiply by 3 00947 rf230_last_rssi = hal_subregister_read(SR_RSSI); 00948 rf230_last_rssi = (rf230_last_rssi <<1) + rf230_last_rssi; 00949 #else // Faster with 1-clock multiply. Raven and Jackdaw have 2-clock multiply so same speed while saving 2 bytes of program memory 00950 rf230_last_rssi = 3 * hal_subregister_read(SR_RSSI); 00951 #endif 00952 #endif 00953 // if(rx_start_callback != NULL){ 00954 // /* Read Frame length and call rx_start callback. */ 00955 // HAL_SPI_TRANSFER_OPEN(); 00956 // uint8_t frame_length = HAL_SPI_TRANSFER(0x20); 00957 // frame_length = HAL_SPI_TRANSFER(frame_length); 00958 00959 // HAL_SPI_TRANSFER_CLOSE(); 00960 00961 // rx_start_callback(isr_timestamp, frame_length); 00962 // } 00963 } else if (interrupt_source & HAL_TRX_END_MASK){ 00964 INTERRUPTDEBUG(11); 00965 // if(trx_end_callback != NULL){ 00966 // trx_end_callback(isr_timestamp); 00967 // } 00968 00969 state = hal_subregister_read(SR_TRX_STATUS); 00970 if((state == BUSY_RX_AACK) || (state == RX_ON) || (state == BUSY_RX) || (state == RX_AACK_ON)){ 00971 /* Received packet interrupt */ 00972 /* Buffer the frame and call rf230_interrupt to schedule poll for rf230 receive process */ 00973 // if (rxframe.length) break; //toss packet if last one not processed yet 00974 if (rxframe[rxframe_tail].length) INTERRUPTDEBUG(42); else INTERRUPTDEBUG(12); 00975 00976 #ifdef RF230_MIN_RX_POWER 00977 /* Discard packets weaker than the minimum if defined. This is for testing miniature meshes.*/ 00978 /* Save the rssi for printing in the main loop */ 00979 #if RF230_CONF_AUTOACK 00980 // rf230_last_rssi=hal_subregister_read(SR_ED_LEVEL); 00981 rf230_last_rssi=hal_register_read(RG_PHY_ED_LEVEL); 00982 #endif 00983 if (rf230_last_rssi >= RF230_MIN_RX_POWER) { 00984 #endif 00985 hal_frame_read(&rxframe[rxframe_tail]); 00986 rxframe_tail++;if (rxframe_tail >= RF230_CONF_RX_BUFFERS) rxframe_tail=0; 00987 rf230_interrupt(); 00988 // trx_end_callback(isr_timestamp); 00989 #ifdef RF230_MIN_RX_POWER 00990 } 00991 #endif 00992 00993 } 00994 00995 } else if (interrupt_source & HAL_TRX_UR_MASK){ 00996 INTERRUPTDEBUG(13); 00997 ; 00998 } else if (interrupt_source & HAL_PLL_UNLOCK_MASK){ 00999 INTERRUPTDEBUG(14); 01000 ; 01001 } else if (interrupt_source & HAL_PLL_LOCK_MASK){ 01002 INTERRUPTDEBUG(15); 01003 // hal_pll_lock_flag++; 01004 ; 01005 } else if (interrupt_source & HAL_BAT_LOW_MASK){ 01006 /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */ 01007 /* will continously be asserted while the supply voltage is less than the */ 01008 /* user-defined voltage threshold. */ 01009 uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK); 01010 trx_isr_mask &= ~HAL_BAT_LOW_MASK; 01011 hal_register_write(RG_IRQ_MASK, trx_isr_mask); 01012 // hal_bat_low_flag++; /* Increment BAT_LOW flag. */ 01013 INTERRUPTDEBUG(16); 01014 ; 01015 } else { 01016 INTERRUPTDEBUG(99); 01017 ; 01018 } 01019 } 01020 #endif /* defined(__AVR_ATmega128RFA1__) */ 01021 # endif /* defined(DOXYGEN) */ 01022 01023 /*----------------------------------------------------------------------------*/ 01024 /* This #if compile switch is used to provide a "standard" function body for the */ 01025 /* doxygen documentation. */ 01026 #if defined(DOXYGEN) 01027 /** \brief Timer Overflow ISR 01028 * This is the interrupt service routine for timer1 overflow. 01029 */ 01030 void TIMER1_OVF_vect(void); 01031 #else /* !DOXYGEN */ 01032 HAL_TIME_ISR() 01033 { 01034 hal_system_time++; 01035 } 01036 #endif 01037 01038 /** @} */ 01039 /** @} */ 01040 01041 /*EOF*/