Contiki 2.6

cc2420.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: cc2420.c,v 1.63 2011/01/09 21:09:28 adamdunkels Exp $
00032  */
00033 /*
00034  * This code is almost device independent and should be easy to port.
00035  */
00036 
00037 #include <string.h>
00038 
00039 #include "contiki.h"
00040 
00041 #if defined(__AVR__)
00042 #include <avr/io.h>
00043 #endif
00044 
00045 #include "dev/leds.h"
00046 #include "dev/spi.h"
00047 #include "dev/cc2420.h"
00048 #include "dev/cc2420_const.h"
00049 
00050 #include "net/packetbuf.h"
00051 #include "net/rime/rimestats.h"
00052 #include "net/netstack.h"
00053 
00054 #include "sys/timetable.h"
00055 
00056 #define WITH_SEND_CCA 1
00057 
00058 #define FOOTER_LEN 2
00059 
00060 #ifndef CC2420_CONF_CHECKSUM
00061 #define CC2420_CONF_CHECKSUM 0
00062 #endif /* CC2420_CONF_CHECKSUM */
00063 
00064 #ifndef CC2420_CONF_AUTOACK
00065 #define CC2420_CONF_AUTOACK 0
00066 #endif /* CC2420_CONF_AUTOACK */
00067 
00068 #if CC2420_CONF_CHECKSUM
00069 #include "lib/crc16.h"
00070 #define CHECKSUM_LEN 2
00071 #else
00072 #define CHECKSUM_LEN 0
00073 #endif /* CC2420_CONF_CHECKSUM */
00074 
00075 #define AUX_LEN (CHECKSUM_LEN + FOOTER_LEN)
00076 
00077 
00078 #define FOOTER1_CRC_OK      0x80
00079 #define FOOTER1_CORRELATION 0x7f
00080 
00081 #define DEBUG 0
00082 #if DEBUG
00083 #include <stdio.h>
00084 #define PRINTF(...) printf(__VA_ARGS__)
00085 #else
00086 #define PRINTF(...) do {} while (0)
00087 #endif
00088 
00089 #define DEBUG_LEDS DEBUG
00090 #undef LEDS_ON
00091 #undef LEDS_OFF
00092 #if DEBUG_LEDS
00093 #define LEDS_ON(x) leds_on(x)
00094 #define LEDS_OFF(x) leds_off(x)
00095 #else
00096 #define LEDS_ON(x)
00097 #define LEDS_OFF(x)
00098 #endif
00099 
00100 void cc2420_arch_init(void);
00101 
00102 /* XXX hack: these will be made as Chameleon packet attributes */
00103 rtimer_clock_t cc2420_time_of_arrival, cc2420_time_of_departure;
00104 
00105 int cc2420_authority_level_of_sender;
00106 
00107 int cc2420_packets_seen, cc2420_packets_read;
00108 
00109 static uint8_t volatile pending;
00110 
00111 #define BUSYWAIT_UNTIL(cond, max_time)                                  \
00112   do {                                                                  \
00113     rtimer_clock_t t0;                                                  \
00114     t0 = RTIMER_NOW();                                                  \
00115     while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time)));   \
00116   } while(0)
00117 
00118 volatile uint8_t cc2420_sfd_counter;
00119 volatile uint16_t cc2420_sfd_start_time;
00120 volatile uint16_t cc2420_sfd_end_time;
00121 
00122 static volatile uint16_t last_packet_timestamp;
00123 /*---------------------------------------------------------------------------*/
00124 PROCESS(cc2420_process, "CC2420 driver");
00125 /*---------------------------------------------------------------------------*/
00126 
00127 
00128 int cc2420_on(void);
00129 int cc2420_off(void);
00130 
00131 static int cc2420_read(void *buf, unsigned short bufsize);
00132 
00133 static int cc2420_prepare(const void *data, unsigned short len);
00134 static int cc2420_transmit(unsigned short len);
00135 static int cc2420_send(const void *data, unsigned short len);
00136 
00137 static int cc2420_receiving_packet(void);
00138 static int pending_packet(void);
00139 static int cc2420_cca(void);
00140 /*static int detected_energy(void);*/
00141 
00142 signed char cc2420_last_rssi;
00143 uint8_t cc2420_last_correlation;
00144 
00145 const struct radio_driver cc2420_driver =
00146   {
00147     cc2420_init,
00148     cc2420_prepare,
00149     cc2420_transmit,
00150     cc2420_send,
00151     cc2420_read,
00152     /* cc2420_set_channel, */
00153     /* detected_energy, */
00154     cc2420_cca,
00155     cc2420_receiving_packet,
00156     pending_packet,
00157     cc2420_on,
00158     cc2420_off,
00159   };
00160 
00161 static uint8_t receive_on;
00162 
00163 static int channel;
00164 
00165 /*---------------------------------------------------------------------------*/
00166 
00167 static void
00168 getrxdata(void *buf, int len)
00169 {
00170   CC2420_READ_FIFO_BUF(buf, len);
00171 }
00172 static void
00173 getrxbyte(uint8_t *byte)
00174 {
00175   CC2420_READ_FIFO_BYTE(*byte);
00176 }
00177 static void
00178 flushrx(void)
00179 {
00180   uint8_t dummy;
00181 
00182   CC2420_READ_FIFO_BYTE(dummy);
00183   CC2420_STROBE(CC2420_SFLUSHRX);
00184   CC2420_STROBE(CC2420_SFLUSHRX);
00185 }
00186 /*---------------------------------------------------------------------------*/
00187 static void
00188 strobe(enum cc2420_register regname)
00189 {
00190   CC2420_STROBE(regname);
00191 }
00192 /*---------------------------------------------------------------------------*/
00193 static unsigned int
00194 status(void)
00195 {
00196   uint8_t status;
00197   CC2420_GET_STATUS(status);
00198   return status;
00199 }
00200 /*---------------------------------------------------------------------------*/
00201 static uint8_t locked, lock_on, lock_off;
00202 
00203 static void
00204 on(void)
00205 {
00206   CC2420_ENABLE_FIFOP_INT();
00207   strobe(CC2420_SRXON);
00208 
00209   BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 100);
00210 
00211   ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00212   receive_on = 1;
00213 }
00214 static void
00215 off(void)
00216 {
00217   /*  PRINTF("off\n");*/
00218   receive_on = 0;
00219 
00220   /* Wait for transmission to end before turning radio off. */
00221   BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
00222 
00223   ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00224   strobe(CC2420_SRFOFF);
00225   CC2420_DISABLE_FIFOP_INT();
00226 
00227   if(!CC2420_FIFOP_IS_1) {
00228     flushrx();
00229   }
00230 }
00231 /*---------------------------------------------------------------------------*/
00232 #define GET_LOCK() locked++
00233 static void RELEASE_LOCK(void) {
00234   if(locked == 1) {
00235     if(lock_on) {
00236       on();
00237       lock_on = 0;
00238     }
00239     if(lock_off) {
00240       off();
00241       lock_off = 0;
00242     }
00243   }
00244   locked--;
00245 }
00246 /*---------------------------------------------------------------------------*/
00247 static unsigned
00248 getreg(enum cc2420_register regname)
00249 {
00250   unsigned reg;
00251   CC2420_READ_REG(regname, reg);
00252   return reg;
00253 }
00254 /*---------------------------------------------------------------------------*/
00255 static void
00256 setreg(enum cc2420_register regname, unsigned value)
00257 {
00258   CC2420_WRITE_REG(regname, value);
00259 }
00260 /*---------------------------------------------------------------------------*/
00261 static void
00262 set_txpower(uint8_t power)
00263 {
00264   uint16_t reg;
00265 
00266   reg = getreg(CC2420_TXCTRL);
00267   reg = (reg & 0xffe0) | (power & 0x1f);
00268   setreg(CC2420_TXCTRL, reg);
00269 }
00270 /*---------------------------------------------------------------------------*/
00271 #define AUTOACK (1 << 4)
00272 #define ADR_DECODE (1 << 11)
00273 #define RXFIFO_PROTECTION (1 << 9)
00274 #define CORR_THR(n) (((n) & 0x1f) << 6)
00275 #define FIFOP_THR(n) ((n) & 0x7f)
00276 #define RXBPF_LOCUR (1 << 13);
00277 /*---------------------------------------------------------------------------*/
00278 int
00279 cc2420_init(void)
00280 {
00281   uint16_t reg;
00282   {
00283     int s = splhigh();
00284     cc2420_arch_init();         /* Initalize ports and SPI. */
00285     CC2420_DISABLE_FIFOP_INT();
00286     CC2420_FIFOP_INT_INIT();
00287     splx(s);
00288   }
00289 
00290   /* Turn on voltage regulator and reset. */
00291   SET_VREG_ACTIVE();
00292   clock_delay(250);
00293   SET_RESET_ACTIVE();
00294   clock_delay(127);
00295   SET_RESET_INACTIVE();
00296   clock_delay(125);
00297 
00298 
00299   /* Turn on the crystal oscillator. */
00300   strobe(CC2420_SXOSCON);
00301 
00302   /* Turn on/off automatic packet acknowledgment and address decoding. */
00303   reg = getreg(CC2420_MDMCTRL0);
00304 
00305 #if CC2420_CONF_AUTOACK
00306   reg |= AUTOACK | ADR_DECODE;
00307 #else
00308   reg &= ~(AUTOACK | ADR_DECODE);
00309 #endif /* CC2420_CONF_AUTOACK */
00310   setreg(CC2420_MDMCTRL0, reg);
00311 
00312   /* Set transmission turnaround time to the lower setting (8 symbols
00313      = 0.128 ms) instead of the default (12 symbols = 0.192 ms). */
00314   /*  reg = getreg(CC2420_TXCTRL);
00315   reg &= ~(1 << 13);
00316   setreg(CC2420_TXCTRL, reg);*/
00317 
00318   
00319   /* Change default values as recomended in the data sheet, */
00320   /* correlation threshold = 20, RX bandpass filter = 1.3uA. */
00321   setreg(CC2420_MDMCTRL1, CORR_THR(20));
00322   reg = getreg(CC2420_RXCTRL1);
00323   reg |= RXBPF_LOCUR;
00324   setreg(CC2420_RXCTRL1, reg);
00325 
00326   /* Set the FIFOP threshold to maximum. */
00327   setreg(CC2420_IOCFG0, FIFOP_THR(127));
00328 
00329   /* Turn off "Security enable" (page 32). */
00330   reg = getreg(CC2420_SECCTRL0);
00331   reg &= ~RXFIFO_PROTECTION;
00332   setreg(CC2420_SECCTRL0, reg);
00333 
00334   cc2420_set_pan_addr(0xffff, 0x0000, NULL);
00335   cc2420_set_channel(26);
00336 
00337   flushrx();
00338 
00339   process_start(&cc2420_process, NULL);
00340   return 1;
00341 }
00342 /*---------------------------------------------------------------------------*/
00343 static int
00344 cc2420_transmit(unsigned short payload_len)
00345 {
00346   int i, txpower;
00347   uint8_t total_len;
00348 #if CC2420_CONF_CHECKSUM
00349   uint16_t checksum;
00350 #endif /* CC2420_CONF_CHECKSUM */
00351 
00352   GET_LOCK();
00353 
00354   txpower = 0;
00355   if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00356     /* Remember the current transmission power */
00357     txpower = cc2420_get_txpower();
00358     /* Set the specified transmission power */
00359     set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
00360   }
00361 
00362   total_len = payload_len + AUX_LEN;
00363   
00364   /* The TX FIFO can only hold one packet. Make sure to not overrun
00365    * FIFO by waiting for transmission to start here and synchronizing
00366    * with the CC2420_TX_ACTIVE check in cc2420_send.
00367    *
00368    * Note that we may have to wait up to 320 us (20 symbols) before
00369    * transmission starts.
00370    */
00371 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
00372 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
00373 #else
00374 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
00375 #endif
00376 
00377 #if WITH_SEND_CCA
00378   strobe(CC2420_SRXON);
00379   BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10);
00380   strobe(CC2420_STXONCCA);
00381 #else /* WITH_SEND_CCA */
00382   strobe(CC2420_STXON);
00383 #endif /* WITH_SEND_CCA */
00384   for(i = LOOP_20_SYMBOLS; i > 0; i--) {
00385     if(CC2420_SFD_IS_1) {
00386       {
00387         rtimer_clock_t sfd_timestamp;
00388         sfd_timestamp = cc2420_sfd_start_time;
00389         if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
00390            PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
00391           /* Write timestamp to last two bytes of packet in TXFIFO. */
00392           CC2420_WRITE_RAM(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2);
00393         }
00394       }
00395 
00396       if(!(status() & BV(CC2420_TX_ACTIVE))) {
00397         /* SFD went high but we are not transmitting. This means that
00398            we just started receiving a packet, so we drop the
00399            transmission. */
00400         RELEASE_LOCK();
00401         return RADIO_TX_COLLISION;
00402       }
00403       if(receive_on) {
00404         ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00405       }
00406       ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00407       /* We wait until transmission has ended so that we get an
00408          accurate measurement of the transmission time.*/
00409       BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
00410 
00411 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
00412       ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
00413 #endif
00414       ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00415       if(receive_on) {
00416         ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00417       } else {
00418         /* We need to explicitly turn off the radio,
00419          * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
00420         off();
00421       }
00422 
00423       if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00424         /* Restore the transmission power */
00425         set_txpower(txpower & 0xff);
00426       }
00427 
00428       RELEASE_LOCK();
00429       return RADIO_TX_OK;
00430     }
00431   }
00432 
00433   /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
00434      transmitted because of other channel activity. */
00435   RIMESTATS_ADD(contentiondrop);
00436   PRINTF("cc2420: do_send() transmission never started\n");
00437 
00438   if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00439     /* Restore the transmission power */
00440     set_txpower(txpower & 0xff);
00441   }
00442 
00443   RELEASE_LOCK();
00444   return RADIO_TX_COLLISION;
00445 }
00446 /*---------------------------------------------------------------------------*/
00447 static int
00448 cc2420_prepare(const void *payload, unsigned short payload_len)
00449 {
00450   uint8_t total_len;
00451 #if CC2420_CONF_CHECKSUM
00452   uint16_t checksum;
00453 #endif /* CC2420_CONF_CHECKSUM */
00454   GET_LOCK();
00455 
00456   PRINTF("cc2420: sending %d bytes\n", payload_len);
00457 
00458   RIMESTATS_ADD(lltx);
00459 
00460   /* Wait for any previous transmission to finish. */
00461   /*  while(status() & BV(CC2420_TX_ACTIVE));*/
00462 
00463   /* Write packet to TX FIFO. */
00464   strobe(CC2420_SFLUSHTX);
00465 
00466 #if CC2420_CONF_CHECKSUM
00467   checksum = crc16_data(payload, payload_len, 0);
00468 #endif /* CC2420_CONF_CHECKSUM */
00469   total_len = payload_len + AUX_LEN;
00470   CC2420_WRITE_FIFO_BUF(&total_len, 1);
00471   CC2420_WRITE_FIFO_BUF(payload, payload_len);
00472 #if CC2420_CONF_CHECKSUM
00473   CC2420_WRITE_FIFO_BUF(&checksum, CHECKSUM_LEN);
00474 #endif /* CC2420_CONF_CHECKSUM */
00475 
00476   RELEASE_LOCK();
00477   return 0;
00478 }
00479 /*---------------------------------------------------------------------------*/
00480 static int
00481 cc2420_send(const void *payload, unsigned short payload_len)
00482 {
00483   cc2420_prepare(payload, payload_len);
00484   return cc2420_transmit(payload_len);
00485 }
00486 /*---------------------------------------------------------------------------*/
00487 int
00488 cc2420_off(void)
00489 {
00490   /* Don't do anything if we are already turned off. */
00491   if(receive_on == 0) {
00492     return 1;
00493   }
00494 
00495   /* If we are called when the driver is locked, we indicate that the
00496      radio should be turned off when the lock is unlocked. */
00497   if(locked) {
00498     /*    printf("Off when locked (%d)\n", locked);*/
00499     lock_off = 1;
00500     return 1;
00501   }
00502 
00503   GET_LOCK();
00504   /* If we are currently receiving a packet (indicated by SFD == 1),
00505      we don't actually switch the radio off now, but signal that the
00506      driver should switch off the radio once the packet has been
00507      received and processed, by setting the 'lock_off' variable. */
00508   if(status() & BV(CC2420_TX_ACTIVE)) {
00509     lock_off = 1;
00510   } else {
00511     off();
00512   }
00513   RELEASE_LOCK();
00514   return 1;
00515 }
00516 /*---------------------------------------------------------------------------*/
00517 int
00518 cc2420_on(void)
00519 {
00520   if(receive_on) {
00521     return 1;
00522   }
00523   if(locked) {
00524     lock_on = 1;
00525     return 1;
00526   }
00527 
00528   GET_LOCK();
00529   on();
00530   RELEASE_LOCK();
00531   return 1;
00532 }
00533 /*---------------------------------------------------------------------------*/
00534 int
00535 cc2420_get_channel(void)
00536 {
00537   return channel;
00538 }
00539 /*---------------------------------------------------------------------------*/
00540 int
00541 cc2420_set_channel(int c)
00542 {
00543   uint16_t f;
00544 
00545   GET_LOCK();
00546   /*
00547    * Subtract the base channel (11), multiply by 5, which is the
00548    * channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
00549    */
00550   channel = c;
00551 
00552   f = 5 * (c - 11) + 357 + 0x4000;
00553   /*
00554    * Writing RAM requires crystal oscillator to be stable.
00555    */
00556   BUSYWAIT_UNTIL((status() & (BV(CC2420_XOSC16M_STABLE))), RTIMER_SECOND / 10);
00557 
00558   /* Wait for any transmission to end. */
00559   BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
00560 
00561   setreg(CC2420_FSCTRL, f);
00562 
00563   /* If we are in receive mode, we issue an SRXON command to ensure
00564      that the VCO is calibrated. */
00565   if(receive_on) {
00566     strobe(CC2420_SRXON);
00567   }
00568 
00569   RELEASE_LOCK();
00570   return 1;
00571 }
00572 /*---------------------------------------------------------------------------*/
00573 void
00574 cc2420_set_pan_addr(unsigned pan,
00575                     unsigned addr,
00576                     const uint8_t *ieee_addr)
00577 {
00578   uint16_t f = 0;
00579   uint8_t tmp[2];
00580 
00581   GET_LOCK();
00582   
00583   /*
00584    * Writing RAM requires crystal oscillator to be stable.
00585    */
00586   BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 10);
00587 
00588   tmp[0] = pan & 0xff;
00589   tmp[1] = pan >> 8;
00590   CC2420_WRITE_RAM(&tmp, CC2420RAM_PANID, 2);
00591 
00592   tmp[0] = addr & 0xff;
00593   tmp[1] = addr >> 8;
00594   CC2420_WRITE_RAM(&tmp, CC2420RAM_SHORTADDR, 2);
00595   if(ieee_addr != NULL) {
00596     uint8_t tmp_addr[8];
00597     /* LSB first, MSB last for 802.15.4 addresses in CC2420 */
00598     for (f = 0; f < 8; f++) {
00599       tmp_addr[7 - f] = ieee_addr[f];
00600     }
00601     CC2420_WRITE_RAM(tmp_addr, CC2420RAM_IEEEADDR, 8);
00602   }
00603   RELEASE_LOCK();
00604 }
00605 /*---------------------------------------------------------------------------*/
00606 /*
00607  * Interrupt leaves frame intact in FIFO.
00608  */
00609 #if CC2420_TIMETABLE_PROFILING
00610 #define cc2420_timetable_size 16
00611 TIMETABLE(cc2420_timetable);
00612 TIMETABLE_AGGREGATE(aggregate_time, 10);
00613 #endif /* CC2420_TIMETABLE_PROFILING */
00614 int
00615 cc2420_interrupt(void)
00616 {
00617   CC2420_CLEAR_FIFOP_INT();
00618   process_poll(&cc2420_process);
00619 #if CC2420_TIMETABLE_PROFILING
00620   timetable_clear(&cc2420_timetable);
00621   TIMETABLE_TIMESTAMP(cc2420_timetable, "interrupt");
00622 #endif /* CC2420_TIMETABLE_PROFILING */
00623 
00624   last_packet_timestamp = cc2420_sfd_start_time;
00625   pending++;
00626   cc2420_packets_seen++;
00627   return 1;
00628 }
00629 /*---------------------------------------------------------------------------*/
00630 PROCESS_THREAD(cc2420_process, ev, data)
00631 {
00632   int len;
00633   PROCESS_BEGIN();
00634 
00635   PRINTF("cc2420_process: started\n");
00636 
00637   while(1) {
00638     PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
00639 #if CC2420_TIMETABLE_PROFILING
00640     TIMETABLE_TIMESTAMP(cc2420_timetable, "poll");
00641 #endif /* CC2420_TIMETABLE_PROFILING */
00642     
00643     PRINTF("cc2420_process: calling receiver callback\n");
00644 
00645     packetbuf_clear();
00646     packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
00647     len = cc2420_read(packetbuf_dataptr(), PACKETBUF_SIZE);
00648     
00649     packetbuf_set_datalen(len);
00650     
00651     NETSTACK_RDC.input();
00652 #if CC2420_TIMETABLE_PROFILING
00653     TIMETABLE_TIMESTAMP(cc2420_timetable, "end");
00654     timetable_aggregate_compute_detailed(&aggregate_time,
00655                                          &cc2420_timetable);
00656       timetable_clear(&cc2420_timetable);
00657 #endif /* CC2420_TIMETABLE_PROFILING */
00658   }
00659 
00660   PROCESS_END();
00661 }
00662 /*---------------------------------------------------------------------------*/
00663 static int
00664 cc2420_read(void *buf, unsigned short bufsize)
00665 {
00666   uint8_t footer[2];
00667   uint8_t len;
00668 #if CC2420_CONF_CHECKSUM
00669   uint16_t checksum;
00670 #endif /* CC2420_CONF_CHECKSUM */
00671 
00672   if(!CC2420_FIFOP_IS_1) {
00673     return 0;
00674   }
00675   /*  if(!pending) {
00676     return 0;
00677     }*/
00678   
00679   pending = 0;
00680   
00681   GET_LOCK();
00682 
00683   cc2420_packets_read++;
00684 
00685   getrxbyte(&len);
00686 
00687   if(len > CC2420_MAX_PACKET_LEN) {
00688     /* Oops, we must be out of sync. */
00689     flushrx();
00690     RIMESTATS_ADD(badsynch);
00691     RELEASE_LOCK();
00692     return 0;
00693   }
00694 
00695   if(len <= AUX_LEN) {
00696     flushrx();
00697     RIMESTATS_ADD(tooshort);
00698     RELEASE_LOCK();
00699     return 0;
00700   }
00701 
00702   if(len - AUX_LEN > bufsize) {
00703     flushrx();
00704     RIMESTATS_ADD(toolong);
00705     RELEASE_LOCK();
00706     return 0;
00707   }
00708 
00709   getrxdata(buf, len - AUX_LEN);
00710 #if CC2420_CONF_CHECKSUM
00711   getrxdata(&checksum, CHECKSUM_LEN);
00712 #endif /* CC2420_CONF_CHECKSUM */
00713   getrxdata(footer, FOOTER_LEN);
00714 
00715 #if CC2420_CONF_CHECKSUM
00716   if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
00717     PRINTF("checksum failed 0x%04x != 0x%04x\n",
00718            checksum, crc16_data(buf, len - AUX_LEN, 0));
00719   }
00720 
00721   if(footer[1] & FOOTER1_CRC_OK &&
00722      checksum == crc16_data(buf, len - AUX_LEN, 0)) {
00723 #else
00724   if(footer[1] & FOOTER1_CRC_OK) {
00725 #endif /* CC2420_CONF_CHECKSUM */
00726     cc2420_last_rssi = footer[0];
00727     cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
00728 
00729 
00730     packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
00731     packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
00732 
00733     RIMESTATS_ADD(llrx);
00734 
00735   } else {
00736     RIMESTATS_ADD(badcrc);
00737     len = AUX_LEN;
00738   }
00739 
00740   if(CC2420_FIFOP_IS_1) {
00741     if(!CC2420_FIFO_IS_1) {
00742       /* Clean up in case of FIFO overflow!  This happens for every
00743        * full length frame and is signaled by FIFOP = 1 and FIFO =
00744        * 0. */
00745       flushrx();
00746     } else {
00747       /* Another packet has been received and needs attention. */
00748       process_poll(&cc2420_process);
00749     }
00750   }
00751 
00752   RELEASE_LOCK();
00753 
00754   if(len < AUX_LEN) {
00755     return 0;
00756   }
00757 
00758   return len - AUX_LEN;
00759 }
00760 /*---------------------------------------------------------------------------*/
00761 void
00762 cc2420_set_txpower(uint8_t power)
00763 {
00764   GET_LOCK();
00765   set_txpower(power);
00766   RELEASE_LOCK();
00767 }
00768 /*---------------------------------------------------------------------------*/
00769 int
00770 cc2420_get_txpower(void)
00771 {
00772   int power;
00773   GET_LOCK();
00774   power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
00775   RELEASE_LOCK();
00776   return power;
00777 }
00778 /*---------------------------------------------------------------------------*/
00779 int
00780 cc2420_rssi(void)
00781 {
00782   int rssi;
00783   int radio_was_off = 0;
00784 
00785   if(locked) {
00786     return 0;
00787   }
00788   
00789   GET_LOCK();
00790 
00791   if(!receive_on) {
00792     radio_was_off = 1;
00793     cc2420_on();
00794   }
00795   BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
00796 
00797   rssi = (int)((signed char)getreg(CC2420_RSSI));
00798 
00799   if(radio_was_off) {
00800     cc2420_off();
00801   }
00802   RELEASE_LOCK();
00803   return rssi;
00804 }
00805 /*---------------------------------------------------------------------------*/
00806 /*
00807 static int
00808 detected_energy(void)
00809 {
00810   return cc2420_rssi();
00811 }
00812 */
00813 /*---------------------------------------------------------------------------*/
00814 int
00815 cc2420_cca_valid(void)
00816 {
00817   int valid;
00818   if(locked) {
00819     return 1;
00820   }
00821   GET_LOCK();
00822   valid = !!(status() & BV(CC2420_RSSI_VALID));
00823   RELEASE_LOCK();
00824   return valid;
00825 }
00826 /*---------------------------------------------------------------------------*/
00827 static int
00828 cc2420_cca(void)
00829 {
00830   int cca;
00831   int radio_was_off = 0;
00832 
00833   /* If the radio is locked by an underlying thread (because we are
00834      being invoked through an interrupt), we preted that the coast is
00835      clear (i.e., no packet is currently being transmitted by a
00836      neighbor). */
00837   if(locked) {
00838     return 1;
00839   }
00840 
00841   GET_LOCK();
00842   if(!receive_on) {
00843     radio_was_off = 1;
00844     cc2420_on();
00845   }
00846 
00847   /* Make sure that the radio really got turned on. */
00848   if(!receive_on) {
00849     RELEASE_LOCK();
00850     if(radio_was_off) {
00851       cc2420_off();
00852     }
00853     return 1;
00854   }
00855 
00856   BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
00857 
00858   cca = CC2420_CCA_IS_1;
00859 
00860   if(radio_was_off) {
00861     cc2420_off();
00862   }
00863   RELEASE_LOCK();
00864   return cca;
00865 }
00866 /*---------------------------------------------------------------------------*/
00867 int
00868 cc2420_receiving_packet(void)
00869 {
00870   return CC2420_SFD_IS_1;
00871 }
00872 /*---------------------------------------------------------------------------*/
00873 static int
00874 pending_packet(void)
00875 {
00876   return CC2420_FIFOP_IS_1;
00877 }
00878 /*---------------------------------------------------------------------------*/
00879 void
00880 cc2420_set_cca_threshold(int value)
00881 {
00882   uint16_t shifted = value << 8;
00883   GET_LOCK();
00884   setreg(CC2420_RSSI, shifted);
00885   RELEASE_LOCK();
00886 }
00887 /*---------------------------------------------------------------------------*/