Contiki 2.6
|
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 /*---------------------------------------------------------------------------*/