Contiki 2.6

halbb.c

Go to the documentation of this file.
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*/