Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2011, 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 /* 00032 * This code is almost device independent and should be easy to port. 00033 */ 00034 00035 #include "contiki.h" 00036 00037 #include "dev/spi.h" 00038 #include "dev/cc2520.h" 00039 #include "dev/cc2520_const.h" 00040 00041 #include "net/packetbuf.h" 00042 #include "net/rime/rimestats.h" 00043 #include "net/netstack.h" 00044 00045 #include "sys/timetable.h" 00046 #include <string.h> 00047 00048 #ifndef CC2520_CONF_AUTOACK 00049 #define CC2520_CONF_AUTOACK 0 00050 #endif /* CC2520_CONF_AUTOACK */ 00051 00052 #define WITH_SEND_CCA 1 00053 00054 #define FOOTER_LEN 2 00055 00056 #define FOOTER1_CRC_OK 0x80 00057 #define FOOTER1_CORRELATION 0x7f 00058 00059 #include <stdio.h> 00060 #define DEBUG 0 00061 #if DEBUG 00062 #define PRINTF(...) printf(__VA_ARGS__) 00063 #else 00064 #define PRINTF(...) do {} while (0) 00065 #endif 00066 00067 #if 0 && DEBUG 00068 #include "dev/leds.h" 00069 #define LEDS_ON(x) leds_on(x) 00070 #define LEDS_OFF(x) leds_off(x) 00071 #else 00072 #define LEDS_ON(x) 00073 #define LEDS_OFF(x) 00074 #endif 00075 00076 void cc2520_arch_init(void); 00077 00078 /* XXX hack: these will be made as Chameleon packet attributes */ 00079 rtimer_clock_t cc2520_time_of_arrival, cc2520_time_of_departure; 00080 00081 int cc2520_authority_level_of_sender; 00082 00083 int cc2520_packets_seen, cc2520_packets_read; 00084 00085 #define BUSYWAIT_UNTIL(cond, max_time) \ 00086 do { \ 00087 rtimer_clock_t t0; \ 00088 t0 = RTIMER_NOW(); \ 00089 while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ 00090 } while(0) 00091 00092 volatile uint8_t cc2520_sfd_counter; 00093 volatile uint16_t cc2520_sfd_start_time; 00094 volatile uint16_t cc2520_sfd_end_time; 00095 00096 static volatile uint16_t last_packet_timestamp; 00097 /*---------------------------------------------------------------------------*/ 00098 PROCESS(cc2520_process, "CC2520 driver"); 00099 /*---------------------------------------------------------------------------*/ 00100 00101 00102 int cc2520_on(void); 00103 int cc2520_off(void); 00104 00105 static int cc2520_read(void *buf, unsigned short bufsize); 00106 00107 static int cc2520_prepare(const void *data, unsigned short len); 00108 static int cc2520_transmit(unsigned short len); 00109 static int cc2520_send(const void *data, unsigned short len); 00110 00111 static int cc2520_receiving_packet(void); 00112 static int pending_packet(void); 00113 static int cc2520_cca(void); 00114 /* static int detected_energy(void); */ 00115 00116 signed char cc2520_last_rssi; 00117 uint8_t cc2520_last_correlation; 00118 00119 const struct radio_driver cc2520_driver = 00120 { 00121 cc2520_init, 00122 cc2520_prepare, 00123 cc2520_transmit, 00124 cc2520_send, 00125 cc2520_read, 00126 /* cc2520_set_channel, */ 00127 /* detected_energy, */ 00128 cc2520_cca, 00129 cc2520_receiving_packet, 00130 pending_packet, 00131 cc2520_on, 00132 cc2520_off, 00133 }; 00134 00135 static uint8_t receive_on; 00136 00137 static int channel; 00138 00139 /*---------------------------------------------------------------------------*/ 00140 00141 static void 00142 getrxdata(void *buf, int len) 00143 { 00144 CC2520_READ_FIFO_BUF(buf, len); 00145 } 00146 static void 00147 getrxbyte(uint8_t *byte) 00148 { 00149 CC2520_READ_FIFO_BYTE(*byte); 00150 } 00151 static void 00152 flushrx(void) 00153 { 00154 uint8_t dummy; 00155 00156 CC2520_READ_FIFO_BYTE(dummy); 00157 CC2520_STROBE(CC2520_INS_SFLUSHRX); 00158 CC2520_STROBE(CC2520_INS_SFLUSHRX); 00159 } 00160 /*---------------------------------------------------------------------------*/ 00161 static void 00162 strobe(uint8_t regname) 00163 { 00164 CC2520_STROBE(regname); 00165 } 00166 /*---------------------------------------------------------------------------*/ 00167 static unsigned int 00168 status(void) 00169 { 00170 uint8_t status; 00171 CC2520_GET_STATUS(status); 00172 return status; 00173 } 00174 /*---------------------------------------------------------------------------*/ 00175 static uint8_t locked, lock_on, lock_off; 00176 00177 static void 00178 on(void) 00179 { 00180 CC2520_ENABLE_FIFOP_INT(); 00181 strobe(CC2520_INS_SRXON); 00182 00183 BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 100); 00184 00185 ENERGEST_ON(ENERGEST_TYPE_LISTEN); 00186 receive_on = 1; 00187 } 00188 static void 00189 off(void) 00190 { 00191 /* PRINTF("off\n");*/ 00192 receive_on = 0; 00193 00194 /* Wait for transmission to end before turning radio off. */ 00195 BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10); 00196 00197 ENERGEST_OFF(ENERGEST_TYPE_LISTEN); 00198 strobe(CC2520_INS_SRFOFF); 00199 CC2520_DISABLE_FIFOP_INT(); 00200 00201 if(!CC2520_FIFOP_IS_1) { 00202 flushrx(); 00203 } 00204 } 00205 /*---------------------------------------------------------------------------*/ 00206 #define GET_LOCK() locked++ 00207 static void RELEASE_LOCK(void) { 00208 if(locked == 1) { 00209 if(lock_on) { 00210 on(); 00211 lock_on = 0; 00212 } 00213 if(lock_off) { 00214 off(); 00215 lock_off = 0; 00216 } 00217 } 00218 locked--; 00219 } 00220 /*---------------------------------------------------------------------------*/ 00221 static uint8_t 00222 getreg(uint16_t regname) 00223 { 00224 uint8_t reg; 00225 CC2520_READ_REG(regname, reg); 00226 return reg; 00227 } 00228 /*---------------------------------------------------------------------------*/ 00229 static void 00230 setreg(uint16_t regname, uint8_t value) 00231 { 00232 CC2520_WRITE_REG(regname, value); 00233 } 00234 /*---------------------------------------------------------------------------*/ 00235 static void 00236 set_txpower(uint8_t power) 00237 { 00238 setreg(CC2520_TXPOWER, power); 00239 } 00240 /*---------------------------------------------------------------------------*/ 00241 #define AUTOCRC (1 << 6) 00242 #define AUTOACK (1 << 5) 00243 #define FRAME_MAX_VERSION ((1 << 3) | (1 << 2)) 00244 #define FRAME_FILTER_ENABLE (1 << 0) 00245 #define CORR_THR(n) (((n) & 0x1f) << 6) 00246 #define FIFOP_THR(n) ((n) & 0x7f) 00247 /*---------------------------------------------------------------------------*/ 00248 int 00249 cc2520_init(void) 00250 { 00251 { 00252 int s = splhigh(); 00253 cc2520_arch_init(); /* Initalize ports and SPI. */ 00254 CC2520_DISABLE_FIFOP_INT(); 00255 CC2520_FIFOP_INT_INIT(); 00256 splx(s); 00257 } 00258 00259 SET_VREG_INACTIVE(); 00260 clock_delay(250); 00261 /* Turn on voltage regulator and reset. */ 00262 SET_VREG_ACTIVE(); 00263 clock_delay(250); 00264 SET_RESET_ACTIVE(); 00265 clock_delay(127); 00266 SET_RESET_INACTIVE(); 00267 clock_delay(125); 00268 /* Turn on the crystal oscillator. */ 00269 strobe(CC2520_INS_SXOSCON); 00270 clock_delay(125); 00271 00272 BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 100); 00273 00274 /* Change default values as recommended in the data sheet, */ 00275 /* correlation threshold = 20, RX bandpass filter = 1.3uA.*/ 00276 00277 setreg(CC2520_TXCTRL, 0x94); 00278 setreg(CC2520_TXPOWER, 0x13); // Output power 1 dBm 00279 00280 /* 00281 00282 valeurs de TXPOWER 00283 0x03 -> -18 dBm 00284 0x2C -> -7 dBm 00285 0x88 -> -4 dBm 00286 0x81 -> -2 dBm 00287 0x32 -> 0 dBm 00288 0x13 -> 1 dBm 00289 0x32 -> 0 dBm 00290 0x13 -> 1 dBm 00291 0xAB -> 2 dBm 00292 0xF2 -> 3 dBm 00293 0xF7 -> 5 dBm 00294 */ 00295 setreg(CC2520_CCACTRL0, 0xF8); // CCA treshold -80dBm 00296 00297 // Recommended RX settings 00298 setreg(CC2520_MDMCTRL0, 0x84); // Controls modem 00299 setreg(CC2520_MDMCTRL1, 0x14); // Controls modem 00300 setreg(CC2520_RXCTRL, 0x3F); // Adjust currents in RX related analog modules 00301 setreg(CC2520_FSCTRL, 0x5A); // Adjust currents in synthesizer. 00302 setreg(CC2520_FSCAL1, 0x2B); // Adjust currents in VCO 00303 setreg(CC2520_AGCCTRL1, 0x11); // Adjust target value for AGC control loop 00304 setreg(CC2520_AGCCTRL2, 0xEB); 00305 00306 // Disable external clock 00307 setreg(CC2520_EXTCLOCK, 0x00); 00308 00309 // Tune ADC performance 00310 setreg(CC2520_ADCTEST0, 0x10); 00311 setreg(CC2520_ADCTEST1, 0x0E); 00312 setreg(CC2520_ADCTEST2, 0x03); 00313 00314 /* Set auto CRC on frame. */ 00315 #if CC2520_CONF_AUTOACK 00316 setreg(CC2520_FRMCTRL0, AUTOCRC | AUTOACK); 00317 setreg(CC2520_FRMFILT0, FRAME_MAX_VERSION|FRAME_FILTER_ENABLE); 00318 #else 00319 /* setreg(CC2520_FRMCTRL0, 0x60); */ 00320 setreg(CC2520_FRMCTRL0, AUTOCRC); 00321 /* Disable filter on @ (remove if you want to address specific wismote) */ 00322 setreg(CC2520_FRMFILT0, 0x00); 00323 #endif /* CC2520_CONF_AUTOACK */ 00324 /* SET_RXENMASK_ON_TX */ 00325 setreg(CC2520_FRMCTRL1, 1); 00326 /* Set FIFOP threshold to maximum .*/ 00327 setreg(CC2520_FIFOPCTRL, FIFOP_THR(0x7F)); 00328 00329 cc2520_set_pan_addr(0xffff, 0x0000, NULL); 00330 cc2520_set_channel(26); 00331 00332 flushrx(); 00333 00334 process_start(&cc2520_process, NULL); 00335 return 1; 00336 } 00337 /*---------------------------------------------------------------------------*/ 00338 static int 00339 cc2520_transmit(unsigned short payload_len) 00340 { 00341 int i, txpower; 00342 00343 GET_LOCK(); 00344 00345 txpower = 0; 00346 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) { 00347 /* Remember the current transmission power */ 00348 txpower = cc2520_get_txpower(); 00349 /* Set the specified transmission power */ 00350 set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1); 00351 } 00352 00353 /* The TX FIFO can only hold one packet. Make sure to not overrun 00354 * FIFO by waiting for transmission to start here and synchronizing 00355 * with the CC2520_TX_ACTIVE check in cc2520_send. 00356 * 00357 * Note that we may have to wait up to 320 us (20 symbols) before 00358 * transmission starts. 00359 */ 00360 #ifndef CC2520_CONF_SYMBOL_LOOP_COUNT 00361 #error CC2520_CONF_SYMBOL_LOOP_COUNT needs to be set!!! 00362 #else 00363 #define LOOP_20_SYMBOLS CC2520_CONF_SYMBOL_LOOP_COUNT 00364 #endif 00365 00366 #if WITH_SEND_CCA 00367 strobe(CC2520_INS_SRXON); 00368 BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID) , RTIMER_SECOND / 10); 00369 strobe(CC2520_INS_STXONCCA); 00370 #else /* WITH_SEND_CCA */ 00371 strobe(CC2520_INS_STXON); 00372 #endif /* WITH_SEND_CCA */ 00373 for(i = LOOP_20_SYMBOLS; i > 0; i--) { 00374 if(CC2520_SFD_IS_1) { 00375 { 00376 rtimer_clock_t sfd_timestamp; 00377 sfd_timestamp = cc2520_sfd_start_time; 00378 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == 00379 PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { 00380 /* Write timestamp to last two bytes of packet in TXFIFO. */ 00381 CC2520_WRITE_RAM(&sfd_timestamp, CC2520RAM_TXFIFO + payload_len - 1, 2); 00382 } 00383 } 00384 00385 if(!(status() & BV(CC2520_TX_ACTIVE))) { 00386 /* SFD went high but we are not transmitting. This means that 00387 we just started receiving a packet, so we drop the 00388 transmission. */ 00389 RELEASE_LOCK(); 00390 return RADIO_TX_COLLISION; 00391 } 00392 if(receive_on) { 00393 ENERGEST_OFF(ENERGEST_TYPE_LISTEN); 00394 } 00395 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); 00396 /* We wait until transmission has ended so that we get an 00397 accurate measurement of the transmission time.*/ 00398 //BUSYWAIT_UNTIL(getreg(CC2520_EXCFLAG0) & TX_FRM_DONE , RTIMER_SECOND / 100); 00399 BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10); 00400 00401 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS 00402 ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2520_get_txpower()); 00403 #endif 00404 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); 00405 if(receive_on) { 00406 ENERGEST_ON(ENERGEST_TYPE_LISTEN); 00407 } else { 00408 /* We need to explicitly turn off the radio, 00409 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */ 00410 off(); 00411 } 00412 00413 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) { 00414 /* Restore the transmission power */ 00415 set_txpower(txpower & 0xff); 00416 } 00417 00418 RELEASE_LOCK(); 00419 00420 return RADIO_TX_OK; 00421 } 00422 } 00423 00424 /* If we are using WITH_SEND_CCA, we get here if the packet wasn't 00425 transmitted because of other channel activity. */ 00426 RIMESTATS_ADD(contentiondrop); 00427 PRINTF("cc2520: do_send() transmission never started\n"); 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_COLLISION; 00436 } 00437 /*---------------------------------------------------------------------------*/ 00438 static int 00439 cc2520_prepare(const void *payload, unsigned short payload_len) 00440 { 00441 uint8_t total_len; 00442 GET_LOCK(); 00443 00444 PRINTF("cc2520: sending %d bytes\n", payload_len); 00445 /*int i; 00446 for(i = 0; i < payload_len;i++) 00447 printf("%x",((uint8_t *) payload)[i]); 00448 printf("\n");*/ 00449 RIMESTATS_ADD(lltx); 00450 00451 /* Wait for any previous transmission to finish. */ 00452 /* while(status() & BV(CC2520_TX_ACTIVE));*/ 00453 00454 /* Write packet to TX FIFO. */ 00455 strobe(CC2520_INS_SFLUSHTX); 00456 00457 total_len = payload_len + FOOTER_LEN; 00458 CC2520_WRITE_FIFO_BUF(&total_len, 1); 00459 CC2520_WRITE_FIFO_BUF(payload, payload_len); 00460 00461 RELEASE_LOCK(); 00462 return 0; 00463 } 00464 /*---------------------------------------------------------------------------*/ 00465 static int 00466 cc2520_send(const void *payload, unsigned short payload_len) 00467 { 00468 cc2520_prepare(payload, payload_len); 00469 return cc2520_transmit(payload_len); 00470 } 00471 /*---------------------------------------------------------------------------*/ 00472 int 00473 cc2520_off(void) 00474 { 00475 /* Don't do anything if we are already turned off. */ 00476 if(receive_on == 0) { 00477 return 1; 00478 } 00479 00480 /* If we are called when the driver is locked, we indicate that the 00481 radio should be turned off when the lock is unlocked. */ 00482 if(locked) { 00483 /* printf("Off when locked (%d)\n", locked);*/ 00484 lock_off = 1; 00485 return 1; 00486 } 00487 00488 GET_LOCK(); 00489 /* If we are currently receiving a packet (indicated by SFD == 1), 00490 we don't actually switch the radio off now, but signal that the 00491 driver should switch off the radio once the packet has been 00492 received and processed, by setting the 'lock_off' variable. */ 00493 if(status() & BV(CC2520_TX_ACTIVE)) { 00494 lock_off = 1; 00495 } else { 00496 off(); 00497 } 00498 RELEASE_LOCK(); 00499 return 1; 00500 } 00501 /*---------------------------------------------------------------------------*/ 00502 int 00503 cc2520_on(void) 00504 { 00505 if(receive_on) { 00506 return 1; 00507 } 00508 if(locked) { 00509 lock_on = 1; 00510 return 1; 00511 } 00512 00513 GET_LOCK(); 00514 on(); 00515 RELEASE_LOCK(); 00516 return 1; 00517 } 00518 /*---------------------------------------------------------------------------*/ 00519 int 00520 cc2520_get_channel(void) 00521 { 00522 return channel; 00523 } 00524 /*---------------------------------------------------------------------------*/ 00525 int 00526 cc2520_set_channel(int c) 00527 { 00528 uint16_t f; 00529 00530 GET_LOCK(); 00531 /* 00532 * Subtract the base channel (11), multiply by 5, which is the 00533 * channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1. 00534 */ 00535 channel = c; 00536 00537 f = MIN_CHANNEL + ((channel - MIN_CHANNEL) * CHANNEL_SPACING); 00538 /* 00539 * Writing RAM requires crystal oscillator to be stable. 00540 */ 00541 BUSYWAIT_UNTIL((status() & (BV(CC2520_XOSC16M_STABLE))), RTIMER_SECOND / 10); 00542 00543 /* Wait for any transmission to end. */ 00544 BUSYWAIT_UNTIL(!(status() & BV(CC2520_TX_ACTIVE)), RTIMER_SECOND / 10); 00545 00546 /* Define radio channel (between 11 and 25) */ 00547 setreg(CC2520_FREQCTRL, f); 00548 00549 /* If we are in receive mode, we issue an SRXON command to ensure 00550 that the VCO is calibrated. */ 00551 if(receive_on) { 00552 strobe(CC2520_INS_SRXON); 00553 } 00554 00555 RELEASE_LOCK(); 00556 return 1; 00557 } 00558 /*---------------------------------------------------------------------------*/ 00559 void 00560 cc2520_set_pan_addr(unsigned pan, 00561 unsigned addr, 00562 const uint8_t *ieee_addr) 00563 { 00564 uint8_t tmp[2]; 00565 00566 GET_LOCK(); 00567 00568 /* 00569 * Writing RAM requires crystal oscillator to be stable. 00570 */ 00571 BUSYWAIT_UNTIL(status() & (BV(CC2520_XOSC16M_STABLE)), RTIMER_SECOND / 10); 00572 00573 tmp[0] = pan & 0xff; 00574 tmp[1] = pan >> 8; 00575 CC2520_WRITE_RAM(&tmp, CC2520RAM_PANID, 2); 00576 00577 00578 tmp[0] = addr & 0xff; 00579 tmp[1] = addr >> 8; 00580 CC2520_WRITE_RAM(&tmp, CC2520RAM_SHORTADDR, 2); 00581 if(ieee_addr != NULL) { 00582 int f; 00583 uint8_t tmp_addr[8]; 00584 // LSB first, MSB last for 802.15.4 addresses in CC2520 00585 for (f = 0; f < 8; f++) { 00586 tmp_addr[7 - f] = ieee_addr[f]; 00587 } 00588 CC2520_WRITE_RAM(tmp_addr, CC2520RAM_IEEEADDR, 8); 00589 } 00590 RELEASE_LOCK(); 00591 } 00592 /*---------------------------------------------------------------------------*/ 00593 /* 00594 * Interrupt leaves frame intact in FIFO. 00595 */ 00596 #if CC2520_TIMETABLE_PROFILING 00597 #define cc2520_timetable_size 16 00598 TIMETABLE(cc2520_timetable); 00599 TIMETABLE_AGGREGATE(aggregate_time, 10); 00600 #endif /* CC2520_TIMETABLE_PROFILING */ 00601 int 00602 cc2520_interrupt(void) 00603 { 00604 CC2520_CLEAR_FIFOP_INT(); 00605 process_poll(&cc2520_process); 00606 #if CC2520_TIMETABLE_PROFILING 00607 timetable_clear(&cc2520_timetable); 00608 TIMETABLE_TIMESTAMP(cc2520_timetable, "interrupt"); 00609 #endif /* CC2520_TIMETABLE_PROFILING */ 00610 00611 last_packet_timestamp = cc2520_sfd_start_time; 00612 cc2520_packets_seen++; 00613 return 1; 00614 } 00615 /*---------------------------------------------------------------------------*/ 00616 PROCESS_THREAD(cc2520_process, ev, data) 00617 { 00618 int len; 00619 PROCESS_BEGIN(); 00620 00621 PRINTF("cc2520_process: started\n"); 00622 00623 while(1) { 00624 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); 00625 #if CC2520_TIMETABLE_PROFILING 00626 TIMETABLE_TIMESTAMP(cc2520_timetable, "poll"); 00627 #endif /* CC2520_TIMETABLE_PROFILING */ 00628 00629 PRINTF("cc2520_process: calling receiver callback\n"); 00630 00631 packetbuf_clear(); 00632 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp); 00633 len = cc2520_read(packetbuf_dataptr(), PACKETBUF_SIZE); 00634 packetbuf_set_datalen(len); 00635 00636 NETSTACK_RDC.input(); 00637 /* flushrx(); */ 00638 #if CC2520_TIMETABLE_PROFILING 00639 TIMETABLE_TIMESTAMP(cc2520_timetable, "end"); 00640 timetable_aggregate_compute_detailed(&aggregate_time, 00641 &cc2520_timetable); 00642 timetable_clear(&cc2520_timetable); 00643 #endif /* CC2520_TIMETABLE_PROFILING */ 00644 } 00645 00646 PROCESS_END(); 00647 } 00648 /*---------------------------------------------------------------------------*/ 00649 static int 00650 cc2520_read(void *buf, unsigned short bufsize) 00651 { 00652 uint8_t footer[2]; 00653 uint8_t len; 00654 00655 if(!CC2520_FIFOP_IS_1) { 00656 return 0; 00657 } 00658 00659 GET_LOCK(); 00660 00661 cc2520_packets_read++; 00662 00663 getrxbyte(&len); 00664 00665 if(len > CC2520_MAX_PACKET_LEN) { 00666 /* Oops, we must be out of sync. */ 00667 flushrx(); 00668 RIMESTATS_ADD(badsynch); 00669 RELEASE_LOCK(); 00670 return 0; 00671 } 00672 00673 if(len <= FOOTER_LEN) { 00674 flushrx(); 00675 RIMESTATS_ADD(tooshort); 00676 RELEASE_LOCK(); 00677 return 0; 00678 } 00679 00680 if(len - FOOTER_LEN > bufsize) { 00681 flushrx(); 00682 RIMESTATS_ADD(toolong); 00683 RELEASE_LOCK(); 00684 return 0; 00685 } 00686 00687 getrxdata(buf, len - FOOTER_LEN); 00688 getrxdata(footer, FOOTER_LEN); 00689 00690 if(footer[1] & FOOTER1_CRC_OK) { 00691 cc2520_last_rssi = footer[0]; 00692 cc2520_last_correlation = footer[1] & FOOTER1_CORRELATION; 00693 00694 00695 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2520_last_rssi); 00696 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2520_last_correlation); 00697 00698 RIMESTATS_ADD(llrx); 00699 00700 } else { 00701 RIMESTATS_ADD(badcrc); 00702 len = FOOTER_LEN; 00703 } 00704 00705 if(CC2520_FIFOP_IS_1) { 00706 if(!CC2520_FIFO_IS_1) { 00707 /* Clean up in case of FIFO overflow! This happens for every 00708 * full length frame and is signaled by FIFOP = 1 and FIFO = 00709 * 0. */ 00710 flushrx(); 00711 } else { 00712 /* Another packet has been received and needs attention. */ 00713 process_poll(&cc2520_process); 00714 } 00715 } 00716 00717 RELEASE_LOCK(); 00718 00719 if(len < FOOTER_LEN) { 00720 return 0; 00721 } 00722 00723 return len - FOOTER_LEN; 00724 } 00725 /*---------------------------------------------------------------------------*/ 00726 void 00727 cc2520_set_txpower(uint8_t power) 00728 { 00729 GET_LOCK(); 00730 set_txpower(power); 00731 RELEASE_LOCK(); 00732 } 00733 /*---------------------------------------------------------------------------*/ 00734 int 00735 cc2520_get_txpower(void) 00736 { 00737 uint8_t power; 00738 GET_LOCK(); 00739 power = getreg(CC2520_TXPOWER); 00740 RELEASE_LOCK(); 00741 return power; 00742 } 00743 /*---------------------------------------------------------------------------*/ 00744 int 00745 cc2520_rssi(void) 00746 { 00747 int rssi; 00748 int radio_was_off = 0; 00749 00750 if(locked) { 00751 return 0; 00752 } 00753 00754 GET_LOCK(); 00755 00756 if(!receive_on) { 00757 radio_was_off = 1; 00758 cc2520_on(); 00759 } 00760 BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID), RTIMER_SECOND / 100); 00761 00762 rssi = (int)((signed char)getreg(CC2520_RSSI)); 00763 00764 if(radio_was_off) { 00765 cc2520_off(); 00766 } 00767 RELEASE_LOCK(); 00768 return rssi; 00769 } 00770 /*---------------------------------------------------------------------------*/ 00771 /* 00772 static int 00773 detected_energy(void) 00774 { 00775 return cc2520_rssi(); 00776 } 00777 */ 00778 /*---------------------------------------------------------------------------*/ 00779 int 00780 cc2520_cca_valid(void) 00781 { 00782 int valid; 00783 if(locked) { 00784 return 1; 00785 } 00786 GET_LOCK(); 00787 valid = !!(status() & BV(CC2520_RSSI_VALID)); 00788 RELEASE_LOCK(); 00789 return valid; 00790 } 00791 /*---------------------------------------------------------------------------*/ 00792 static int 00793 cc2520_cca(void) 00794 { 00795 int cca; 00796 int radio_was_off = 0; 00797 00798 /* If the radio is locked by an underlying thread (because we are 00799 being invoked through an interrupt), we preted that the coast is 00800 clear (i.e., no packet is currently being transmitted by a 00801 neighbor). */ 00802 if(locked) { 00803 return 1; 00804 } 00805 00806 GET_LOCK(); 00807 if(!receive_on) { 00808 radio_was_off = 1; 00809 cc2520_on(); 00810 } 00811 00812 /* Make sure that the radio really got turned on. */ 00813 if(!receive_on) { 00814 RELEASE_LOCK(); 00815 if(radio_was_off) { 00816 cc2520_off(); 00817 } 00818 return 1; 00819 } 00820 00821 BUSYWAIT_UNTIL(status() & BV(CC2520_RSSI_VALID), RTIMER_SECOND / 100); 00822 00823 cca = CC2520_CCA_IS_1; 00824 00825 if(radio_was_off) { 00826 cc2520_off(); 00827 } 00828 RELEASE_LOCK(); 00829 return cca; 00830 } 00831 /*---------------------------------------------------------------------------*/ 00832 int 00833 cc2520_receiving_packet(void) 00834 { 00835 return CC2520_SFD_IS_1; 00836 } 00837 /*---------------------------------------------------------------------------*/ 00838 static int 00839 pending_packet(void) 00840 { 00841 return CC2520_FIFOP_IS_1; 00842 } 00843 /*---------------------------------------------------------------------------*/ 00844 void 00845 cc2520_set_cca_threshold(int value) 00846 { 00847 GET_LOCK(); 00848 setreg(CC2520_CCACTRL0, value & 0xff); 00849 RELEASE_LOCK(); 00850 } 00851 /*---------------------------------------------------------------------------*/