Contiki 2.5
cc2420.c
1 /*
2  * Copyright (c) 2007, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * @(#)$Id: cc2420.c,v 1.63 2011/01/09 21:09:28 adamdunkels Exp $
32  */
33 /*
34  * This code is almost device independent and should be easy to port.
35  */
36 
37 #include <string.h>
38 
39 #include "contiki.h"
40 
41 #if defined(__AVR__)
42 #include <avr/io.h>
43 #endif
44 
45 #include "dev/leds.h"
46 #include "dev/spi.h"
47 #include "dev/cc2420.h"
48 #include "dev/cc2420_const.h"
49 
50 #include "net/packetbuf.h"
51 #include "net/rime/rimestats.h"
52 #include "net/netstack.h"
53 
54 #include "sys/timetable.h"
55 
56 #define WITH_SEND_CCA 1
57 
58 #define FOOTER_LEN 2
59 
60 #ifndef CC2420_CONF_CHECKSUM
61 #define CC2420_CONF_CHECKSUM 0
62 #endif /* CC2420_CONF_CHECKSUM */
63 
64 #ifndef CC2420_CONF_AUTOACK
65 #define CC2420_CONF_AUTOACK 0
66 #endif /* CC2420_CONF_AUTOACK */
67 
68 #if CC2420_CONF_CHECKSUM
69 #include "lib/crc16.h"
70 #define CHECKSUM_LEN 2
71 #else
72 #define CHECKSUM_LEN 0
73 #endif /* CC2420_CONF_CHECKSUM */
74 
75 #define AUX_LEN (CHECKSUM_LEN + FOOTER_LEN)
76 
77 
78 #define FOOTER1_CRC_OK 0x80
79 #define FOOTER1_CORRELATION 0x7f
80 
81 #define DEBUG 0
82 #if DEBUG
83 #include <stdio.h>
84 #define PRINTF(...) printf(__VA_ARGS__)
85 #else
86 #define PRINTF(...) do {} while (0)
87 #endif
88 
89 #define DEBUG_LEDS DEBUG
90 #undef LEDS_ON
91 #undef LEDS_OFF
92 #if DEBUG_LEDS
93 #define LEDS_ON(x) leds_on(x)
94 #define LEDS_OFF(x) leds_off(x)
95 #else
96 #define LEDS_ON(x)
97 #define LEDS_OFF(x)
98 #endif
99 
100 void cc2420_arch_init(void);
101 
102 /* XXX hack: these will be made as Chameleon packet attributes */
103 rtimer_clock_t cc2420_time_of_arrival, cc2420_time_of_departure;
104 
105 int cc2420_authority_level_of_sender;
106 
107 int cc2420_packets_seen, cc2420_packets_read;
108 
109 static uint8_t volatile pending;
110 
111 #define BUSYWAIT_UNTIL(cond, max_time) \
112  do { \
113  rtimer_clock_t t0; \
114  t0 = RTIMER_NOW(); \
115  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
116  } while(0)
117 
118 volatile uint8_t cc2420_sfd_counter;
119 volatile uint16_t cc2420_sfd_start_time;
120 volatile uint16_t cc2420_sfd_end_time;
121 
122 static volatile uint16_t last_packet_timestamp;
123 /*---------------------------------------------------------------------------*/
124 PROCESS(cc2420_process, "CC2420 driver");
125 /*---------------------------------------------------------------------------*/
126 
127 
128 int cc2420_on(void);
129 int cc2420_off(void);
130 
131 static int cc2420_read(void *buf, unsigned short bufsize);
132 
133 static int cc2420_prepare(const void *data, unsigned short len);
134 static int cc2420_transmit(unsigned short len);
135 static int cc2420_send(const void *data, unsigned short len);
136 
137 static int cc2420_receiving_packet(void);
138 static int pending_packet(void);
139 static int cc2420_cca(void);
140 /*static int detected_energy(void);*/
141 
142 signed char cc2420_last_rssi;
143 uint8_t cc2420_last_correlation;
144 
145 const struct radio_driver cc2420_driver =
146  {
147  cc2420_init,
148  cc2420_prepare,
149  cc2420_transmit,
150  cc2420_send,
151  cc2420_read,
152  /* cc2420_set_channel, */
153  /* detected_energy, */
154  cc2420_cca,
155  cc2420_receiving_packet,
157  cc2420_on,
158  cc2420_off,
159  };
160 
161 static uint8_t receive_on;
162 
163 static int channel;
164 
165 /*---------------------------------------------------------------------------*/
166 
167 static void
168 getrxdata(void *buf, int len)
169 {
170  CC2420_READ_FIFO_BUF(buf, len);
171 }
172 static void
173 getrxbyte(uint8_t *byte)
174 {
175  CC2420_READ_FIFO_BYTE(*byte);
176 }
177 static void
178 flushrx(void)
179 {
180  uint8_t dummy;
181 
182  CC2420_READ_FIFO_BYTE(dummy);
183  CC2420_STROBE(CC2420_SFLUSHRX);
184  CC2420_STROBE(CC2420_SFLUSHRX);
185 }
186 /*---------------------------------------------------------------------------*/
187 static void
188 strobe(enum cc2420_register regname)
189 {
190  CC2420_STROBE(regname);
191 }
192 /*---------------------------------------------------------------------------*/
193 static unsigned int
194 status(void)
195 {
196  uint8_t status;
197  CC2420_GET_STATUS(status);
198  return status;
199 }
200 /*---------------------------------------------------------------------------*/
201 static uint8_t locked, lock_on, lock_off;
202 
203 static void
204 on(void)
205 {
206  CC2420_ENABLE_FIFOP_INT();
207  strobe(CC2420_SRXON);
208 
209  BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 100);
210 
211  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
212  receive_on = 1;
213 }
214 static void
215 off(void)
216 {
217  /* PRINTF("off\n");*/
218  receive_on = 0;
219 
220  /* Wait for transmission to end before turning radio off. */
221  BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
222 
223  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
224  strobe(CC2420_SRFOFF);
225  CC2420_DISABLE_FIFOP_INT();
226 
227  if(!CC2420_FIFOP_IS_1) {
228  flushrx();
229  }
230 }
231 /*---------------------------------------------------------------------------*/
232 #define GET_LOCK() locked++
233 static void RELEASE_LOCK(void) {
234  if(locked == 1) {
235  if(lock_on) {
236  on();
237  lock_on = 0;
238  }
239  if(lock_off) {
240  off();
241  lock_off = 0;
242  }
243  }
244  locked--;
245 }
246 /*---------------------------------------------------------------------------*/
247 static unsigned
248 getreg(enum cc2420_register regname)
249 {
250  unsigned reg;
251  CC2420_READ_REG(regname, reg);
252  return reg;
253 }
254 /*---------------------------------------------------------------------------*/
255 static void
256 setreg(enum cc2420_register regname, unsigned value)
257 {
258  CC2420_WRITE_REG(regname, value);
259 }
260 /*---------------------------------------------------------------------------*/
261 static void
262 set_txpower(uint8_t power)
263 {
264  uint16_t reg;
265 
266  reg = getreg(CC2420_TXCTRL);
267  reg = (reg & 0xffe0) | (power & 0x1f);
268  setreg(CC2420_TXCTRL, reg);
269 }
270 /*---------------------------------------------------------------------------*/
271 #define AUTOACK (1 << 4)
272 #define ADR_DECODE (1 << 11)
273 #define RXFIFO_PROTECTION (1 << 9)
274 #define CORR_THR(n) (((n) & 0x1f) << 6)
275 #define FIFOP_THR(n) ((n) & 0x7f)
276 #define RXBPF_LOCUR (1 << 13);
277 /*---------------------------------------------------------------------------*/
278 int
279 cc2420_init(void)
280 {
281  PRINTF("CC2420: init\n");
282  uint16_t reg;
283  {
284  int s = splhigh();
285  cc2420_arch_init(); /* Initalize ports and SPI. */
286  CC2420_DISABLE_FIFOP_INT();
287  CC2420_FIFOP_INT_INIT();
288  splx(s);
289  }
290 
291  /* Turn on voltage regulator and reset. */
292  SET_VREG_ACTIVE();
293  clock_delay(250);
294  SET_RESET_ACTIVE();
295  clock_delay(127);
296  SET_RESET_INACTIVE();
297  clock_delay(125);
298 
299 
300  /* Turn on the crystal oscillator. */
301  strobe(CC2420_SXOSCON);
302 
303  /* Turn on/off automatic packet acknowledgment and address decoding. */
304  reg = getreg(CC2420_MDMCTRL0);
305 
306 #if CC2420_CONF_AUTOACK
307  reg |= AUTOACK | ADR_DECODE;
308 #else
309  reg &= ~(AUTOACK | ADR_DECODE);
310 #endif /* CC2420_CONF_AUTOACK */
311  setreg(CC2420_MDMCTRL0, reg);
312 
313  /* Set transmission turnaround time to the lower setting (8 symbols
314  = 0.128 ms) instead of the default (12 symbols = 0.192 ms). */
315  /* reg = getreg(CC2420_TXCTRL);
316  reg &= ~(1 << 13);
317  setreg(CC2420_TXCTRL, reg);*/
318 
319 
320  /* Change default values as recomended in the data sheet, */
321  /* correlation threshold = 20, RX bandpass filter = 1.3uA. */
322  setreg(CC2420_MDMCTRL1, CORR_THR(20));
323  reg = getreg(CC2420_RXCTRL1);
324  reg |= RXBPF_LOCUR;
325  setreg(CC2420_RXCTRL1, reg);
326 
327  /* Set the FIFOP threshold to maximum. */
328  setreg(CC2420_IOCFG0, FIFOP_THR(127));
329 
330  /* Turn off "Security enable" (page 32). */
331  reg = getreg(CC2420_SECCTRL0);
332  reg &= ~RXFIFO_PROTECTION;
333  setreg(CC2420_SECCTRL0, reg);
334 
335  cc2420_set_pan_addr(0xffff, 0x0000, NULL);
336  cc2420_set_channel(26);
337 
338  flushrx();
339 
340  process_start(&cc2420_process, NULL);
341  return 1;
342 }
343 /*---------------------------------------------------------------------------*/
344 static int
345 cc2420_transmit(unsigned short payload_len)
346 {
347  int i, txpower;
348  uint8_t total_len;
349 #if CC2420_CONF_CHECKSUM
350  uint16_t checksum;
351 #endif /* CC2420_CONF_CHECKSUM */
352 
353  GET_LOCK();
354 
355  txpower = 0;
356  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
357  /* Remember the current transmission power */
358  txpower = cc2420_get_txpower();
359  /* Set the specified transmission power */
360  set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
361  }
362 
363  total_len = payload_len + AUX_LEN;
364 
365  /* The TX FIFO can only hold one packet. Make sure to not overrun
366  * FIFO by waiting for transmission to start here and synchronizing
367  * with the CC2420_TX_ACTIVE check in cc2420_send.
368  *
369  * Note that we may have to wait up to 320 us (20 symbols) before
370  * transmission starts.
371  */
372 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
373 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
374 #else
375 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
376 #endif
377 
378 #if WITH_SEND_CCA
379  strobe(CC2420_SRXON);
380  BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10);
381  strobe(CC2420_STXONCCA);
382 #else /* WITH_SEND_CCA */
383  strobe(CC2420_STXON);
384 #endif /* WITH_SEND_CCA */
385  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
386  if(CC2420_SFD_IS_1) {
387  {
388  rtimer_clock_t sfd_timestamp;
389  sfd_timestamp = cc2420_sfd_start_time;
390  if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
391  PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
392  /* Write timestamp to last two bytes of packet in TXFIFO. */
393  CC2420_WRITE_RAM(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2);
394  }
395  }
396 
397  if(!(status() & BV(CC2420_TX_ACTIVE))) {
398  /* SFD went high but we are not transmitting. This means that
399  we just started receiving a packet, so we drop the
400  transmission. */
401  RELEASE_LOCK();
402  return RADIO_TX_COLLISION;
403  }
404  if(receive_on) {
405  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
406  }
407  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
408  /* We wait until transmission has ended so that we get an
409  accurate measurement of the transmission time.*/
410  BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
411 
412 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
413  ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
414 #endif
415  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
416  if(receive_on) {
417  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
418  } else {
419  /* We need to explicitly turn off the radio,
420  * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
421  off();
422  }
423 
424  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
425  /* Restore the transmission power */
426  set_txpower(txpower & 0xff);
427  }
428 
429  RELEASE_LOCK();
430  return RADIO_TX_OK;
431  }
432  }
433 
434  /* If we are using WITH_SEND_CCA, we get here if the packet wasn't
435  transmitted because of other channel activity. */
436  RIMESTATS_ADD(contentiondrop);
437  PRINTF("cc2420: do_send() transmission never started\n");
438 
439  if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
440  /* Restore the transmission power */
441  set_txpower(txpower & 0xff);
442  }
443 
444  RELEASE_LOCK();
445  return RADIO_TX_COLLISION;
446 }
447 /*---------------------------------------------------------------------------*/
448 static int
449 cc2420_prepare(const void *payload, unsigned short payload_len)
450 {
451  uint8_t total_len;
452 #if CC2420_CONF_CHECKSUM
453  uint16_t checksum;
454 #endif /* CC2420_CONF_CHECKSUM */
455  GET_LOCK();
456 
457  PRINTF("cc2420: sending %d bytes\n", payload_len);
458 
459  RIMESTATS_ADD(lltx);
460 
461  /* Wait for any previous transmission to finish. */
462  /* while(status() & BV(CC2420_TX_ACTIVE));*/
463 
464  /* Write packet to TX FIFO. */
465  strobe(CC2420_SFLUSHTX);
466 
467 #if CC2420_CONF_CHECKSUM
468  checksum = crc16_data(payload, payload_len, 0);
469 #endif /* CC2420_CONF_CHECKSUM */
470  total_len = payload_len + AUX_LEN;
471  CC2420_WRITE_FIFO_BUF(&total_len, 1);
472  CC2420_WRITE_FIFO_BUF(payload, payload_len);
473 #if CC2420_CONF_CHECKSUM
474  CC2420_WRITE_FIFO_BUF(&checksum, CHECKSUM_LEN);
475 #endif /* CC2420_CONF_CHECKSUM */
476 
477  RELEASE_LOCK();
478  return 0;
479 }
480 /*---------------------------------------------------------------------------*/
481 static int
482 cc2420_send(const void *payload, unsigned short payload_len)
483 {
484  cc2420_prepare(payload, payload_len);
485  return cc2420_transmit(payload_len);
486 }
487 /*---------------------------------------------------------------------------*/
488 int
489 cc2420_off(void)
490 {
491 // PRINTF("CC2420: radio off\n");
492 
493  /* Don't do anything if we are already turned off. */
494  if(receive_on == 0) {
495  return 1;
496  }
497 
498  /* If we are called when the driver is locked, we indicate that the
499  radio should be turned off when the lock is unlocked. */
500  if(locked) {
501  /* printf("Off when locked (%d)\n", locked);*/
502  lock_off = 1;
503  return 1;
504  }
505 
506  GET_LOCK();
507  /* If we are currently receiving a packet (indicated by SFD == 1),
508  we don't actually switch the radio off now, but signal that the
509  driver should switch off the radio once the packet has been
510  received and processed, by setting the 'lock_off' variable. */
511  if(status() & BV(CC2420_TX_ACTIVE)) {
512  lock_off = 1;
513  } else {
514  off();
515  }
516  RELEASE_LOCK();
517  return 1;
518 }
519 /*---------------------------------------------------------------------------*/
520 int
521 cc2420_on(void)
522 {
523  if(receive_on) {
524  return 1;
525  }
526  if(locked) {
527  lock_on = 1;
528  return 1;
529  }
530 
531  GET_LOCK();
532  on();
533  RELEASE_LOCK();
534  return 1;
535 }
536 /*---------------------------------------------------------------------------*/
537 int
538 cc2420_get_channel(void)
539 {
540  return channel;
541 }
542 /*---------------------------------------------------------------------------*/
543 int
544 cc2420_set_channel(int c)
545 {
546  uint16_t f;
547 
548  GET_LOCK();
549  /*
550  * Subtract the base channel (11), multiply by 5, which is the
551  * channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
552  */
553  channel = c;
554 
555  f = 5 * (c - 11) + 357 + 0x4000;
556  /*
557  * Writing RAM requires crystal oscillator to be stable.
558  */
559  BUSYWAIT_UNTIL((status() & (BV(CC2420_XOSC16M_STABLE))), RTIMER_SECOND / 10);
560 
561  /* Wait for any transmission to end. */
562  BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
563 
564  setreg(CC2420_FSCTRL, f);
565 
566  /* If we are in receive mode, we issue an SRXON command to ensure
567  that the VCO is calibrated. */
568  if(receive_on) {
569  strobe(CC2420_SRXON);
570  }
571 
572  RELEASE_LOCK();
573  return 1;
574 }
575 /*---------------------------------------------------------------------------*/
576 void
577 cc2420_set_pan_addr(unsigned pan,
578  unsigned addr,
579  const uint8_t *ieee_addr)
580 {
581  uint16_t f = 0;
582  uint8_t tmp[2];
583 
584  GET_LOCK();
585 
586  /*
587  * Writing RAM requires crystal oscillator to be stable.
588  */
589  BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 10);
590 
591  tmp[0] = pan & 0xff;
592  tmp[1] = pan >> 8;
593  CC2420_WRITE_RAM(&tmp, CC2420RAM_PANID, 2);
594 
595  tmp[0] = addr & 0xff;
596  tmp[1] = addr >> 8;
597  CC2420_WRITE_RAM(&tmp, CC2420RAM_SHORTADDR, 2);
598  if(ieee_addr != NULL) {
599  uint8_t tmp_addr[8];
600  /* LSB first, MSB last for 802.15.4 addresses in CC2420 */
601  for (f = 0; f < 8; f++) {
602  tmp_addr[7 - f] = ieee_addr[f];
603  }
604  CC2420_WRITE_RAM(tmp_addr, CC2420RAM_IEEEADDR, 8);
605  }
606  RELEASE_LOCK();
607 }
608 /*---------------------------------------------------------------------------*/
609 /*
610  * Interrupt leaves frame intact in FIFO.
611  */
612 #if CC2420_TIMETABLE_PROFILING
613 #define cc2420_timetable_size 16
614 TIMETABLE(cc2420_timetable);
615 TIMETABLE_AGGREGATE(aggregate_time, 10);
616 #endif /* CC2420_TIMETABLE_PROFILING */
617 int
618 cc2420_interrupt(void)
619 {
620  PRINTF("got packet\n");
621  CC2420_CLEAR_FIFOP_INT();
622  process_poll(&cc2420_process);
623 #if CC2420_TIMETABLE_PROFILING
624  timetable_clear(&cc2420_timetable);
625  TIMETABLE_TIMESTAMP(cc2420_timetable, "interrupt");
626 #endif /* CC2420_TIMETABLE_PROFILING */
627 
628  last_packet_timestamp = cc2420_sfd_start_time;
629  pending++;
630  cc2420_packets_seen++;
631  return 1;
632 }
633 /*---------------------------------------------------------------------------*/
634 PROCESS_THREAD(cc2420_process, ev, data)
635 {
636  int len;
637  PROCESS_BEGIN();
638 
639  PRINTF("cc2420_process: started\n");
640 
641  while(1) {
642  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
643 #if CC2420_TIMETABLE_PROFILING
644  TIMETABLE_TIMESTAMP(cc2420_timetable, "poll");
645 #endif /* CC2420_TIMETABLE_PROFILING */
646 
647  PRINTF("cc2420_process: calling receiver callback\n");
648 
649  packetbuf_clear();
650  packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
651  len = cc2420_read(packetbuf_dataptr(), PACKETBUF_SIZE);
652 #if DEBUG
653  uint16_t i;
654  CC2420_GET_STATUS(i);
655  uint8_t regi;
656  regi= getreg(CC2420_IOCFG0);
657  PRINTF("cc2420_process: fifo threshold: %u, got %u bytes, CC2420 satus:%u \n",regi,len,i);
658 #endif
659 
660 
662 
663  NETSTACK_RDC.input();
664 #if CC2420_TIMETABLE_PROFILING
665  TIMETABLE_TIMESTAMP(cc2420_timetable, "end");
666  timetable_aggregate_compute_detailed(&aggregate_time,
667  &cc2420_timetable);
668  timetable_clear(&cc2420_timetable);
669 #endif /* CC2420_TIMETABLE_PROFILING */
670  }
671 
672  PROCESS_END();
673 }
674 /*---------------------------------------------------------------------------*/
675 static int
676 cc2420_read(void *buf, unsigned short bufsize)
677 {
678  uint8_t footer[2];
679  uint8_t len;
680 #if CC2420_CONF_CHECKSUM
681  uint16_t checksum;
682 #endif /* CC2420_CONF_CHECKSUM */
683 
684  if(!CC2420_FIFOP_IS_1) {
685  return 0;
686  }
687  /* if(!pending) {
688  return 0;
689  }*/
690 
691  pending = 0;
692 
693  GET_LOCK();
694 
695  cc2420_packets_read++;
696 
697  getrxbyte(&len);
698 
699  if(len > CC2420_MAX_PACKET_LEN) {
700  /* Oops, we must be out of sync. */
701  flushrx();
702  RIMESTATS_ADD(badsynch);
703  RELEASE_LOCK();
704  return 0;
705  }
706 
707  if(len <= AUX_LEN) {
708  flushrx();
709  RIMESTATS_ADD(tooshort);
710  RELEASE_LOCK();
711  return 0;
712  }
713 
714  if(len - AUX_LEN > bufsize) {
715  flushrx();
716  RIMESTATS_ADD(toolong);
717  RELEASE_LOCK();
718  return 0;
719  }
720 
721  getrxdata(buf, len - AUX_LEN);
722 #if CC2420_CONF_CHECKSUM
723  getrxdata(&checksum, CHECKSUM_LEN);
724 #endif /* CC2420_CONF_CHECKSUM */
725  getrxdata(footer, FOOTER_LEN);
726 
727 #if CC2420_CONF_CHECKSUM
728  if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
729  PRINTF("checksum failed 0x%04x != 0x%04x\n",
730  checksum, crc16_data(buf, len - AUX_LEN, 0));
731  }
732 
733  if(footer[1] & FOOTER1_CRC_OK &&
734  checksum == crc16_data(buf, len - AUX_LEN, 0)) {
735 #else
736  if(footer[1] & FOOTER1_CRC_OK) {
737 #endif /* CC2420_CONF_CHECKSUM */
738  cc2420_last_rssi = footer[0];
739  cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
740 
741 
742  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
743  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
744 
745  RIMESTATS_ADD(llrx);
746 
747  } else {
748  RIMESTATS_ADD(badcrc);
749  len = AUX_LEN;
750  }
751 
752  if(CC2420_FIFOP_IS_1) {
753  if(!CC2420_FIFO_IS_1) {
754  /* Clean up in case of FIFO overflow! This happens for every
755  * full length frame and is signaled by FIFOP = 1 and FIFO =
756  * 0. */
757  flushrx();
758  } else {
759  /* Another packet has been received and needs attention. */
760  process_poll(&cc2420_process);
761  }
762  }
763 
764  RELEASE_LOCK();
765 
766  if(len < AUX_LEN) {
767  return 0;
768  }
769 
770  return len - AUX_LEN;
771 }
772 /*---------------------------------------------------------------------------*/
773 void
774 cc2420_set_txpower(uint8_t power)
775 {
776  GET_LOCK();
777  set_txpower(power);
778  RELEASE_LOCK();
779 }
780 /*---------------------------------------------------------------------------*/
781 int
782 cc2420_get_txpower(void)
783 {
784  int power;
785  GET_LOCK();
786  power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
787  RELEASE_LOCK();
788  return power;
789 }
790 /*---------------------------------------------------------------------------*/
791 int
792 cc2420_rssi(void)
793 {
794  int rssi;
795  int radio_was_off = 0;
796 
797  if(locked) {
798  return 0;
799  }
800 
801  GET_LOCK();
802 
803  if(!receive_on) {
804  radio_was_off = 1;
805  cc2420_on();
806  }
807  BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
808 
809  rssi = (int)((signed char)getreg(CC2420_RSSI));
810 
811  if(radio_was_off) {
812  cc2420_off();
813  }
814  RELEASE_LOCK();
815  return rssi;
816 }
817 /*---------------------------------------------------------------------------*/
818 /*
819 static int
820 detected_energy(void)
821 {
822  return cc2420_rssi();
823 }
824 */
825 /*---------------------------------------------------------------------------*/
826 int
827 cc2420_cca_valid(void)
828 {
829  int valid;
830  if(locked) {
831  return 1;
832  }
833  GET_LOCK();
834  valid = !!(status() & BV(CC2420_RSSI_VALID));
835  RELEASE_LOCK();
836  return valid;
837 }
838 /*---------------------------------------------------------------------------*/
839 static int
840 cc2420_cca(void)
841 {
842  int cca;
843  int radio_was_off = 0;
844 
845  /* If the radio is locked by an underlying thread (because we are
846  being invoked through an interrupt), we preted that the coast is
847  clear (i.e., no packet is currently being transmitted by a
848  neighbor). */
849  if(locked) {
850  return 1;
851  }
852 
853  GET_LOCK();
854  if(!receive_on) {
855  radio_was_off = 1;
856  cc2420_on();
857  }
858 
859  /* Make sure that the radio really got turned on. */
860  if(!receive_on) {
861  RELEASE_LOCK();
862  if(radio_was_off) {
863  cc2420_off();
864  }
865  return 1;
866  }
867 
868  BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
869 
870  cca = CC2420_CCA_IS_1;
871 
872  if(radio_was_off) {
873  cc2420_off();
874  }
875  RELEASE_LOCK();
876  return cca;
877 }
878 /*---------------------------------------------------------------------------*/
879 int
880 cc2420_receiving_packet(void)
881 {
882  return CC2420_SFD_IS_1;
883 }
884 /*---------------------------------------------------------------------------*/
885 static int
886 pending_packet(void)
887 {
888  return CC2420_FIFOP_IS_1;
889 }
890 /*---------------------------------------------------------------------------*/
891 void
892 cc2420_set_cca_threshold(int value)
893 {
894  uint16_t shifted = value << 8;
895  GET_LOCK();
896  setreg(CC2420_RSSI, shifted);
897  RELEASE_LOCK();
898 }
899 /*---------------------------------------------------------------------------*/