dakrf230bb.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 #if RF230_CONF_CCA_THRES < -91
00746 #warning RF230_CONF_CCA_THRES below hardware limit, setting to -91dBm
00747   hal_subregister_write(SR_CCA_ED_THRES,0);  
00748 #elif RF230_CONF_CCA_THRES > -61
00749 #warning RF230_CONF_CCA_THRES above hardware limit, setting to -61dBm
00750   hal_subregister_write(SR_CCA_ED_THRES,15);  
00751 #else
00752   hal_subregister_write(SR_CCA_ED_THRES,(RF230_CONF_CCA_THRES+91)/2);  
00753 #endif
00754 
00755   /* Use automatic CRC unless manual is specified */
00756 #if RF230_CONF_CHECKSUM
00757   hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
00758 #else
00759   hal_subregister_write(SR_TX_AUTO_CRC_ON, 1);
00760 #endif
00761 
00762 /* Limit tx power for testing miniature Raven mesh */
00763 #ifdef RF230_MAX_TX_POWER
00764   set_txpower(RF230_MAX_TX_POWER);  //0=3dbm 15=-17.2dbm
00765 #endif
00766 }
00767 /*---------------------------------------------------------------------------*/
00768 static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH+AUX_LEN];
00769 static int
00770 rf230_transmit(unsigned short payload_len)
00771 {
00772   int txpower;
00773   uint8_t total_len;
00774   uint8_t radiowason;
00775   uint8_t tx_result;
00776 #if RF230_CONF_TIMESTAMPS
00777   struct timestamp timestamp;
00778 #endif /* RF230_CONF_TIMESTAMPS */
00779 
00780   GET_LOCK();
00781 //  DEBUGFLOW('T');
00782 
00783   /* Save receiver state */
00784   radiowason=RF230_receive_on;
00785 
00786   /* If radio is sleeping we have to turn it on first */
00787   /* This automatically does the PLL calibrations */
00788   if (RF230_sleeping) {
00789     hal_set_slptr_low();
00790  //   delay_us(TIME_SLEEP_TO_TRX_OFF);
00791     RF230_sleeping=0;
00792   } else {
00793 #if RADIOCALIBRATE
00794   /* If on, do periodic calibration. See clock.c */
00795     if (rf230_calibrate) {
00796       hal_subregister_write(SR_PLL_CF_START,1);   //takes 80us max
00797       hal_subregister_write(SR_PLL_DCU_START,1); //takes 6us, concurrently
00798       rf230_calibrate=0;
00799       rf230_calibrated=1;
00800       delay_us(80); //?
00801     }
00802 #endif
00803   }
00804  
00805   /* Wait for any previous operation or state transition to finish */
00806   rf230_waitidle();
00807 
00808   /* Prepare to transmit */
00809 #if RF230_CONF_AUTORETRIES
00810   radio_set_trx_state(TX_ARET_ON);
00811 #else
00812   radio_set_trx_state(PLL_ON);
00813 #endif
00814 
00815   txpower = 0;
00816   
00817   if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00818     /* Remember the current transmission power */
00819     txpower = rf230_get_txpower();
00820     /* Set the specified transmission power */
00821     set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
00822   }
00823 
00824   total_len = payload_len + AUX_LEN;
00825 
00826 #if RF230_CONF_TIMESTAMPS
00827   rtimer_clock_t txtime = timesynch_time();
00828 #endif /* RF230_CONF_TIMESTAMPS */
00829 #if defined(__AVR_ATmega128RFA1__)
00830 /* No interrupts across frame download! */
00831   cli();
00832 /* slow down the transmit? */
00833  //   delay_us(500);
00834 #endif
00835  /* Toggle the SLP_TR pin to initiate the frame transmission */
00836   hal_set_slptr_high();
00837   hal_set_slptr_low();
00838   hal_frame_write(buffer, total_len);
00839 #if defined(__AVR_ATmega128RFA1__)
00840  sei();
00841 #endif
00842   PRINTF("rf230_transmit:\n");
00843 #if DEBUG>1
00844 /* Note the dumped packet will have a zero checksum unless compiled with RF230_CONF_CHECKSUM
00845  * since we don't know what it will be if calculated by the hardware.
00846  */
00847   {
00848     uint8_t i;
00849     PRINTF("0000");       //Start a new wireshark packet
00850     for (i=0;i<total_len;i++) PRINTF(" %02x",buffer[i]);
00851     PRINTF("\n");
00852   }
00853 #endif
00854 
00855   if(RF230_receive_on) {
00856     ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00857   }
00858   ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00859 
00860 #if RADIOSTATS
00861   RF230_sendpackets++;
00862 #endif
00863  
00864  /* We wait until transmission has ended so that we get an
00865      accurate measurement of the transmission time.*/
00866   rf230_waitidle();
00867 
00868  /* Get the transmission result */  
00869 #if RF230_CONF_AUTORETRIES
00870   tx_result = hal_subregister_read(SR_TRAC_STATUS);
00871 #else
00872   tx_result=0;
00873 #endif
00874 
00875 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
00876   ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
00877 #endif
00878 
00879  /* Restore the transmission power */
00880  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00881     set_txpower(txpower & 0xff);
00882   }
00883  
00884   /* Restore receive mode */
00885   if(radiowason) {
00886  //       DEBUGFLOW('m');
00887     on();
00888   }
00889 
00890 #if RF230_CONF_TIMESTAMPS
00891   setup_time_for_transmission = txtime - timestamp.time;
00892 
00893   if(num_transmissions < 10000) {
00894     total_time_for_transmission += timesynch_time() - txtime;
00895     total_transmission_len += total_len;
00896     num_transmissions++;
00897   }
00898 
00899 #endif /* RF230_CONF_TIMESTAMPS */
00900 
00901   ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00902   if(RF230_receive_on) {
00903     ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00904   } else {
00905 #if RADIOALWAYSON
00906     /* Enable reception */
00907     on();
00908 #else
00909     /* Go to lower power TRX_OFF state (turn off PLL) */
00910     hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00911 #endif
00912   }
00913 
00914   RELEASE_LOCK();
00915   if (tx_result==1) {               //success, data pending from adressee
00916     tx_result=0;                    //Just show success?
00917   } else if (tx_result==3) {        //CSMA channel access failure
00918     RIMESTATS_ADD(contentiondrop);
00919     PRINTF("rf230_transmit: Transmission never started\n");
00920 //} else if (tx_result==5) {        //Expected ACK, none received
00921 //} else if (tx_result==7) {        //Invalid (Can't happen since waited for idle above?)
00922   }
00923 
00924   return tx_result;
00925 }
00926 /*---------------------------------------------------------------------------*/
00927 static int
00928 rf230_prepare(const void *payload, unsigned short payload_len)
00929 {
00930   int ret = 0;
00931   uint8_t total_len,*pbuf;
00932 #if RF230_CONF_TIMESTAMPS
00933   struct timestamp timestamp;
00934 #endif /* RF230_CONF_TIMESTAMPS */
00935 #if RF230_CONF_CHECKSUM
00936   uint16_t checksum;
00937 #endif /* RF230_CONF_CHECKSUM */
00938 
00939   GET_LOCK();
00940 //    DEBUGFLOW('P');
00941 
00942 //  PRINTF("rf230: sending %d bytes\n", payload_len);
00943 //  PRINTSHORT("s%d ",payload_len);
00944 
00945   RIMESTATS_ADD(lltx);
00946 
00947 #if RF230_CONF_CHECKSUM
00948   checksum = crc16_data(payload, payload_len, 0);
00949 #endif /* RF230_CONF_CHECKSUM */
00950  
00951   /* Copy payload to RAM buffer */
00952   total_len = payload_len + AUX_LEN;
00953   if (total_len > RF230_MAX_TX_FRAME_LENGTH){
00954 #if RADIOSTATS
00955     RF230_sendfail++;
00956 #endif
00957 #if DEBUG
00958     printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH);
00959 #endif
00960     ret = -1;
00961         goto bail;
00962   }
00963   pbuf=&buffer[0];
00964   memcpy(pbuf,payload,payload_len);
00965   pbuf+=payload_len;
00966 
00967 #if RF230_CONF_CHECKSUM
00968   memcpy(pbuf,&checksum,CHECKSUM_LEN);
00969   pbuf+=CHECKSUM_LEN;
00970 #endif /* RF230_CONF_CHECKSUM */
00971 
00972 #if RF230_CONF_TIMESTAMPS
00973   timestamp.authority_level = timesynch_authority_level();
00974   timestamp.time = timesynch_time();
00975   memcpy(pbuf,&timestamp,TIMESTAMP_LEN);
00976   pbuf+=TIMESTAMP_LEN;
00977 #endif /* RF230_CONF_TIMESTAMPS */
00978 /*------------------------------------------------------------*/  
00979 
00980 #ifdef RF230BB_HOOK_TX_PACKET
00981 #if !RF230_CONF_CHECKSUM
00982   { // Add a checksum before we log the packet out
00983     uint16_t checksum;
00984     checksum = crc16_data(payload, payload_len, 0);
00985     memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN);
00986   }
00987 #endif /* RF230_CONF_CHECKSUM */
00988   RF230BB_HOOK_TX_PACKET(buffer,total_len);
00989 #endif
00990   
00991 
00992 bail:
00993   RELEASE_LOCK();
00994   return ret;
00995 }
00996 /*---------------------------------------------------------------------------*/
00997 static int
00998 rf230_send(const void *payload, unsigned short payload_len)
00999 {
01000         int ret = 0;
01001 
01002 #ifdef RF230BB_HOOK_IS_SEND_ENABLED
01003         if(!RF230BB_HOOK_IS_SEND_ENABLED()) {
01004                 goto bail;
01005         }
01006 #endif
01007         
01008         if((ret=rf230_prepare(payload, payload_len))) {
01009 #if DEBUG
01010                 printf_P(PSTR("rf230_send: Unable to send, prep failed (%d)\n"),ret);
01011 #endif
01012                 goto bail;
01013         }
01014 
01015         ret = rf230_transmit(payload_len);
01016         
01017 bail:
01018 #if RADIOSTATS
01019     if (ret) RF230_sendfail++;
01020 #endif
01021         return ret;
01022 }
01023 /*---------------------------------------------------------------------------*/
01024 int
01025 rf230_off(void)
01026 {
01027   /* Don't do anything if we are already turned off. */
01028   if(RF230_receive_on == 0) {
01029     return 1;
01030   }
01031 
01032   /* If we are called when the driver is locked, we indicate that the
01033      radio should be turned off when the lock is unlocked. */
01034   if(locked) {
01035     lock_off = 1;
01036     return 1;
01037   }
01038 
01039   /* If we are currently receiving a packet
01040      we don't actually switch the radio off now, but signal that the
01041      driver should switch off the radio once the packet has been
01042      received and processed, by setting the 'lock_off' variable. */
01043   if (!rf230_isidle()) {
01044 // if (radio_get_trx_state()==BUSY_RX) {
01045     lock_off = 1;
01046     return 1;
01047   }
01048 
01049   off();
01050   return 1;
01051 }
01052 /*---------------------------------------------------------------------------*/
01053 int
01054 rf230_on(void)
01055 {
01056   if(RF230_receive_on) {
01057     return 1;
01058   }
01059   if(locked) {
01060     DEBUGFLOW('L');
01061     lock_on = 1;
01062     return 1;
01063   }
01064 
01065   on();
01066   return 1;
01067 }
01068 /*---------------------------------------------------------------------------*/
01069 uint8_t
01070 rf230_get_channel(void)
01071 {
01072 //jackdaw reads zero channel, raven reads correct channel?
01073 //return hal_subregister_read(SR_CHANNEL);
01074   return channel;
01075 }
01076 /*---------------------------------------------------------------------------*/
01077 void
01078 rf230_set_channel(uint8_t c)
01079 {
01080  /* Wait for any transmission to end. */
01081   PRINTF("rf230: Set Channel %u\n",c);
01082   rf230_waitidle();
01083   channel=c;
01084   hal_subregister_write(SR_CHANNEL, c);
01085 }
01086 /*---------------------------------------------------------------------------*/
01087 void
01088 rf230_listen_channel(uint8_t c)
01089 {
01090  /* Same as set channel but forces RX_ON state for sniffer or energy scan */
01091 //  PRINTF("rf230: Listen Channel %u\n",c);
01092   rf230_set_channel(c);
01093   radio_set_trx_state(RX_ON);
01094 }
01095 /*---------------------------------------------------------------------------*/
01096 void
01097 rf230_set_pan_addr(unsigned pan,
01098                     unsigned addr,
01099                     const uint8_t ieee_addr[8])
01100 //rf230_set_pan_addr(uint16_t pan,uint16_t addr,uint8_t *ieee_addr)
01101 {
01102   PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
01103   
01104   uint8_t abyte;
01105   abyte = pan & 0xFF;
01106   hal_register_write(RG_PAN_ID_0,abyte);
01107   abyte = (pan >> 8*1) & 0xFF;
01108   hal_register_write(RG_PAN_ID_1, abyte);
01109 
01110   abyte = addr & 0xFF;
01111   hal_register_write(RG_SHORT_ADDR_0, abyte);
01112   abyte = (addr >> 8*1) & 0xFF;
01113   hal_register_write(RG_SHORT_ADDR_1, abyte);  
01114 
01115   if (ieee_addr != NULL) {
01116     PRINTF("MAC=%x",*ieee_addr);
01117     hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++);
01118     PRINTF(":%x",*ieee_addr);
01119     hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++);
01120     PRINTF(":%x",*ieee_addr);
01121     hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++);
01122     PRINTF(":%x",*ieee_addr);
01123     hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++);
01124     PRINTF(":%x",*ieee_addr);
01125     hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++);
01126     PRINTF(":%x",*ieee_addr);
01127     hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++);
01128     PRINTF(":%x",*ieee_addr);
01129     hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++);
01130     PRINTF(":%x",*ieee_addr);
01131     hal_register_write(RG_IEEE_ADDR_0, *ieee_addr);
01132     PRINTF("\n");
01133   }
01134 }
01135 /*---------------------------------------------------------------------------*/
01136 /*
01137  * Interrupt leaves frame intact in FIFO.
01138  */
01139 #if RF230_CONF_TIMESTAMPS
01140 static volatile rtimer_clock_t interrupt_time;
01141 static volatile int interrupt_time_set;
01142 #endif /* RF230_CONF_TIMESTAMPS */
01143 #if RF230_TIMETABLE_PROFILING
01144 #define rf230_timetable_size 16
01145 TIMETABLE(rf230_timetable);
01146 TIMETABLE_AGGREGATE(aggregate_time, 10);
01147 #endif /* RF230_TIMETABLE_PROFILING */
01148 int
01149 rf230_interrupt(void)
01150 {
01151   /* Poll the receive process, unless the stack thinks the radio is off */
01152 #if RADIOALWAYSON
01153 if (RF230_receive_on) {
01154   DEBUGFLOW('+');
01155 #endif
01156 #if RF230_CONF_TIMESTAMPS
01157   interrupt_time = timesynch_time();
01158   interrupt_time_set = 1;
01159 #endif /* RF230_CONF_TIMESTAMPS */
01160 
01161   process_poll(&rf230_process);
01162   
01163 #if RF230_TIMETABLE_PROFILING
01164   timetable_clear(&rf230_timetable);
01165   TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt");
01166 #endif /* RF230_TIMETABLE_PROFILING */
01167 
01168   pending = 1;
01169   
01170 #if RADIOSTATS //TODO:This will double count buffered packets
01171   RF230_receivepackets++;
01172 #endif
01173 
01174 #if RADIOALWAYSON
01175 } else {
01176   DEBUGFLOW('-');
01177   rxframe[rxframe_head].length=0;
01178 }
01179 #endif
01180   return 1;
01181 }
01182 /*---------------------------------------------------------------------------*/
01183 /* Process to handle input packets
01184  * Receive interrupts cause this process to be polled
01185  * It calls the core MAC layer which calls rf230_read to get the packet
01186  * rf230processflag can be printed in the main idle loop for debugging
01187  */
01188 #if 0
01189 uint8_t rf230processflag;
01190 #define RF230PROCESSFLAG(arg) rf230processflag=arg
01191 #else
01192 #define RF230PROCESSFLAG(arg)
01193 #endif
01194 
01195 PROCESS_THREAD(rf230_process, ev, data)
01196 {
01197   int len;
01198   PROCESS_BEGIN();
01199   RF230PROCESSFLAG(99);
01200 
01201   while(1) {
01202     PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
01203     RF230PROCESSFLAG(42);
01204 #if RF230_TIMETABLE_PROFILING
01205     TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
01206 #endif /* RF230_TIMETABLE_PROFILING */
01207 
01208     pending = 0;
01209 
01210     packetbuf_clear();
01211     len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);        
01212     RF230PROCESSFLAG(1);
01213     if(len > 0) {
01214       packetbuf_set_datalen(len);
01215       RF230PROCESSFLAG(2);
01216       NETSTACK_RDC.input();
01217 #if RF230_TIMETABLE_PROFILING
01218       TIMETABLE_TIMESTAMP(rf230_timetable, "end");
01219       timetable_aggregate_compute_detailed(&aggregate_time,
01220                                            &rf230_timetable);
01221       timetable_clear(&rf230_timetable);
01222 #endif /* RF230_TIMETABLE_PROFILING */
01223     } else {
01224 #if RADIOSTATS
01225        RF230_receivefail++;
01226 #endif
01227     }
01228   }
01229 
01230   PROCESS_END();
01231 }
01232 /* Get packet from Radio if any, else return zero.
01233  * The two-byte checksum is appended but the returned length does not include it.
01234  * Frames are buffered in the interrupt routine so this routine
01235  * does not access the hardware or change its status
01236  */
01237 /*---------------------------------------------------------------------------*/
01238 static int
01239 rf230_read(void *buf, unsigned short bufsize)
01240 {
01241   uint8_t len,*framep;
01242 #if FOOTER_LEN
01243   uint8_t footer[FOOTER_LEN];
01244 #endif /* FOOTER_LEN */
01245 #if RF230_CONF_CHECKSUM
01246   uint16_t checksum;
01247 #endif /* RF230_CONF_CHECKSUM */
01248 #if RF230_CONF_TIMESTAMPS
01249   struct timestamp t;
01250 #endif /* RF230_CONF_TIMESTAMPS */
01251   /* The length includes the twp-byte checksum but not the LQI byte */
01252   len=rxframe[rxframe_head].length;
01253   if (len==0) {
01254 #if RADIOALWAYSON && DEBUGFLOWSIZE
01255    if (RF230_receive_on==0) {if (debugflow[debugflowsize-1]!='z') DEBUGFLOW('z');} //cxmac calls with radio off?
01256 #endif
01257     return 0;
01258   }
01259 
01260 #if RADIOALWAYSON
01261 if (RF230_receive_on) {
01262 #endif
01263 
01264 #if RF230_CONF_TIMESTAMPS
01265   if(interrupt_time_set) {
01266     rf230_time_of_arrival = interrupt_time;
01267     interrupt_time_set = 0;
01268   } else {
01269     rf230_time_of_arrival = 0;
01270   }
01271   rf230_time_of_departure = 0;
01272 #endif /* RF230_CONF_TIMESTAMPS */
01273 
01274 // PRINTSHORT("r%d",rxframe[rxframe_head].length);  
01275   PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe[rxframe_head].length,rxframe[rxframe_head].lqi,rxframe[rxframe_head].crc);
01276 #if DEBUG>1
01277  {
01278     uint8_t i;
01279     PRINTF("0000");
01280     for (i=0;i<rxframe[rxframe_head].length;i++) PRINTF(" %02x",rxframe[rxframe_head].data[i]);    
01281     PRINTF("\n");
01282   }
01283 #endif
01284 
01285 // GET_LOCK();
01286 
01287 //if(len > RF230_MAX_PACKET_LEN) {
01288   if(len > RF230_MAX_TX_FRAME_LENGTH) {
01289     /* Oops, we must be out of sync. */
01290     DEBUGFLOW('y');
01291     flushrx();
01292     RIMESTATS_ADD(badsynch);
01293 //    RELEASE_LOCK();
01294     return 0;
01295   }
01296 
01297   if(len <= AUX_LEN) {
01298     DEBUGFLOW('s');
01299     PRINTF("len <= AUX_LEN\n");
01300     flushrx();
01301     RIMESTATS_ADD(tooshort);
01302  //   RELEASE_LOCK();
01303     return 0;
01304   }
01305 
01306   if(len - AUX_LEN > bufsize) {
01307     DEBUGFLOW('b');
01308     PRINTF("len - AUX_LEN > bufsize\n");
01309     flushrx();
01310     RIMESTATS_ADD(toolong);
01311 //    RELEASE_LOCK();
01312     return 0;
01313   }
01314  /* Transfer the frame, stripping the footer, but copying the checksum */
01315   framep=&(rxframe[rxframe_head].data[0]);
01316   memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
01317   rf230_last_correlation = rxframe[rxframe_head].lqi;
01318 
01319   /* Clear the length field to allow buffering of the next packet */
01320   rxframe[rxframe_head].length=0;
01321   rxframe_head++;if (rxframe_head >= RF230_CONF_RX_BUFFERS) rxframe_head=0;
01322   /* If another packet has been buffered, schedule another receive poll */
01323   if (rxframe[rxframe_head].length) rf230_interrupt();
01324   
01325  /* Point to the checksum */
01326   framep+=len-AUX_LEN; 
01327 #if RF230_CONF_CHECKSUM
01328   memcpy(&checksum,framep,CHECKSUM_LEN);
01329 #endif /* RF230_CONF_CHECKSUM */
01330   framep+=CHECKSUM_LEN;
01331 #if RF230_CONF_TIMESTAMPS
01332   memcpy(&t,framep,TIMESTAMP_LEN);
01333 #endif /* RF230_CONF_TIMESTAMPS */
01334   framep+=TIMESTAMP_LEN;
01335 #if FOOTER_LEN
01336   memcpy(footer,framep,FOOTER_LEN);
01337 #endif
01338 #if RF230_CONF_CHECKSUM
01339   if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
01340     DEBUGFLOW('K');
01341     PRINTF("checksum failed 0x%04x != 0x%04x\n",
01342       checksum, crc16_data(buf, len - AUX_LEN, 0));
01343   }
01344 #if FOOTER_LEN
01345   if(footer[1] & FOOTER1_CRC_OK &&
01346      checksum == crc16_data(buf, len - AUX_LEN, 0)) {
01347 #endif
01348 #endif /* RF230_CONF_CHECKSUM */
01349 
01350 /* Get the received signal strength for the packet, 0-84 dB above rx threshold */
01351 #if 0   //more general
01352     rf230_last_rssi = rf230_get_raw_rssi();
01353 #else   //faster
01354 #if RF230_CONF_AUTOACK
01355  //   rf230_last_rssi = hal_subregister_read(SR_ED_LEVEL);  //0-84 resolution 1 dB
01356     rf230_last_rssi = hal_register_read(RG_PHY_ED_LEVEL);  //0-84, resolution 1 dB
01357 #else
01358 /* last_rssi will have been set at RX_START interrupt */
01359 //  rf230_last_rssi = 3*hal_subregister_read(SR_RSSI);    //0-28 resolution 3 dB
01360 #endif
01361 #endif /* speed vs. generality */
01362 
01363   /* Save the smallest rssi. The display routine can reset by setting it to zero */
01364   if ((rf230_smallest_rssi==0) || (rf230_last_rssi<rf230_smallest_rssi))
01365      rf230_smallest_rssi=rf230_last_rssi;
01366 
01367  //   rf230_last_correlation = rxframe[rxframe_head].lqi;
01368     packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
01369     packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
01370 
01371     RIMESTATS_ADD(llrx);
01372 
01373 #if RF230_CONF_TIMESTAMPS
01374     rf230_time_of_departure =
01375       t.time +
01376       setup_time_for_transmission +
01377       (total_time_for_transmission * (len - 2)) / total_transmission_len;
01378 
01379     rf230_authority_level_of_sender = t.authority_level;
01380 
01381     packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
01382 #endif /* RF230_CONF_TIMESTAMPS */
01383 
01384 #if RF230_CONF_CHECKSUM
01385 #if FOOTER_LEN
01386   } else {
01387     DEBUGFLOW('X');
01388     PRINTF("bad crc");
01389     RIMESTATS_ADD(badcrc);
01390     len = AUX_LEN;
01391   }
01392 #endif
01393 #endif
01394 
01395 #ifdef RF230BB_HOOK_RX_PACKET
01396   RF230BB_HOOK_RX_PACKET(buf,len);
01397 #endif
01398 
01399   /* Here return just the data length. The checksum is however still in the buffer for packet sniffing */
01400   return len - AUX_LEN;
01401 
01402 #if RADIOALWAYSON
01403 } else {
01404    DEBUGFLOW('R');  //Stack thought radio was off
01405    return 0;
01406 }
01407 #endif
01408 }
01409 /*---------------------------------------------------------------------------*/
01410 void
01411 rf230_set_txpower(uint8_t power)
01412 {
01413   GET_LOCK();
01414   set_txpower(power);
01415   RELEASE_LOCK();
01416 }
01417 /*---------------------------------------------------------------------------*/
01418 uint8_t
01419 rf230_get_txpower(void)
01420 {
01421         uint8_t power = TX_PWR_UNDEFINED;
01422         if (radio_is_sleeping()) {
01423                 PRINTF("rf230_get_txpower:Sleeping");
01424         } else {
01425                 power = hal_subregister_read(SR_TX_PWR);
01426         }
01427         return power;
01428 }
01429 
01430 /*---------------------------------------------------------------------------*/
01431 uint8_t
01432 rf230_get_raw_rssi(void)
01433 {
01434   uint8_t rssi,state;
01435   bool radio_was_off = 0;
01436 
01437   /*The RSSI measurement should only be done in RX_ON or BUSY_RX.*/
01438   if(!RF230_receive_on) {
01439     radio_was_off = 1;
01440     rf230_on();
01441   }
01442 
01443 /* The energy detect register is used in extended mode (since RSSI will read 0) */
01444 /* The rssi register is multiplied by 3 to a consistent value from either register */
01445   state=radio_get_trx_state();
01446   if ((state==RX_AACK_ON) || (state==BUSY_RX_AACK)) {
01447  //  rssi = hal_subregister_read(SR_ED_LEVEL);  //0-84, resolution 1 dB
01448      rssi = hal_register_read(RG_PHY_ED_LEVEL);  //0-84, resolution 1 dB
01449   } else {
01450 #if 0   // 3-clock shift and add is faster on machines with no hardware multiply
01451 /* avr-gcc may have an -Os bug that uses the general subroutine for multiplying by 3 */
01452      rssi = hal_subregister_read(SR_RSSI);      //0-28, resolution 3 dB
01453      rssi = (rssi << 1)  + rssi;                //*3
01454 #else  // 1 or 2 clock multiply, or compiler with correct optimization
01455      rssi = 3 * hal_subregister_read(SR_RSSI);
01456 #endif
01457 
01458   }
01459 
01460   if(radio_was_off) {
01461     rf230_off();
01462   }
01463   return rssi;
01464 }
01465 
01466 /*---------------------------------------------------------------------------*/
01467 static int
01468 rf230_cca(void)
01469 {
01470   int cca;
01471   int radio_was_off = 0;
01472 
01473   /* If the radio is locked by an underlying thread (because we are
01474      being invoked through an interrupt), we preted that the coast is
01475      clear (i.e., no packet is currently being transmitted by a
01476      neighbor). */
01477   if(locked) {
01478     return 1;
01479   }
01480   
01481   if(!RF230_receive_on) {
01482     radio_was_off = 1;
01483     rf230_on();
01484   }
01485 
01486   DEBUGFLOW('c');
01487   /* CCA Mode Mode 1=Energy above threshold  2=Carrier sense only  3=Both 0=Either (RF231 only) */
01488   /* Use the current mode. Note triggering a manual CCA is not recommended in extended mode */
01489 //hal_subregister_write(SR_CCA_MODE,1);
01490 
01491   /* Start the CCA, wait till done, return result */
01492   hal_subregister_write(SR_CCA_REQUEST,1);
01493   delay_us(TIME_CCA);
01494 //while ((hal_register_read(RG_TRX_STATUS) & 0x80) == 0 ) {continue;}
01495   while (!hal_subregister_read(SR_CCA_DONE)) {continue;}
01496   cca=hal_subregister_read(SR_CCA_STATUS);
01497   
01498   if(radio_was_off) {
01499     rf230_off();
01500   }
01501   return cca;
01502 }
01503 /*---------------------------------------------------------------------------*/
01504 int
01505 rf230_receiving_packet(void)
01506 {
01507   uint8_t radio_state;
01508   radio_state = hal_subregister_read(SR_TRX_STATUS);
01509   if ((radio_state==BUSY_RX) || (radio_state==BUSY_RX_AACK)) {
01510     DEBUGFLOW('B');
01511     return 1;
01512   } else {
01513     return 0;
01514   }
01515 }
01516 /*---------------------------------------------------------------------------*/
01517 static int
01518 pending_packet(void)
01519 {
01520   if (pending) DEBUGFLOW('p');
01521   return pending;
01522 }
01523 /*---------------------------------------------------------------------------*/
01524 #if RF230_CONF_SNEEZER && JACKDAW
01525 /* See A.2 in the datasheet for the sequence needed.
01526  * This version for RF230 only, hence Jackdaw.
01527  * A full reset seems not necessary and allows keeping the pan address, etc.
01528  * for an easy reset back to network mode.
01529  */
01530 void rf230_start_sneeze(void) {
01531 //write buffer with random data for uniform spectral noise
01532 
01533 //uint8_t txpower = hal_register_read(0x05);  //save auto_crc bit and power
01534 //  hal_set_rst_low();
01535 //  hal_set_slptr_low();
01536 //  delay_us(TIME_RESET);
01537 //  hal_set_rst_high();
01538     hal_register_write(0x0E, 0x01);
01539     hal_register_write(0x02, 0x03);
01540     hal_register_write(0x03, 0x10);
01541  // hal_register_write(0x08, 0x20+26);    //channel 26
01542     hal_subregister_write(SR_CCA_MODE,1); //leave channel unchanged
01543 
01544  // hal_register_write(0x05, 0x00);       //output power maximum
01545     hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);  //clear AUTO_CRC, leave output power unchanged
01546  
01547     hal_register_read(0x01);             //should be trx-off state=0x08  
01548     hal_frame_write(buffer, 127);        //maximum length, random for spectral noise 
01549 
01550     hal_register_write(0x36,0x0F);       //configure continuous TX
01551     hal_register_write(0x3D,0x00);       //Modulated frame, other options are:
01552 //  hal_register_write(RG_TX_2,0x10);    //CW -2MHz
01553 //  hal_register_write(RG_TX_2,0x80);    //CW -500KHz
01554 //  hal_register_write(RG_TX_2,0xC0);    //CW +500KHz
01555 
01556     DDRB  |= 1<<7;                       //Raven USB stick has PB7 connected to the RF230 TST pin.   
01557     PORTB |= 1<<7;                       //Raise it to enable continuous TX Test Mode.
01558 
01559     hal_register_write(0x02,0x09);       //Set TRX_STATE to PLL_ON
01560     delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
01561     delay_us(TIME_PLL_LOCK);
01562     delay_us(TIME_PLL_LOCK);
01563  // while (hal_register_read(0x0f)!=1) {continue;}  //wait for pll lock-hangs
01564     hal_register_write(0x02,0x02);       //Set TRX_STATE to TX_START
01565 }
01566 #endif

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