rf230bb.c

00001 /*
00002  * Copyright (c) 2007, Swedish Institute of Computer Science
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * @(#)$Id: rf230bb.c,v 1.24 2010/12/22 20:10:00 dak664 Exp $
00032  */
00033 /*
00034  * This code is almost device independent and should be easy to port.
00035  * Ported to Atmel RF230 21Feb2010 by dak
00036  */
00037 
00038 #include <stdio.h>
00039 #include <string.h>
00040 
00041 #include "contiki.h"
00042 
00043 #if defined(__AVR__)
00044 #include <avr/io.h>
00045 
00046 //_delay_us has the potential to use floating point which brings the 256 byte clz table into RAM
00047 //#include <util/delay.h>
00048 //#define delay_us( us )   ( _delay_us( ( us ) ) )
00049 //_delay_loop_2(uint16_t count) is 4 CPU cycles per iteration, up to 32 milliseconds at 8MHz
00050 #include <util/delay_basic.h>
00051 #define delay_us( us )   ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) 
00052 
00053 #include <avr/pgmspace.h>
00054 #elif defined(__MSP430__)
00055 #include <io.h>
00056 #endif
00057 
00058 #include "dev/leds.h"
00059 #include "dev/spi.h"
00060 #include "rf230bb.h"
00061 
00062 #include "net/packetbuf.h"
00063 #include "net/rime/rimestats.h"
00064 #include "net/netstack.h"
00065 
00066 #include "sys/timetable.h"
00067 
00068 #define WITH_SEND_CCA 0
00069 
00070 /* Timestamps have not been tested */
00071 #if RF230_CONF_TIMESTAMPS
00072 #include "net/rime/timesynch.h"
00073 #define TIMESTAMP_LEN 3
00074 #else /* RF230_CONF_TIMESTAMPS */
00075 #define TIMESTAMP_LEN 0
00076 #endif /* RF230_CONF_TIMESTAMPS */
00077 /* Nonzero FOOTER_LEN has not been tested */
00078 #define FOOTER_LEN 0
00079 
00080 /* RF230_CONF_CHECKSUM=0 for automatic hardware checksum */
00081 #ifndef RF230_CONF_CHECKSUM
00082 #define RF230_CONF_CHECKSUM 0
00083 #endif /* RF230_CONF_CHECKSUM */
00084 
00085 #ifndef RF230_CONF_AUTOACK
00086 #define RF230_CONF_AUTOACK 1
00087 #endif /* RF230_CONF_AUTOACK */
00088 
00089 #if RF230_CONF_AUTOACK
00090 static bool is_promiscuous;
00091 #endif
00092 
00093 #ifndef RF230_CONF_AUTORETRIES
00094 #define RF230_CONF_AUTORETRIES 2
00095 #endif /* RF230_CONF_AUTOACK */
00096 
00097 //Automatic and manual CRC both append 2 bytes to packets 
00098 #if RF230_CONF_CHECKSUM || defined(RF230BB_HOOK_TX_PACKET)
00099 #include "lib/crc16.h"
00100 #endif /* RF230_CONF_CHECKSUM */
00101 #define CHECKSUM_LEN 2
00102 
00103 /* Note the AUC_LEN is equal to the CHECKSUM_LEN in any tested configurations to date! */
00104 #define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN)
00105 #if AUX_LEN != CHECKSUM_LEN
00106 #warning RF230 Untested Configuration!
00107 #endif
00108 
00109 struct timestamp {
00110   uint16_t time;
00111   uint8_t authority_level;
00112 };
00113 
00114 #define FOOTER1_CRC_OK      0x80
00115 #define FOOTER1_CORRELATION 0x7f
00116 
00117 /* Leave radio on for testing low power protocols */
00118 #if JACKDAW
00119 #define RADIOALWAYSON 1
00120 #else
00121 #define RADIOALWAYSON 0
00122 #define RADIOSLEEPSWHENOFF 1
00123 #endif
00124 
00125 //RS232 delays will cause 6lowpan fragment overruns!
00126 #define DEBUG 0
00127 #if DEBUG
00128 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00129 #define PRINTSHORT(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00130 #else
00131 #define PRINTF(...)
00132 #define PRINTSHORT(...)
00133 #endif
00134 #if DEBUG>1
00135 /* Output format is suitable for text2pcap to convert to wireshark pcap file.
00136  * Use $text2pcap -e 0x809a (these_outputs) capture.pcap
00137  * Since the hardware calculates and appends the two byte checksum to Tx packets,
00138  * we just add two zero bytes to the packet dump. Don't forget to enable wireshark
00139  * 802.15.4 dissection even when the checksum is wrong!
00140  */
00141 //int wireshark_offset;
00142 #endif
00143 
00144 /* See clock.c and httpd-cgi.c for RADIOSTATS code */
00145 #if WEBSERVER
00146 #define RADIOSTATS 1
00147 #endif
00148 #if RADIOSTATS
00149 uint16_t RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail;
00150 #endif
00151 
00152 #if RADIOCALIBRATE
00153 /* Set in clock.c every 256 seconds */
00154 uint8_t rf230_calibrate;
00155 uint8_t rf230_calibrated; //for debugging, prints from main loop when calibration occurs
00156 #endif
00157 
00158 /* Track flow through driver, see contiki-raven-main.c for example of use */
00159 //#define DEBUGFLOWSIZE 64
00160 #if DEBUGFLOWSIZE
00161 uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE];
00162 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c
00163 #else
00164 #define DEBUGFLOW(c)
00165 #endif
00166 
00167 /* XXX hack: these will be made as Chameleon packet attributes */
00168 rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure;
00169 
00170 int rf230_authority_level_of_sender;
00171 
00172 #if RF230_CONF_TIMESTAMPS
00173 static rtimer_clock_t setup_time_for_transmission;
00174 static unsigned long total_time_for_transmission, total_transmission_len;
00175 static int num_transmissions;
00176 #endif /* RF230_CONF_TIMESTAMPS */
00177 
00178 static uint8_t volatile pending;
00179 
00180 /* RF230 hardware delay times, from datasheet */
00181 typedef enum{
00182     TIME_TO_ENTER_P_ON               = 510, /**<  Transition time from VCC is applied to P_ON - most favorable case! */
00183     TIME_P_ON_TO_TRX_OFF             = 510, /**<  Transition time from P_ON to TRX_OFF. */
00184     TIME_SLEEP_TO_TRX_OFF            = 880, /**<  Transition time from SLEEP to TRX_OFF. */
00185     TIME_RESET                       = 6,   /**<  Time to hold the RST pin low during reset */
00186     TIME_ED_MEASUREMENT              = 140, /**<  Time it takes to do a ED measurement. */
00187     TIME_CCA                         = 140, /**<  Time it takes to do a CCA. */
00188     TIME_PLL_LOCK                    = 150, /**<  Maximum time it should take for the PLL to lock. */
00189     TIME_FTN_TUNING                  = 25,  /**<  Maximum time it should take to do the filter tuning. */
00190     TIME_NOCLK_TO_WAKE               = 6,   /**<  Transition time from *_NOCLK to being awake. */
00191     TIME_CMD_FORCE_TRX_OFF           = 1,   /**<  Time it takes to execute the FORCE_TRX_OFF command. */
00192     TIME_TRX_OFF_TO_PLL_ACTIVE       = 180, /**<  Transition time from TRX_OFF to: RX_ON, PLL_ON, TX_ARET_ON and RX_AACK_ON. */
00193     TIME_STATE_TRANSITION_PLL_ACTIVE = 1,   /**<  Transition time from PLL active state to another. */
00194 }radio_trx_timing_t;
00195 /*---------------------------------------------------------------------------*/
00196 PROCESS(rf230_process, "RF230 driver");
00197 /*---------------------------------------------------------------------------*/
00198 
00199 int rf230_on(void);
00200 int rf230_off(void);
00201 
00202 static int rf230_read(void *buf, unsigned short bufsize);
00203 
00204 static int rf230_prepare(const void *data, unsigned short len);
00205 static int rf230_transmit(unsigned short len);
00206 static int rf230_send(const void *data, unsigned short len);
00207 
00208 static int rf230_receiving_packet(void);
00209 static int pending_packet(void);
00210 static int rf230_cca(void);
00211 
00212 uint8_t rf230_last_correlation,rf230_last_rssi,rf230_smallest_rssi;
00213 
00214 const struct radio_driver rf230_driver =
00215   {
00216     rf230_init,
00217     rf230_prepare,
00218     rf230_transmit,
00219     rf230_send,
00220     rf230_read,
00221     rf230_cca,
00222     rf230_receiving_packet,
00223     pending_packet,
00224     rf230_on,
00225     rf230_off
00226   };
00227 
00228 uint8_t RF230_receive_on,RF230_sleeping;
00229 static uint8_t channel;
00230 
00231 /* Received frames are buffered to rxframe in the interrupt routine in hal.c */
00232 uint8_t rxframe_head,rxframe_tail;
00233 hal_rx_frame_t rxframe[RF230_CONF_RX_BUFFERS];
00234 
00235 /*----------------------------------------------------------------------------*/
00236 /** \brief  This function return the Radio Transceivers current state.
00237  *
00238  *  \retval     P_ON               When the external supply voltage (VDD) is
00239  *                                 first supplied to the transceiver IC, the
00240  *                                 system is in the P_ON (Poweron) mode.
00241  *  \retval     BUSY_RX            The radio transceiver is busy receiving a
00242  *                                 frame.
00243  *  \retval     BUSY_TX            The radio transceiver is busy transmitting a
00244  *                                 frame.
00245  *  \retval     RX_ON              The RX_ON mode enables the analog and digital
00246  *                                 receiver blocks and the PLL frequency
00247  *                                 synthesizer.
00248  *  \retval     TRX_OFF            In this mode, the SPI module and crystal
00249  *                                 oscillator are active.
00250  *  \retval     PLL_ON             Entering the PLL_ON mode from TRX_OFF will
00251  *                                 first enable the analog voltage regulator. The
00252  *                                 transceiver is ready to transmit a frame.
00253  *  \retval     BUSY_RX_AACK       The radio was in RX_AACK_ON mode and received
00254  *                                 the Start of Frame Delimiter (SFD). State
00255  *                                 transition to BUSY_RX_AACK is done if the SFD
00256  *                                 is valid.
00257  *  \retval     BUSY_TX_ARET       The radio transceiver is busy handling the
00258  *                                 auto retry mechanism.
00259  *  \retval     RX_AACK_ON         The auto acknowledge mode of the radio is
00260  *                                 enabled and it is waiting for an incomming
00261  *                                 frame.
00262  *  \retval     TX_ARET_ON         The auto retry mechanism is enabled and the
00263  *                                 radio transceiver is waiting for the user to
00264  *                                 send the TX_START command.
00265  *  \retval     RX_ON_NOCLK        The radio transceiver is listening for
00266  *                                 incomming frames, but the CLKM is disabled so
00267  *                                 that the controller could be sleeping.
00268  *                                 However, this is only true if the controller
00269  *                                 is run from the clock output of the radio.
00270  *  \retval     RX_AACK_ON_NOCLK   Same as the RX_ON_NOCLK state, but with the
00271  *                                 auto acknowledge module turned on.
00272  *  \retval     BUSY_RX_AACK_NOCLK Same as BUSY_RX_AACK, but the controller
00273  *                                 could be sleeping since the CLKM pin is
00274  *                                 disabled.
00275  *  \retval     STATE_TRANSITION   The radio transceiver's state machine is in
00276  *                                 transition between two states.
00277  */
00278 static uint8_t
00279 radio_get_trx_state(void)
00280 {
00281     return hal_subregister_read(SR_TRX_STATUS);
00282 }
00283 
00284 /*----------------------------------------------------------------------------*/
00285 /** \brief  This function checks if the radio transceiver is sleeping.
00286  *
00287  *  \retval     true    The radio transceiver is in SLEEP or one of the *_NOCLK
00288  *                      states.
00289  *  \retval     false   The radio transceiver is not sleeping.
00290  */
00291 static bool radio_is_sleeping(void)
00292 {
00293     bool sleeping = false;
00294 
00295     /* The radio transceiver will be at SLEEP or one of the *_NOCLK states only if */
00296     /* the SLP_TR pin is high. */
00297     if (hal_get_slptr() != 0){
00298         sleeping = true;
00299     }
00300 
00301     return sleeping;
00302 }
00303 
00304 /*----------------------------------------------------------------------------*/
00305 /** \brief  This function will reset the state machine (to TRX_OFF) from any of
00306  *          its states, except for the SLEEP state.
00307  */
00308 static void
00309 radio_reset_state_machine(void)
00310 {
00311     hal_set_slptr_low();
00312     delay_us(TIME_NOCLK_TO_WAKE);
00313     hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00314     delay_us(TIME_CMD_FORCE_TRX_OFF);
00315 }
00316 /*---------------------------------------------------------------------------*/
00317 static char
00318 rf230_isidle(void)
00319 {
00320   uint8_t radio_state;
00321   radio_state = hal_subregister_read(SR_TRX_STATUS);
00322   if (radio_state != BUSY_TX_ARET &&
00323       radio_state != BUSY_RX_AACK &&
00324       radio_state != STATE_TRANSITION &&
00325       radio_state != BUSY_RX && 
00326       radio_state != BUSY_TX) {
00327     return(1);
00328   } else {
00329 //    printf(".%u",radio_state);
00330     return(0);
00331   }
00332 }
00333   
00334 static void
00335 rf230_waitidle(void)
00336 {
00337   while (1) {
00338     if (rf230_isidle()) break;
00339   }
00340 }
00341 
00342 /*----------------------------------------------------------------------------*/
00343 /** \brief  This function will change the current state of the radio
00344  *          transceiver's internal state machine.
00345  *
00346  *  \param     new_state        Here is a list of possible states:
00347  *             - RX_ON        Requested transition to RX_ON state.
00348  *             - TRX_OFF      Requested transition to TRX_OFF state.
00349  *             - PLL_ON       Requested transition to PLL_ON state.
00350  *             - RX_AACK_ON   Requested transition to RX_AACK_ON state.
00351  *             - TX_ARET_ON   Requested transition to TX_ARET_ON state.
00352  *
00353  *  \retval    RADIO_SUCCESS          Requested state transition completed
00354  *                                  successfully.
00355  *  \retval    RADIO_INVALID_ARGUMENT Supplied function parameter out of bounds.
00356  *  \retval    RADIO_WRONG_STATE      Illegal state to do transition from.
00357  *  \retval    RADIO_BUSY_STATE       The radio transceiver is busy.
00358  *  \retval    RADIO_TIMED_OUT        The state transition could not be completed
00359  *                                  within resonable time.
00360  */
00361 static radio_status_t
00362 radio_set_trx_state(uint8_t new_state)
00363 {
00364     uint8_t original_state;
00365 
00366     /*Check function paramter and current state of the radio transceiver.*/
00367     if (!((new_state == TRX_OFF)    ||
00368           (new_state == RX_ON)      ||
00369           (new_state == PLL_ON)     ||
00370           (new_state == RX_AACK_ON) ||
00371           (new_state == TX_ARET_ON))){
00372         return RADIO_INVALID_ARGUMENT;
00373     }
00374 
00375     if (radio_is_sleeping() == true){
00376         return RADIO_WRONG_STATE;
00377     }
00378 
00379     /* Wait for radio to finish previous operation */
00380     rf230_waitidle();
00381  //   for(;;)
00382  //   {
00383         original_state = radio_get_trx_state();
00384   //      if (original_state != BUSY_TX_ARET &&
00385   //          original_state != BUSY_RX_AACK &&
00386   //          original_state != BUSY_RX && 
00387   //          original_state != BUSY_TX)
00388   //          break;
00389   //  }
00390 
00391     if (new_state == original_state){
00392         return RADIO_SUCCESS;
00393     }
00394 
00395 
00396     /* At this point it is clear that the requested new_state is: */
00397     /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON or TX_ARET_ON. */
00398 
00399     /* The radio transceiver can be in one of the following states: */
00400     /* TRX_OFF, RX_ON, PLL_ON, RX_AACK_ON, TX_ARET_ON. */
00401     if(new_state == TRX_OFF){
00402         radio_reset_state_machine(); /* Go to TRX_OFF from any state. */
00403     } else {
00404         /* It is not allowed to go from RX_AACK_ON or TX_AACK_ON and directly to */
00405         /* TX_AACK_ON or RX_AACK_ON respectively. Need to go via RX_ON or PLL_ON. */
00406         if ((new_state == TX_ARET_ON) &&
00407             (original_state == RX_AACK_ON)){
00408             /* First do intermediate state transition to PLL_ON, then to TX_ARET_ON. */
00409             /* The final state transition to TX_ARET_ON is handled after the if-else if. */
00410             hal_subregister_write(SR_TRX_CMD, PLL_ON);
00411             delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
00412         } else if ((new_state == RX_AACK_ON) &&
00413                  (original_state == TX_ARET_ON)){
00414             /* First do intermediate state transition to RX_ON, then to RX_AACK_ON. */
00415             /* The final state transition to RX_AACK_ON is handled after the if-else if. */
00416             hal_subregister_write(SR_TRX_CMD, RX_ON);
00417             delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
00418         }
00419 
00420         /* Any other state transition can be done directly. */
00421         hal_subregister_write(SR_TRX_CMD, new_state);
00422 
00423         /* When the PLL is active most states can be reached in 1us. However, from */
00424         /* TRX_OFF the PLL needs time to activate. */
00425         if (original_state == TRX_OFF){
00426             delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
00427         } else {
00428             delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
00429         }
00430     } /*  end: if(new_state == TRX_OFF) ... */
00431 
00432     /*Verify state transition.*/
00433     radio_status_t set_state_status = RADIO_TIMED_OUT;
00434 
00435     if (radio_get_trx_state() == new_state){
00436         set_state_status = RADIO_SUCCESS;
00437     }
00438 
00439     return set_state_status;
00440 }
00441 
00442 void
00443 rf230_set_promiscuous_mode(bool isPromiscuous) {
00444 #if RF230_CONF_AUTOACK
00445     is_promiscuous = isPromiscuous;
00446 /* TODO: Figure out when to pass promisc state to 802.15.4 */
00447 //    radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON);
00448 #endif
00449 }
00450 
00451 bool
00452 rf230_is_ready_to_send() {
00453         switch(radio_get_trx_state()) {
00454                 case BUSY_TX:
00455                 case BUSY_TX_ARET:
00456                         return false;
00457         }
00458         
00459         return true;
00460 }
00461 
00462 
00463 static void
00464 flushrx(void)
00465 {
00466   rxframe[rxframe_head].length=0;
00467 }
00468 /*---------------------------------------------------------------------------*/
00469 static uint8_t locked, lock_on, lock_off;
00470 
00471 static void
00472 on(void)
00473 {
00474   ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00475   
00476 #ifdef RF230BB_HOOK_RADIO_ON
00477   RF230BB_HOOK_RADIO_ON();
00478 #endif
00479 
00480   if (RF230_sleeping) {
00481     hal_set_slptr_low();
00482     delay_us(TIME_SLEEP_TO_TRX_OFF);
00483 //  delay_us(TIME_SLEEP_TO_TRX_OFF);//extra delay for now, wake time depends on board capacitance
00484     RF230_sleeping=0;
00485   }
00486   rf230_waitidle();
00487 
00488 #if RF230_CONF_AUTOACK
00489  // radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON);
00490   radio_set_trx_state(RX_AACK_ON);
00491 #else
00492   radio_set_trx_state(RX_ON);
00493 #endif
00494 
00495  // flushrx();
00496  //  DEBUGFLOW('O');
00497   RF230_receive_on = 1;
00498 }
00499 static void
00500 off(void)
00501 {
00502  //     rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
00503   RF230_receive_on = 0;
00504 
00505 #ifdef RF230BB_HOOK_RADIO_OFF
00506   RF230BB_HOOK_RADIO_OFF();
00507 #endif
00508 
00509 //   DEBUGFLOW('F');
00510 #if !RADIOALWAYSON
00511   
00512   /* Wait any transmission to end */
00513   rf230_waitidle(); 
00514 
00515   /* Force the device into TRX_OFF. */   
00516   radio_reset_state_machine();
00517 
00518 #if RADIOSLEEPSWHENOFF
00519   /* Sleep Radio */
00520   hal_set_slptr_high();
00521   RF230_sleeping = 1;
00522 #endif
00523 
00524 #endif /* !RADIOALWAYSON */
00525 
00526   ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00527 }
00528 /*---------------------------------------------------------------------------*/
00529 #define GET_LOCK() locked = 1
00530 static void RELEASE_LOCK(void) {
00531   if(lock_on) {
00532     on();
00533     lock_on = 0;
00534   }
00535   if(lock_off) {
00536     off();
00537     lock_off = 0;
00538   }
00539   locked = 0;
00540 }
00541 /*---------------------------------------------------------------------------*/
00542 static void
00543 set_txpower(uint8_t power)
00544 {
00545   if (power > TX_PWR_17_2DBM){
00546     power=TX_PWR_17_2DBM;
00547   }
00548   if (radio_is_sleeping() ==true) {
00549     PRINTF("rf230_set_txpower:Sleeping");  //happens with cxmac
00550   } else {
00551     hal_subregister_write(SR_TX_PWR, power);
00552   }
00553 }
00554 /*----------------------------------------------------------------------------*/
00555 /**
00556     \brief Calibrate the internal RC oscillator
00557 
00558     This function calibrates the internal RC oscillator, based
00559     on an external 32KHz crystal connected to TIMER2. In order to
00560     verify the calibration result you can program the CKOUT fuse
00561     and monitor the CPU clock on an I/O pin.
00562 */
00563 #define AVR_ENTER_CRITICAL_REGION( ) {uint8_t volatile saved_sreg = SREG; cli( )
00564 #define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;}
00565     uint8_t osccal_original,osccal_calibrated;
00566 void
00567 calibrate_rc_osc_32k(void)
00568 {
00569 #if 1
00570 
00571     /* Calibrate RC Oscillator: The calibration routine is done by clocking TIMER2
00572      * from the external 32kHz crystal while running an internal timer simultaneously.
00573      * The internal timer will be clocked at the same speed as the internal RC
00574      * oscillator, while TIMER2 is running at 32768 Hz. This way it is not necessary
00575      * to use a timed loop, and keep track cycles in timed loop vs. optimization
00576      * and compiler.
00577      */
00578     uint8_t osccal_original = OSCCAL;
00579     volatile uint16_t temp;
00580      
00581     /* Start with current value, which for some MCUs could be in upper or lower range */
00582 
00583 //  PRR0 &= ~((1 << PRTIM2)|(1 << PRTIM1)); /*  Enable Timer 1 and 2 */
00584 
00585     TIMSK2 = 0x00; /*  Disable Timer/Counter 2 interrupts. */
00586     TIMSK1 = 0x00; /*  Disable Timer/Counter 1 interrupts. */
00587 
00588     /* Enable TIMER/COUNTER 2 to be clocked from the external 32kHz clock crystal.
00589      * Then wait for the timer to become stable before doing any calibration.
00590      */
00591     ASSR |= (1 << AS2);
00592  // while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)|(1 << TCR2BUB))) { ; }
00593     TCCR2B = 1 << CS20;   /* run timer 2 at divide by 1 (32KHz) */
00594 
00595     delay_us(50000UL);  //crystal takes significant time to stabilize
00596     AVR_ENTER_CRITICAL_REGION();
00597 
00598     uint8_t counter = 128;
00599     bool cal_ok = false;
00600     do{
00601         /* wait for timer to be ready for updated config */
00602         TCCR1B = 1 << CS10;
00603 
00604         while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)|(1 << TCR2BUB))) { ; }
00605 
00606         TCNT2 = 0x80;
00607         TCNT1 = 0;
00608 
00609         TIFR2 = 0xFF; /* Clear TIFR2 flags (Yes, really) */
00610 
00611         /* Wait for TIMER/COUNTER 2 to overflow. Stop TIMER/COUNTER 1 and 2, and
00612          * read the counter value of TIMER/COUNTER 1. It will now contain the
00613          * number of cpu cycles elapsed within the 3906.25 microsecond period.
00614          */
00615         while (!(TIFR2 & (1 << TOV2))){
00616             ;
00617             }
00618         temp = TCNT1;
00619 
00620         TCCR1B = 0;
00621 /* Defining these as floating point introduces a lot of code and the 256 byte .clz table to RAM */
00622 /* At 8 MHz we would expect 8*3906.25 = 31250 CPU clocks */
00623 #define cal_upper 32812 //(31250*1.05) // 32812 = 0x802c
00624 #define cal_lower 29687 //(31250*0.95) // 29687 = 0x73f7
00625         /* Iteratively reduce the error to be within limits */
00626         if (temp < cal_lower) {
00627             /* Too slow. Put the hammer down. */
00628             if (OSCCAL==0x7e) break; //stay in lowest range
00629             if (OSCCAL==0xff) break;
00630             OSCCAL++;
00631         } else if (temp > cal_upper) {
00632             /* Too fast, retard. */
00633             if (OSCCAL==0x81) break; //stay in highest range
00634             if (OSCCAL==0x00) break;
00635             OSCCAL--;
00636         } else {
00637             /* The CPU clock frequency is now within +/- 0.5% of the target value. */
00638             cal_ok = true;
00639         }
00640 
00641         counter--;
00642     } while ((counter != 0) && (false == cal_ok));
00643 
00644      osccal_calibrated=OSCCAL;   
00645     if (true != cal_ok) {
00646         /* We failed, therefore restore previous OSCCAL value. */
00647         OSCCAL = osccal_original;
00648     }
00649 
00650     OSCCAL = osccal_original;
00651     TCCR2B = 0;
00652 
00653     ASSR &= ~(1 << AS2);
00654 
00655     /* Disable both timers again to save power. */
00656     //    PRR0 |= (1 << PRTIM2);/* |(1 << PRTIM1); */
00657 
00658     AVR_LEAVE_CRITICAL_REGION();
00659 #endif
00660 }
00661 /*---------------------------------------------------------------------------*/
00662 int
00663 rf230_init(void)
00664 {
00665   uint8_t i;
00666   DEBUGFLOW('I');
00667 
00668   /* Wait in case VCC just applied */
00669   delay_us(TIME_TO_ENTER_P_ON);
00670  
00671   /* Calibrate oscillator */
00672  // printf_P(PSTR("\nBefore calibration OSCCAL=%x\n"),OSCCAL);
00673  // calibrate_rc_osc_32k();
00674  // printf_P(PSTR("After calibration OSCCAL=%x\n"),OSCCAL); 
00675 
00676   /* Initialize Hardware Abstraction Layer */
00677   hal_init();
00678   
00679   /* Set receive buffers empty and point to the first */
00680   for (i=0;i<RF230_CONF_RX_BUFFERS;i++) rxframe[i].length=0;
00681   rxframe_head=0;rxframe_tail=0;
00682   
00683   /* Do full rf230 Reset */
00684   hal_set_rst_low();
00685   hal_set_slptr_low();
00686   delay_us(TIME_RESET);
00687   hal_set_rst_high();
00688 
00689   /* Force transition to TRX_OFF */
00690   hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00691   delay_us(TIME_P_ON_TO_TRX_OFF);
00692   
00693   /* Verify that it is a supported version */
00694   /* Note gcc optimizes this away if DEBUG is not set! */
00695   //ATMEGA128RFA1 - version 4, ID 31
00696   uint8_t tvers = hal_register_read(RG_VERSION_NUM);
00697   uint8_t tmanu = hal_register_read(RG_MAN_ID_0);
00698 
00699   if ((tvers != RF230_REVA) && (tvers != RF230_REVB))
00700     PRINTF("rf230: Unsupported version %u\n",tvers);
00701   if (tmanu != SUPPORTED_MANUFACTURER_ID) 
00702     PRINTF("rf230: Unsupported manufacturer ID %u\n",tmanu);
00703 
00704   PRINTF("rf230: Version %u, ID %u\n",tvers,tmanu);
00705   
00706   rf230_warm_reset();
00707  
00708  /* Start the packet receive process */
00709   process_start(&rf230_process, NULL);
00710  
00711  /* Leave radio in on state (?)*/
00712   on();
00713 
00714   return 1;
00715 }
00716 /*---------------------------------------------------------------------------*/
00717 /* Used to reinitialize radio parameters without losing pan and mac address, channel, power, etc. */
00718 void rf230_warm_reset(void) {
00719 #if RF230_CONF_SNEEZER && JACKDAW
00720   /* Take jackdaw radio out of test mode */
00721 #warning Manipulating PORTB pins for RF230 Sneezer mode!
00722   PORTB &= ~(1<<7);
00723   DDRB  &= ~(1<<7);
00724 #endif
00725   
00726   hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK);
00727 
00728   /* Set up number of automatic retries 0-15 (0 implies PLL_ON sends instead of the extended TX_ARET mode */
00729   hal_subregister_write(SR_MAX_FRAME_RETRIES, RF230_CONF_AUTORETRIES );
00730  
00731  /* Set up carrier sense/clear channel assesment parameters for extended operating mode */
00732   hal_subregister_write(SR_MAX_CSMA_RETRIES, 5 );//highest allowed retries
00733   hal_register_write(RG_CSMA_BE, 0x80);       //min backoff exponent 0, max 8 (highest allowed)
00734   hal_register_write(RG_CSMA_SEED_0,hal_register_read(RG_PHY_RSSI) );//upper two RSSI reg bits RND_VALUE are random in rf231
00735  // hal_register_write(CSMA_SEED_1,42 );
00736 
00737   /* CCA Mode Mode 1=Energy above threshold  2=Carrier sense only  3=Both 0=Either (RF231 only) */
00738 //hal_subregister_write(SR_CCA_MODE,1);  //1 is the power-on default
00739 
00740   /* Carrier sense threshold (not implemented in RF230 or RF231) */
00741 // hal_subregister_write(SR_CCA_CS_THRES,1);
00742 
00743   /* CCA energy threshold = -91dB + 2*SR_CCA_ED_THRESH. Reset defaults to -77dB */
00744   /* Use RF230 base of -91;  RF231 base is -90 according to datasheet */
00745 #ifdef RF230_CONF_CCA_THRES
00746 #if RF230_CONF_CCA_THRES < -91
00747 #warning
00748 #warning RF230_CONF_CCA_THRES below hardware limit, setting to -91dBm
00749 #warning
00750   hal_subregister_write(SR_CCA_ED_THRES,0);  
00751 #elif RF230_CONF_CCA_THRES > -61
00752 #warning
00753 #warning RF230_CONF_CCA_THRES above hardware limit, setting to -61dBm
00754 #warning
00755   hal_subregister_write(SR_CCA_ED_THRES,15);  
00756 #else
00757   hal_subregister_write(SR_CCA_ED_THRES,(RF230_CONF_CCA_THRES+91)/2);  
00758 #endif
00759 #endif
00760 
00761   /* Use automatic CRC unless manual is specified */
00762 #if RF230_CONF_CHECKSUM
00763   hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
00764 #else
00765   hal_subregister_write(SR_TX_AUTO_CRC_ON, 1);
00766 #endif
00767 
00768 /* Limit tx power for testing miniature Raven mesh */
00769 #ifdef RF230_MAX_TX_POWER
00770   set_txpower(RF230_MAX_TX_POWER);  //0=3dbm 15=-17.2dbm
00771 #endif
00772 }
00773 /*---------------------------------------------------------------------------*/
00774 static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH+AUX_LEN];
00775 static int
00776 rf230_transmit(unsigned short payload_len)
00777 {
00778   int txpower;
00779   uint8_t total_len;
00780   uint8_t radiowason;
00781   uint8_t tx_result;
00782 #if RF230_CONF_TIMESTAMPS
00783   struct timestamp timestamp;
00784 #endif /* RF230_CONF_TIMESTAMPS */
00785 
00786   GET_LOCK();
00787 //  DEBUGFLOW('T');
00788 
00789   /* Save receiver state */
00790   radiowason=RF230_receive_on;
00791 
00792   /* If radio is sleeping we have to turn it on first */
00793   /* This automatically does the PLL calibrations */
00794   if (RF230_sleeping) {
00795     hal_set_slptr_low();
00796  //   delay_us(TIME_SLEEP_TO_TRX_OFF);
00797     RF230_sleeping=0;
00798   } else {
00799 #if RADIOCALIBRATE
00800   /* If on, do periodic calibration. See clock.c */
00801     if (rf230_calibrate) {
00802       hal_subregister_write(SR_PLL_CF_START,1);   //takes 80us max
00803       hal_subregister_write(SR_PLL_DCU_START,1); //takes 6us, concurrently
00804       rf230_calibrate=0;
00805       rf230_calibrated=1;
00806       delay_us(80); //?
00807     }
00808 #endif
00809   }
00810  
00811   /* Wait for any previous operation or state transition to finish */
00812   rf230_waitidle();
00813 
00814   /* Prepare to transmit */
00815 #if RF230_CONF_AUTORETRIES
00816   radio_set_trx_state(TX_ARET_ON);
00817 #else
00818   radio_set_trx_state(PLL_ON);
00819 #endif
00820 
00821   txpower = 0;
00822   
00823   if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00824     /* Remember the current transmission power */
00825     txpower = rf230_get_txpower();
00826     /* Set the specified transmission power */
00827     set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
00828   }
00829 
00830   total_len = payload_len + AUX_LEN;
00831 
00832 #if RF230_CONF_TIMESTAMPS
00833   rtimer_clock_t txtime = timesynch_time();
00834 #endif /* RF230_CONF_TIMESTAMPS */
00835 #if defined(__AVR_ATmega128RFA1__)
00836 /* No interrupts across frame download! */
00837   cli();
00838 /* slow down the transmit? */
00839  //   delay_us(500);
00840 #endif
00841  /* Toggle the SLP_TR pin to initiate the frame transmission */
00842   hal_set_slptr_high();
00843   hal_set_slptr_low();
00844   hal_frame_write(buffer, total_len);
00845 #if defined(__AVR_ATmega128RFA1__)
00846  sei();
00847 #endif
00848   PRINTF("rf230_transmit:\n");
00849 #if DEBUG>1
00850 /* Note the dumped packet will have a zero checksum unless compiled with RF230_CONF_CHECKSUM
00851  * since we don't know what it will be if calculated by the hardware.
00852  */
00853   {
00854     uint8_t i;
00855     PRINTF("0000");       //Start a new wireshark packet
00856     for (i=0;i<total_len;i++) PRINTF(" %02x",buffer[i]);
00857     PRINTF("\n");
00858   }
00859 #endif
00860 
00861   if(RF230_receive_on) {
00862     ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00863   }
00864   ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00865 
00866 #if RADIOSTATS
00867   RF230_sendpackets++;
00868 #endif
00869  
00870  /* We wait until transmission has ended so that we get an
00871      accurate measurement of the transmission time.*/
00872   rf230_waitidle();
00873 
00874  /* Get the transmission result */  
00875 #if RF230_CONF_AUTORETRIES
00876   tx_result = hal_subregister_read(SR_TRAC_STATUS);
00877 #else
00878   tx_result=0;
00879 #endif
00880 
00881 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
00882   ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
00883 #endif
00884 
00885  /* Restore the transmission power */
00886  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00887     set_txpower(txpower & 0xff);
00888   }
00889  
00890   /* Restore receive mode */
00891   if(radiowason) {
00892  //       DEBUGFLOW('m');
00893     on();
00894   }
00895 
00896 #if RF230_CONF_TIMESTAMPS
00897   setup_time_for_transmission = txtime - timestamp.time;
00898 
00899   if(num_transmissions < 10000) {
00900     total_time_for_transmission += timesynch_time() - txtime;
00901     total_transmission_len += total_len;
00902     num_transmissions++;
00903   }
00904 
00905 #endif /* RF230_CONF_TIMESTAMPS */
00906 
00907   ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00908   if(RF230_receive_on) {
00909     ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00910   } else {
00911 #if RADIOALWAYSON
00912     /* Enable reception */
00913     on();
00914 #else
00915     /* Go to lower power TRX_OFF state (turn off PLL) */
00916     hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00917 #endif
00918   }
00919 
00920   RELEASE_LOCK();
00921   if (tx_result==1) {               //success, data pending from adressee
00922     tx_result=0;                    //Just show success?
00923   } else if (tx_result==3) {        //CSMA channel access failure
00924     RIMESTATS_ADD(contentiondrop);
00925     PRINTF("rf230_transmit: Transmission never started\n");
00926 //} else if (tx_result==5) {        //Expected ACK, none received
00927 //} else if (tx_result==7) {        //Invalid (Can't happen since waited for idle above?)
00928   }
00929 
00930   return tx_result;
00931 }
00932 /*---------------------------------------------------------------------------*/
00933 static int
00934 rf230_prepare(const void *payload, unsigned short payload_len)
00935 {
00936   int ret = 0;
00937   uint8_t total_len,*pbuf;
00938 #if RF230_CONF_TIMESTAMPS
00939   struct timestamp timestamp;
00940 #endif /* RF230_CONF_TIMESTAMPS */
00941 #if RF230_CONF_CHECKSUM
00942   uint16_t checksum;
00943 #endif /* RF230_CONF_CHECKSUM */
00944 
00945   GET_LOCK();
00946 //    DEBUGFLOW('P');
00947 
00948 //  PRINTF("rf230: sending %d bytes\n", payload_len);
00949 //  PRINTSHORT("s%d ",payload_len);
00950 
00951   RIMESTATS_ADD(lltx);
00952 
00953 #if RF230_CONF_CHECKSUM
00954   checksum = crc16_data(payload, payload_len, 0);
00955 #endif /* RF230_CONF_CHECKSUM */
00956  
00957   /* Copy payload to RAM buffer */
00958   total_len = payload_len + AUX_LEN;
00959   if (total_len > RF230_MAX_TX_FRAME_LENGTH){
00960 #if RADIOSTATS
00961     RF230_sendfail++;
00962 #endif
00963 #if DEBUG
00964     printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH);
00965 #endif
00966     ret = -1;
00967         goto bail;
00968   }
00969   pbuf=&buffer[0];
00970   memcpy(pbuf,payload,payload_len);
00971   pbuf+=payload_len;
00972 
00973 #if RF230_CONF_CHECKSUM
00974   memcpy(pbuf,&checksum,CHECKSUM_LEN);
00975   pbuf+=CHECKSUM_LEN;
00976 #endif /* RF230_CONF_CHECKSUM */
00977 
00978 #if RF230_CONF_TIMESTAMPS
00979   timestamp.authority_level = timesynch_authority_level();
00980   timestamp.time = timesynch_time();
00981   memcpy(pbuf,&timestamp,TIMESTAMP_LEN);
00982   pbuf+=TIMESTAMP_LEN;
00983 #endif /* RF230_CONF_TIMESTAMPS */
00984 /*------------------------------------------------------------*/  
00985 
00986 #ifdef RF230BB_HOOK_TX_PACKET
00987 #if !RF230_CONF_CHECKSUM
00988   { // Add a checksum before we log the packet out
00989     uint16_t checksum;
00990     checksum = crc16_data(payload, payload_len, 0);
00991     memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN);
00992   }
00993 #endif /* RF230_CONF_CHECKSUM */
00994   RF230BB_HOOK_TX_PACKET(buffer,total_len);
00995 #endif
00996   
00997 
00998 bail:
00999   RELEASE_LOCK();
01000   return ret;
01001 }
01002 /*---------------------------------------------------------------------------*/
01003 static int
01004 rf230_send(const void *payload, unsigned short payload_len)
01005 {
01006         int ret = 0;
01007 
01008 #ifdef RF230BB_HOOK_IS_SEND_ENABLED
01009         if(!RF230BB_HOOK_IS_SEND_ENABLED()) {
01010                 goto bail;
01011         }
01012 #endif
01013         
01014         if((ret=rf230_prepare(payload, payload_len))) {
01015 #if DEBUG
01016                 printf_P(PSTR("rf230_send: Unable to send, prep failed (%d)\n"),ret);
01017 #endif
01018                 goto bail;
01019         }
01020 
01021         ret = rf230_transmit(payload_len);
01022         
01023 bail:
01024 #if RADIOSTATS
01025     if (ret) RF230_sendfail++;
01026 #endif
01027         return ret;
01028 }
01029 /*---------------------------------------------------------------------------*/
01030 int
01031 rf230_off(void)
01032 {
01033   /* Don't do anything if we are already turned off. */
01034   if(RF230_receive_on == 0) {
01035     return 1;
01036   }
01037 
01038   /* If we are called when the driver is locked, we indicate that the
01039      radio should be turned off when the lock is unlocked. */
01040   if(locked) {
01041     lock_off = 1;
01042     return 1;
01043   }
01044 
01045   /* If we are currently receiving a packet
01046      we don't actually switch the radio off now, but signal that the
01047      driver should switch off the radio once the packet has been
01048      received and processed, by setting the 'lock_off' variable. */
01049   if (!rf230_isidle()) {
01050 // if (radio_get_trx_state()==BUSY_RX) {
01051     lock_off = 1;
01052     return 1;
01053   }
01054 
01055   off();
01056   return 1;
01057 }
01058 /*---------------------------------------------------------------------------*/
01059 int
01060 rf230_on(void)
01061 {
01062   if(RF230_receive_on) {
01063     return 1;
01064   }
01065   if(locked) {
01066     DEBUGFLOW('L');
01067     lock_on = 1;
01068     return 1;
01069   }
01070 
01071   on();
01072   return 1;
01073 }
01074 /*---------------------------------------------------------------------------*/
01075 uint8_t
01076 rf230_get_channel(void)
01077 {
01078 //jackdaw reads zero channel, raven reads correct channel?
01079 //return hal_subregister_read(SR_CHANNEL);
01080   return channel;
01081 }
01082 /*---------------------------------------------------------------------------*/
01083 void
01084 rf230_set_channel(uint8_t c)
01085 {
01086  /* Wait for any transmission to end. */
01087   PRINTF("rf230: Set Channel %u\n",c);
01088   rf230_waitidle();
01089   channel=c;
01090   hal_subregister_write(SR_CHANNEL, c);
01091 }
01092 /*---------------------------------------------------------------------------*/
01093 void
01094 rf230_listen_channel(uint8_t c)
01095 {
01096  /* Same as set channel but forces RX_ON state for sniffer or energy scan */
01097 //  PRINTF("rf230: Listen Channel %u\n",c);
01098   rf230_set_channel(c);
01099   radio_set_trx_state(RX_ON);
01100 }
01101 /*---------------------------------------------------------------------------*/
01102 void
01103 rf230_set_pan_addr(unsigned pan,
01104                     unsigned addr,
01105                     const uint8_t ieee_addr[8])
01106 //rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr)
01107 {
01108   PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
01109   
01110   uint8_t abyte;
01111   abyte = pan & 0xFF;
01112   hal_register_write(RG_PAN_ID_0,abyte);
01113   abyte = (pan >> 8*1) & 0xFF;
01114   hal_register_write(RG_PAN_ID_1, abyte);
01115 
01116   abyte = addr & 0xFF;
01117   hal_register_write(RG_SHORT_ADDR_0, abyte);
01118   abyte = (addr >> 8*1) & 0xFF;
01119   hal_register_write(RG_SHORT_ADDR_1, abyte);  
01120 
01121   if (ieee_addr != NULL) {
01122     PRINTF("MAC=%x",*ieee_addr);
01123     hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++);
01124     PRINTF(":%x",*ieee_addr);
01125     hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++);
01126     PRINTF(":%x",*ieee_addr);
01127     hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++);
01128     PRINTF(":%x",*ieee_addr);
01129     hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++);
01130     PRINTF(":%x",*ieee_addr);
01131     hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++);
01132     PRINTF(":%x",*ieee_addr);
01133     hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++);
01134     PRINTF(":%x",*ieee_addr);
01135     hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++);
01136     PRINTF(":%x",*ieee_addr);
01137     hal_register_write(RG_IEEE_ADDR_0, *ieee_addr);
01138     PRINTF("\n");
01139   }
01140 }
01141 /*---------------------------------------------------------------------------*/
01142 /*
01143  * Interrupt leaves frame intact in FIFO.
01144  */
01145 #if RF230_CONF_TIMESTAMPS
01146 static volatile rtimer_clock_t interrupt_time;
01147 static volatile int interrupt_time_set;
01148 #endif /* RF230_CONF_TIMESTAMPS */
01149 #if RF230_TIMETABLE_PROFILING
01150 #define rf230_timetable_size 16
01151 TIMETABLE(rf230_timetable);
01152 TIMETABLE_AGGREGATE(aggregate_time, 10);
01153 #endif /* RF230_TIMETABLE_PROFILING */
01154 int
01155 rf230_interrupt(void)
01156 {
01157   /* Poll the receive process, unless the stack thinks the radio is off */
01158 #if RADIOALWAYSON
01159 if (RF230_receive_on) {
01160   DEBUGFLOW('+');
01161 #endif
01162 #if RF230_CONF_TIMESTAMPS
01163   interrupt_time = timesynch_time();
01164   interrupt_time_set = 1;
01165 #endif /* RF230_CONF_TIMESTAMPS */
01166 
01167   process_poll(&rf230_process);
01168   
01169 #if RF230_TIMETABLE_PROFILING
01170   timetable_clear(&rf230_timetable);
01171   TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt");
01172 #endif /* RF230_TIMETABLE_PROFILING */
01173 
01174   pending = 1;
01175   
01176 #if RADIOSTATS //TODO:This will double count buffered packets
01177   RF230_receivepackets++;
01178 #endif
01179 
01180 #if RADIOALWAYSON
01181 } else {
01182   DEBUGFLOW('-');
01183   rxframe[rxframe_head].length=0;
01184 }
01185 #endif
01186   return 1;
01187 }
01188 /*---------------------------------------------------------------------------*/
01189 /* Process to handle input packets
01190  * Receive interrupts cause this process to be polled
01191  * It calls the core MAC layer which calls rf230_read to get the packet
01192  * rf230processflag can be printed in the main idle loop for debugging
01193  */
01194 #if 0
01195 uint8_t rf230processflag;
01196 #define RF230PROCESSFLAG(arg) rf230processflag=arg
01197 #else
01198 #define RF230PROCESSFLAG(arg)
01199 #endif
01200 
01201 PROCESS_THREAD(rf230_process, ev, data)
01202 {
01203   int len;
01204   PROCESS_BEGIN();
01205   RF230PROCESSFLAG(99);
01206 
01207   while(1) {
01208     PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
01209     RF230PROCESSFLAG(42);
01210 #if RF230_TIMETABLE_PROFILING
01211     TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
01212 #endif /* RF230_TIMETABLE_PROFILING */
01213 
01214     pending = 0;
01215 
01216     packetbuf_clear();
01217     len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);        
01218     RF230PROCESSFLAG(1);
01219     if(len > 0) {
01220       packetbuf_set_datalen(len);
01221       RF230PROCESSFLAG(2);
01222       NETSTACK_RDC.input();
01223 #if RF230_TIMETABLE_PROFILING
01224       TIMETABLE_TIMESTAMP(rf230_timetable, "end");
01225       timetable_aggregate_compute_detailed(&aggregate_time,
01226                                            &rf230_timetable);
01227       timetable_clear(&rf230_timetable);
01228 #endif /* RF230_TIMETABLE_PROFILING */
01229     } else {
01230 #if RADIOSTATS
01231        RF230_receivefail++;
01232 #endif
01233     }
01234   }
01235 
01236   PROCESS_END();
01237 }
01238 /* Get packet from Radio if any, else return zero.
01239  * The two-byte checksum is appended but the returned length does not include it.
01240  * Frames are buffered in the interrupt routine so this routine
01241  * does not access the hardware or change its status
01242  */
01243 /*---------------------------------------------------------------------------*/
01244 static int
01245 rf230_read(void *buf, unsigned short bufsize)
01246 {
01247   uint8_t len,*framep;
01248 #if FOOTER_LEN
01249   uint8_t footer[FOOTER_LEN];
01250 #endif /* FOOTER_LEN */
01251 #if RF230_CONF_CHECKSUM
01252   uint16_t checksum;
01253 #endif /* RF230_CONF_CHECKSUM */
01254 #if RF230_CONF_TIMESTAMPS
01255   struct timestamp t;
01256 #endif /* RF230_CONF_TIMESTAMPS */
01257   /* The length includes the twp-byte checksum but not the LQI byte */
01258   len=rxframe[rxframe_head].length;
01259   if (len==0) {
01260 #if RADIOALWAYSON && DEBUGFLOWSIZE
01261    if (RF230_receive_on==0) {if (debugflow[debugflowsize-1]!='z') DEBUGFLOW('z');} //cxmac calls with radio off?
01262 #endif
01263     return 0;
01264   }
01265 
01266 #if RADIOALWAYSON
01267 if (RF230_receive_on) {
01268 #endif
01269 
01270 #if RF230_CONF_TIMESTAMPS
01271   if(interrupt_time_set) {
01272     rf230_time_of_arrival = interrupt_time;
01273     interrupt_time_set = 0;
01274   } else {
01275     rf230_time_of_arrival = 0;
01276   }
01277   rf230_time_of_departure = 0;
01278 #endif /* RF230_CONF_TIMESTAMPS */
01279 
01280 // PRINTSHORT("r%d",rxframe[rxframe_head].length);  
01281   PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe[rxframe_head].length,rxframe[rxframe_head].lqi,rxframe[rxframe_head].crc);
01282 #if DEBUG>1
01283  {
01284     uint8_t i;
01285     PRINTF("0000");
01286     for (i=0;i<rxframe[rxframe_head].length;i++) PRINTF(" %02x",rxframe[rxframe_head].data[i]);    
01287     PRINTF("\n");
01288   }
01289 #endif
01290 
01291 // GET_LOCK();
01292 
01293 //if(len > RF230_MAX_PACKET_LEN) {
01294   if(len > RF230_MAX_TX_FRAME_LENGTH) {
01295     /* Oops, we must be out of sync. */
01296     DEBUGFLOW('y');
01297     flushrx();
01298     RIMESTATS_ADD(badsynch);
01299 //    RELEASE_LOCK();
01300     return 0;
01301   }
01302 
01303   if(len <= AUX_LEN) {
01304     DEBUGFLOW('s');
01305     PRINTF("len <= AUX_LEN\n");
01306     flushrx();
01307     RIMESTATS_ADD(tooshort);
01308  //   RELEASE_LOCK();
01309     return 0;
01310   }
01311 
01312   if(len - AUX_LEN > bufsize) {
01313     DEBUGFLOW('b');
01314     PRINTF("len - AUX_LEN > bufsize\n");
01315     flushrx();
01316     RIMESTATS_ADD(toolong);
01317 //    RELEASE_LOCK();
01318     return 0;
01319   }
01320  /* Transfer the frame, stripping the footer, but copying the checksum */
01321   framep=&(rxframe[rxframe_head].data[0]);
01322   memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
01323   rf230_last_correlation = rxframe[rxframe_head].lqi;
01324 
01325   /* Clear the length field to allow buffering of the next packet */
01326   rxframe[rxframe_head].length=0;
01327   rxframe_head++;if (rxframe_head >= RF230_CONF_RX_BUFFERS) rxframe_head=0;
01328   /* If another packet has been buffered, schedule another receive poll */
01329   if (rxframe[rxframe_head].length) rf230_interrupt();
01330   
01331  /* Point to the checksum */
01332   framep+=len-AUX_LEN; 
01333 #if RF230_CONF_CHECKSUM
01334   memcpy(&checksum,framep,CHECKSUM_LEN);
01335 #endif /* RF230_CONF_CHECKSUM */
01336   framep+=CHECKSUM_LEN;
01337 #if RF230_CONF_TIMESTAMPS
01338   memcpy(&t,framep,TIMESTAMP_LEN);
01339 #endif /* RF230_CONF_TIMESTAMPS */
01340   framep+=TIMESTAMP_LEN;
01341 #if FOOTER_LEN
01342   memcpy(footer,framep,FOOTER_LEN);
01343 #endif
01344 #if RF230_CONF_CHECKSUM
01345   if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
01346     DEBUGFLOW('K');
01347     PRINTF("checksum failed 0x%04x != 0x%04x\n",
01348       checksum, crc16_data(buf, len - AUX_LEN, 0));
01349   }
01350 #if FOOTER_LEN
01351   if(footer[1] & FOOTER1_CRC_OK &&
01352      checksum == crc16_data(buf, len - AUX_LEN, 0)) {
01353 #endif
01354 #endif /* RF230_CONF_CHECKSUM */
01355 
01356 /* Get the received signal strength for the packet, 0-84 dB above rx threshold */
01357 #if 0   //more general
01358     rf230_last_rssi = rf230_get_raw_rssi();
01359 #else   //faster
01360 #if RF230_CONF_AUTOACK
01361  //   rf230_last_rssi = hal_subregister_read(SR_ED_LEVEL);  //0-84 resolution 1 dB
01362     rf230_last_rssi = hal_register_read(RG_PHY_ED_LEVEL);  //0-84, resolution 1 dB
01363 #else
01364 /* last_rssi will have been set at RX_START interrupt */
01365 //  rf230_last_rssi = 3*hal_subregister_read(SR_RSSI);    //0-28 resolution 3 dB
01366 #endif
01367 #endif /* speed vs. generality */
01368 
01369   /* Save the smallest rssi. The display routine can reset by setting it to zero */
01370   if ((rf230_smallest_rssi==0) || (rf230_last_rssi<rf230_smallest_rssi))
01371      rf230_smallest_rssi=rf230_last_rssi;
01372 
01373  //   rf230_last_correlation = rxframe[rxframe_head].lqi;
01374     packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
01375     packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
01376 
01377     RIMESTATS_ADD(llrx);
01378 
01379 #if RF230_CONF_TIMESTAMPS
01380     rf230_time_of_departure =
01381       t.time +
01382       setup_time_for_transmission +
01383       (total_time_for_transmission * (len - 2)) / total_transmission_len;
01384 
01385     rf230_authority_level_of_sender = t.authority_level;
01386 
01387     packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
01388 #endif /* RF230_CONF_TIMESTAMPS */
01389 
01390 #if RF230_CONF_CHECKSUM
01391 #if FOOTER_LEN
01392   } else {
01393     DEBUGFLOW('X');
01394     PRINTF("bad crc");
01395     RIMESTATS_ADD(badcrc);
01396     len = AUX_LEN;
01397   }
01398 #endif
01399 #endif
01400 
01401 #ifdef RF230BB_HOOK_RX_PACKET
01402   RF230BB_HOOK_RX_PACKET(buf,len);
01403 #endif
01404 
01405   /* Here return just the data length. The checksum is however still in the buffer for packet sniffing */
01406   return len - AUX_LEN;
01407 
01408 #if RADIOALWAYSON
01409 } else {
01410    DEBUGFLOW('R');  //Stack thought radio was off
01411    return 0;
01412 }
01413 #endif
01414 }
01415 /*---------------------------------------------------------------------------*/
01416 void
01417 rf230_set_txpower(uint8_t power)
01418 {
01419   GET_LOCK();
01420   set_txpower(power);
01421   RELEASE_LOCK();
01422 }
01423 /*---------------------------------------------------------------------------*/
01424 uint8_t
01425 rf230_get_txpower(void)
01426 {
01427         uint8_t power = TX_PWR_UNDEFINED;
01428         if (radio_is_sleeping()) {
01429                 PRINTF("rf230_get_txpower:Sleeping");
01430         } else {
01431                 power = hal_subregister_read(SR_TX_PWR);
01432         }
01433         return power;
01434 }
01435 
01436 /*---------------------------------------------------------------------------*/
01437 uint8_t
01438 rf230_get_raw_rssi(void)
01439 {
01440   uint8_t rssi,state;
01441   bool radio_was_off = 0;
01442 
01443   /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/
01444   if(!RF230_receive_on) {
01445     radio_was_off = 1;
01446     rf230_on();
01447   }
01448 
01449 /* The energy detect register is used in extended mode (since RSSI will read 0) */
01450 /* The rssi register is multiplied by 3 to a consistent value from either register */
01451   state=radio_get_trx_state();
01452   if ((state==RX_AACK_ON) || (state==BUSY_RX_AACK)) {
01453  //  rssi = hal_subregister_read(SR_ED_LEVEL);  //0-84, resolution 1 dB
01454      rssi = hal_register_read(RG_PHY_ED_LEVEL);  //0-84, resolution 1 dB
01455   } else {
01456 #if 0   // 3-clock shift and add is faster on machines with no hardware multiply
01457 /* avr-gcc may have an -Os bug that uses the general subroutine for multiplying by 3 */
01458      rssi = hal_subregister_read(SR_RSSI);      //0-28, resolution 3 dB
01459      rssi = (rssi << 1)  + rssi;                //*3
01460 #else  // 1 or 2 clock multiply, or compiler with correct optimization
01461      rssi = 3 * hal_subregister_read(SR_RSSI);
01462 #endif
01463 
01464   }
01465 
01466   if(radio_was_off) {
01467     rf230_off();
01468   }
01469   return rssi;
01470 }
01471 
01472 /*---------------------------------------------------------------------------*/
01473 static int
01474 rf230_cca(void)
01475 {
01476   int cca;
01477   int radio_was_off = 0;
01478 
01479   /* If the radio is locked by an underlying thread (because we are
01480      being invoked through an interrupt), we preted that the coast is
01481      clear (i.e., no packet is currently being transmitted by a
01482      neighbor). */
01483   if(locked) {
01484     return 1;
01485   }
01486   
01487   if(!RF230_receive_on) {
01488     radio_was_off = 1;
01489     rf230_on();
01490   }
01491 
01492   DEBUGFLOW('c');
01493   /* CCA Mode Mode 1=Energy above threshold  2=Carrier sense only  3=Both 0=Either (RF231 only) */
01494   /* Use the current mode. Note triggering a manual CCA is not recommended in extended mode */
01495 //hal_subregister_write(SR_CCA_MODE,1);
01496 
01497   /* Start the CCA, wait till done, return result */
01498   hal_subregister_write(SR_CCA_REQUEST,1);
01499   delay_us(TIME_CCA);
01500 //while ((hal_register_read(RG_TRX_STATUS) & 0x80) == 0 ) {continue;}
01501   while (!hal_subregister_read(SR_CCA_DONE)) {continue;}
01502   cca=hal_subregister_read(SR_CCA_STATUS);
01503   
01504   if(radio_was_off) {
01505     rf230_off();
01506   }
01507   return cca;
01508 }
01509 /*---------------------------------------------------------------------------*/
01510 int
01511 rf230_receiving_packet(void)
01512 {
01513   uint8_t radio_state;
01514   radio_state = hal_subregister_read(SR_TRX_STATUS);
01515   if ((radio_state==BUSY_RX) || (radio_state==BUSY_RX_AACK)) {
01516     DEBUGFLOW('B');
01517     return 1;
01518   } else {
01519     return 0;
01520   }
01521 }
01522 /*---------------------------------------------------------------------------*/
01523 static int
01524 pending_packet(void)
01525 {
01526   if (pending) DEBUGFLOW('p');
01527   return pending;
01528 }
01529 /*---------------------------------------------------------------------------*/
01530 #if RF230_CONF_SNEEZER && JACKDAW
01531 /* See A.2 in the datasheet for the sequence needed.
01532  * This version for RF230 only, hence Jackdaw.
01533  * A full reset seems not necessary and allows keeping the pan address, etc.
01534  * for an easy reset back to network mode.
01535  */
01536 void rf230_start_sneeze(void) {
01537 //write buffer with random data for uniform spectral noise
01538 
01539 //uint8_t txpower = hal_register_read(0x05);  //save auto_crc bit and power
01540 //  hal_set_rst_low();
01541 //  hal_set_slptr_low();
01542 //  delay_us(TIME_RESET);
01543 //  hal_set_rst_high();
01544     hal_register_write(0x0E, 0x01);
01545     hal_register_write(0x02, 0x03);
01546     hal_register_write(0x03, 0x10);
01547  // hal_register_write(0x08, 0x20+26);    //channel 26
01548     hal_subregister_write(SR_CCA_MODE,1); //leave channel unchanged
01549 
01550  // hal_register_write(0x05, 0x00);       //output power maximum
01551     hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);  //clear AUTO_CRC, leave output power unchanged
01552  
01553     hal_register_read(0x01);             //should be trx-off state=0x08  
01554     hal_frame_write(buffer, 127);        //maximum length, random for spectral noise 
01555 
01556     hal_register_write(0x36,0x0F);       //configure continuous TX
01557     hal_register_write(0x3D,0x00);       //Modulated frame, other options are:
01558 //  hal_register_write(RG_TX_2,0x10);    //CW -2MHz
01559 //  hal_register_write(RG_TX_2,0x80);    //CW -500KHz
01560 //  hal_register_write(RG_TX_2,0xC0);    //CW +500KHz
01561 
01562     DDRB  |= 1<<7;                       //Raven USB stick has PB7 connected to the RF230 TST pin.   
01563     PORTB |= 1<<7;                       //Raise it to enable continuous TX Test Mode.
01564 
01565     hal_register_write(0x02,0x09);       //Set TRX_STATE to PLL_ON
01566     delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
01567     delay_us(TIME_PLL_LOCK);
01568     delay_us(TIME_PLL_LOCK);
01569  // while (hal_register_read(0x0f)!=1) {continue;}  //wait for pll lock-hangs
01570     hal_register_write(0x02,0x02);       //Set TRX_STATE to TX_START
01571 }
01572 #endif

Generated on Mon Apr 11 14:23:37 2011 for Contiki 2.5 by  doxygen 1.6.1