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

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