Contiki-NG
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  */
32 /*
33  * This code is almost device independent and should be easy to port.
34  */
35 
36 #include <string.h>
37 
38 #include "contiki.h"
39 #include "sys/energest.h"
40 
41 #include "dev/leds.h"
42 #include "dev/spi-legacy.h"
43 #include "cc2420.h"
44 #include "cc2420_const.h"
45 
46 #include "net/packetbuf.h"
47 #include "net/netstack.h"
48 
49 enum write_ram_order {
50  /* Begin with writing the first given byte */
51  WRITE_RAM_IN_ORDER,
52  /* Begin with writing the last given byte */
53  WRITE_RAM_REVERSE
54 };
55 
56 #define DEBUG 0
57 #if DEBUG
58 #include <stdio.h>
59 #define PRINTF(...) printf(__VA_ARGS__)
60 #else
61 #define PRINTF(...) do {} while (0)
62 #endif
63 
64 #define DEBUG_LEDS DEBUG
65 #undef LEDS_ON
66 #undef LEDS_OFF
67 #if DEBUG_LEDS
68 #define LEDS_ON(x) leds_on(x)
69 #define LEDS_OFF(x) leds_off(x)
70 #else
71 #define LEDS_ON(x)
72 #define LEDS_OFF(x)
73 #endif
74 
75 /* Conversion map between PA_LEVEL and output power in dBm
76  (from table 9 in CC2420 specification).
77 */
78 struct output_config {
79  int8_t power;
80  uint8_t config;
81 };
82 
83 static const struct output_config output_power[] = {
84  { 0, 31 }, /* 0xff */
85  { -1, 27 }, /* 0xfb */
86  { -3, 23 }, /* 0xf7 */
87  { -5, 19 }, /* 0xf3 */
88  { -7, 15 }, /* 0xef */
89  {-10, 11 }, /* 0xeb */
90  {-15, 7 }, /* 0xe7 */
91  {-25, 3 }, /* 0xe3 */
92 };
93 #define OUTPUT_NUM (sizeof(output_power) / sizeof(struct output_config))
94 #define OUTPUT_POWER_MAX 0
95 #define OUTPUT_POWER_MIN -25
96 
97 void cc2420_arch_init(void);
98 
99 int cc2420_authority_level_of_sender;
100 
101 volatile uint8_t cc2420_sfd_counter;
102 volatile uint16_t cc2420_sfd_start_time;
103 volatile uint16_t cc2420_sfd_end_time;
104 
105 static volatile uint16_t last_packet_timestamp;
106 /*---------------------------------------------------------------------------*/
107 PROCESS(cc2420_process, "CC2420 driver");
108 /*---------------------------------------------------------------------------*/
109 
110 #define AUTOACK (1 << 4)
111 #define AUTOCRC (1 << 5)
112 #define ADR_DECODE (1 << 11)
113 #define RXFIFO_PROTECTION (1 << 9)
114 #define CORR_THR(n) (((n) & 0x1f) << 6)
115 #define FIFOP_THR(n) ((n) & 0x7f)
116 #define RXBPF_LOCUR (1 << 13);
117 
118 int cc2420_on(void);
119 int cc2420_off(void);
120 
121 static int cc2420_read(void *buf, unsigned short bufsize);
122 
123 static int cc2420_prepare(const void *data, unsigned short len);
124 static int cc2420_transmit(unsigned short len);
125 static int cc2420_send(const void *data, unsigned short len);
126 
127 static int cc2420_receiving_packet(void);
128 static int pending_packet(void);
129 static int get_cca_threshold(void);
130 static int cc2420_cca(void);
131 static uint16_t getreg(enum cc2420_register regname);
132 
133 static void set_frame_filtering(uint8_t enable);
134 static void set_poll_mode(uint8_t enable);
135 static void set_send_on_cca(uint8_t enable);
136 static void set_auto_ack(uint8_t enable);
137 
138 signed char cc2420_last_rssi;
139 uint8_t cc2420_last_correlation;
140 
141 static uint8_t receive_on;
142 static int channel;
143 
144 /* Are we currently in poll mode? */
145 static uint8_t volatile poll_mode = 0;
146 /* Do we perform a CCA before sending? */
147 static uint8_t send_on_cca = WITH_SEND_CCA;
148 
149 static radio_result_t
150 get_value(radio_param_t param, radio_value_t *value)
151 {
152  int i, v;
153 
154  if(!value) {
155  return RADIO_RESULT_INVALID_VALUE;
156  }
157  switch(param) {
158  case RADIO_PARAM_POWER_MODE:
159  *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
160  return RADIO_RESULT_OK;
161  case RADIO_PARAM_CHANNEL:
162  *value = cc2420_get_channel();
163  return RADIO_RESULT_OK;
164  case RADIO_PARAM_RX_MODE:
165  *value = 0;
166  if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
168  }
169  if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
170  *value |= RADIO_RX_MODE_AUTOACK;
171  }
172  if(poll_mode) {
173  *value |= RADIO_RX_MODE_POLL_MODE;
174  }
175  return RADIO_RESULT_OK;
176  case RADIO_PARAM_TX_MODE:
177  *value = 0;
178  if(send_on_cca) {
179  *value |= RADIO_TX_MODE_SEND_ON_CCA;
180  }
181  return RADIO_RESULT_OK;
182  case RADIO_PARAM_TXPOWER:
183  v = cc2420_get_txpower();
184  *value = OUTPUT_POWER_MIN;
185  /* Find the actual estimated output power in conversion table */
186  for(i = 0; i < OUTPUT_NUM; i++) {
187  if(v >= output_power[i].config) {
188  *value = output_power[i].power;
189  break;
190  }
191  }
192  return RADIO_RESULT_OK;
193  case RADIO_PARAM_CCA_THRESHOLD:
194  *value = get_cca_threshold() + RSSI_OFFSET;
195  return RADIO_RESULT_OK;
196  case RADIO_PARAM_RSSI:
197  /* Return the RSSI value in dBm */
198  *value = cc2420_rssi();
199  return RADIO_RESULT_OK;
200  case RADIO_PARAM_LAST_RSSI:
201  /* RSSI of the last packet received */
202  *value = cc2420_last_rssi;
203  return RADIO_RESULT_OK;
204  case RADIO_PARAM_LAST_LINK_QUALITY:
205  /* LQI of the last packet received */
206  *value = cc2420_last_correlation;
207  return RADIO_RESULT_OK;
208  case RADIO_CONST_CHANNEL_MIN:
209  *value = 11;
210  return RADIO_RESULT_OK;
211  case RADIO_CONST_CHANNEL_MAX:
212  *value = 26;
213  return RADIO_RESULT_OK;
214  case RADIO_CONST_TXPOWER_MIN:
215  *value = OUTPUT_POWER_MIN;
216  return RADIO_RESULT_OK;
217  case RADIO_CONST_TXPOWER_MAX:
218  *value = OUTPUT_POWER_MAX;
219  return RADIO_RESULT_OK;
220  default:
221  return RADIO_RESULT_NOT_SUPPORTED;
222  }
223 }
224 
225 static radio_result_t
226 set_value(radio_param_t param, radio_value_t value)
227 {
228  int i;
229 
230  switch(param) {
231  case RADIO_PARAM_POWER_MODE:
232  if(value == RADIO_POWER_MODE_ON) {
233  cc2420_on();
234  return RADIO_RESULT_OK;
235  }
236  if(value == RADIO_POWER_MODE_OFF) {
237  cc2420_off();
238  return RADIO_RESULT_OK;
239  }
240  return RADIO_RESULT_INVALID_VALUE;
241  case RADIO_PARAM_CHANNEL:
242  if(value < 11 || value > 26) {
243  return RADIO_RESULT_INVALID_VALUE;
244  }
245  cc2420_set_channel(value);
246  return RADIO_RESULT_OK;
247  case RADIO_PARAM_RX_MODE:
248  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
249  RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
250  return RADIO_RESULT_INVALID_VALUE;
251  }
252  set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
253  set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
254  set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
255  return RADIO_RESULT_OK;
256  case RADIO_PARAM_TX_MODE:
257  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
258  return RADIO_RESULT_INVALID_VALUE;
259  }
260  set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
261  return RADIO_RESULT_OK;
262  case RADIO_PARAM_TXPOWER:
263  if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
264  return RADIO_RESULT_INVALID_VALUE;
265  }
266  /* Find the closest higher PA_LEVEL for the desired output power */
267  for(i = 1; i < OUTPUT_NUM; i++) {
268  if(value > output_power[i].power) {
269  break;
270  }
271  }
272  cc2420_set_txpower(output_power[i - 1].config);
273  return RADIO_RESULT_OK;
274  case RADIO_PARAM_CCA_THRESHOLD:
275  cc2420_set_cca_threshold(value - RSSI_OFFSET);
276  return RADIO_RESULT_OK;
277  default:
278  return RADIO_RESULT_NOT_SUPPORTED;
279  }
280 }
281 
282 static radio_result_t
283 get_object(radio_param_t param, void *dest, size_t size)
284 {
285  if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
286 #if CC2420_CONF_SFD_TIMESTAMPS
287  if(size != sizeof(rtimer_clock_t) || !dest) {
288  return RADIO_RESULT_INVALID_VALUE;
289  }
290  *(rtimer_clock_t*)dest = cc2420_sfd_start_time;
291  return RADIO_RESULT_OK;
292 #else
293  return RADIO_RESULT_NOT_SUPPORTED;
294 #endif
295  }
296  return RADIO_RESULT_NOT_SUPPORTED;
297 }
298 
299 static radio_result_t
300 set_object(radio_param_t param, const void *src, size_t size)
301 {
302  return RADIO_RESULT_NOT_SUPPORTED;
303 }
304 
305 const struct radio_driver cc2420_driver =
306  {
307  cc2420_init,
308  cc2420_prepare,
309  cc2420_transmit,
310  cc2420_send,
311  cc2420_read,
312  cc2420_cca,
313  cc2420_receiving_packet,
315  cc2420_on,
316  cc2420_off,
317  get_value,
318  set_value,
319  get_object,
320  set_object
321  };
322 
323 /*---------------------------------------------------------------------------*/
324 /* Sends a strobe */
325 static void
326 strobe(enum cc2420_register regname)
327 {
328  CC2420_SPI_ENABLE();
329  SPI_WRITE(regname);
330  CC2420_SPI_DISABLE();
331 }
332 /*---------------------------------------------------------------------------*/
333 /* Reads a register */
334 static uint16_t
335 getreg(enum cc2420_register regname)
336 {
337  uint16_t value;
338 
339  CC2420_SPI_ENABLE();
340  SPI_WRITE(regname | 0x40);
341  value = (uint8_t)SPI_RXBUF;
342  SPI_TXBUF = 0;
343  SPI_WAITFOREORx();
344  value = SPI_RXBUF << 8;
345  SPI_TXBUF = 0;
346  SPI_WAITFOREORx();
347  value |= SPI_RXBUF;
348  CC2420_SPI_DISABLE();
349 
350  return value;
351 }
352 /*---------------------------------------------------------------------------*/
353 /**
354  * Writes to a register.
355  * Note: the SPI_WRITE(0) seems to be needed for getting the
356  * write reg working on the Z1 / MSP430X platform
357  */
358 static void
359 setreg(enum cc2420_register regname, uint16_t value)
360 {
361  CC2420_SPI_ENABLE();
362  SPI_WRITE_FAST(regname);
363  SPI_WRITE_FAST((uint8_t) (value >> 8));
364  SPI_WRITE_FAST((uint8_t) (value & 0xff));
365  SPI_WAITFORTx_ENDED();
366  SPI_WRITE(0);
367  CC2420_SPI_DISABLE();
368 }
369 /*---------------------------------------------------------------------------*/
370 static void
371 read_ram(uint8_t *buffer, uint16_t adr, uint16_t count)
372 {
373  uint8_t i;
374 
375  CC2420_SPI_ENABLE();
376  SPI_WRITE(0x80 | ((adr) & 0x7f));
377  SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20);
378  SPI_RXBUF;
379  for(i = 0; i < count; i++) {
380  SPI_READ(((uint8_t*) buffer)[i]);
381  }
382  CC2420_SPI_DISABLE();
383 }
384 /*---------------------------------------------------------------------------*/
385 /* Write to RAM in the CC2420 */
386 static void
387 write_ram(const uint8_t *buffer,
388  uint16_t adr,
389  uint16_t count,
390  enum write_ram_order order)
391 {
392  uint8_t i;
393 
394  CC2420_SPI_ENABLE();
395  SPI_WRITE_FAST(0x80 | (adr & 0x7f));
396  SPI_WRITE_FAST((adr >> 1) & 0xc0);
397  if(order == WRITE_RAM_IN_ORDER) {
398  for(i = 0; i < count; i++) {
399  SPI_WRITE_FAST((buffer)[i]);
400  }
401  } else {
402  for(i = count; i > 0; i--) {
403  SPI_WRITE_FAST((buffer)[i - 1]);
404  }
405  }
406  SPI_WAITFORTx_ENDED();
407  CC2420_SPI_DISABLE();
408 }
409 /*---------------------------------------------------------------------------*/
410 static void
411 write_fifo_buf(const uint8_t *buffer, uint16_t count)
412 {
413  uint8_t i;
414 
415  CC2420_SPI_ENABLE();
416  SPI_WRITE_FAST(CC2420_TXFIFO);
417  for(i = 0; i < count; i++) {
418  SPI_WRITE_FAST((buffer)[i]);
419  }
420  SPI_WAITFORTx_ENDED();
421  CC2420_SPI_DISABLE();
422 }
423 /*---------------------------------------------------------------------------*/
424 /* Returns the current status */
425 static uint8_t
426 get_status(void)
427 {
428  uint8_t status;
429 
430  CC2420_SPI_ENABLE();
431  SPI_WRITE(CC2420_SNOP);
432  status = SPI_RXBUF;
433  CC2420_SPI_DISABLE();
434 
435  return status;
436 }
437 /*---------------------------------------------------------------------------*/
438 static void
439 getrxdata(uint8_t *buffer, int count)
440 {
441  uint8_t i;
442 
443  CC2420_SPI_ENABLE();
444  SPI_WRITE(CC2420_RXFIFO | 0x40);
445  (void) SPI_RXBUF;
446  for(i = 0; i < count; i++) {
447  SPI_READ(buffer[i]);
448  }
449  clock_delay(1);
450  CC2420_SPI_DISABLE();
451 }
452 /*---------------------------------------------------------------------------*/
453 static void
454 flushrx(void)
455 {
456  uint8_t dummy;
457 
458  getrxdata(&dummy, 1);
459  strobe(CC2420_SFLUSHRX);
460  strobe(CC2420_SFLUSHRX);
461  if(dummy) {
462  /* avoid unused variable compiler warning */
463  }
464 }
465 /*---------------------------------------------------------------------------*/
466 static void
467 wait_for_status(uint8_t status_bit)
468 {
469  rtimer_clock_t t0;
470  t0 = RTIMER_NOW();
471  while(!(get_status() & status_bit)
472  && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
473 }
474 /*---------------------------------------------------------------------------*/
475 static void
476 wait_for_transmission(void)
477 {
478  rtimer_clock_t t0;
479  t0 = RTIMER_NOW();
480  while((get_status() & BV(CC2420_TX_ACTIVE))
481  && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
482 }
483 /*---------------------------------------------------------------------------*/
484 static void
485 on(void)
486 {
487  if(!poll_mode) {
488  CC2420_ENABLE_FIFOP_INT();
489  }
490 
491  strobe(CC2420_SRXON);
492 
493  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
494  receive_on = 1;
495 }
496 /*---------------------------------------------------------------------------*/
497 static void
498 off(void)
499 {
500  /* PRINTF("off\n");*/
501  receive_on = 0;
502 
503  /* Wait for transmission to end before turning radio off. */
504  wait_for_transmission();
505 
506  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
507  strobe(CC2420_SRFOFF);
508  if(!poll_mode) {
509  CC2420_DISABLE_FIFOP_INT();
510  }
511 
512  if(!CC2420_FIFOP_IS_1) {
513  flushrx();
514  }
515 }
516 /*---------------------------------------------------------------------------*/
517 static uint8_t locked, lock_on, lock_off;
518 #define GET_LOCK() locked++
519 static void RELEASE_LOCK(void) {
520  if(locked == 1) {
521  if(lock_on) {
522  on();
523  lock_on = 0;
524  }
525  if(lock_off) {
526  off();
527  lock_off = 0;
528  }
529  }
530  locked--;
531 }
532 /*---------------------------------------------------------------------------*/
533 static void
534 init_security(void)
535 {
536  /* only use key 0 */
537  setreg(CC2420_SECCTRL0, 0);
538  setreg(CC2420_SECCTRL1, 0);
539 }
540 /*---------------------------------------------------------------------------*/
541 static void
542 set_key(const uint8_t *key)
543 {
544  GET_LOCK();
545 
546  write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE);
547 
548  RELEASE_LOCK();
549 }
550 /*---------------------------------------------------------------------------*/
551 static void
552 encrypt(uint8_t *plaintext_and_result)
553 {
554  GET_LOCK();
555 
556  write_ram(plaintext_and_result,
557  CC2420RAM_SABUF,
558  16,
559  WRITE_RAM_IN_ORDER);
560 
561  strobe(CC2420_SAES);
562  while(get_status() & BV(CC2420_ENC_BUSY));
563 
564  read_ram(plaintext_and_result, CC2420RAM_SABUF, 16);
565 
566  RELEASE_LOCK();
567 }
568 /*---------------------------------------------------------------------------*/
569 const struct aes_128_driver cc2420_aes_128_driver = {
570  set_key,
571  encrypt
572 };
573 /*---------------------------------------------------------------------------*/
574 static void
575 set_txpower(uint8_t power)
576 {
577  uint16_t reg;
578 
579  reg = getreg(CC2420_TXCTRL);
580  reg = (reg & 0xffe0) | (power & 0x1f);
581  setreg(CC2420_TXCTRL, reg);
582 }
583 /*---------------------------------------------------------------------------*/
584 int
585 cc2420_init(void)
586 {
587  uint16_t reg;
588  {
589  int s = splhigh();
590  cc2420_arch_init(); /* Initalize ports and SPI. */
591  CC2420_DISABLE_FIFOP_INT();
592  CC2420_FIFOP_INT_INIT();
593  splx(s);
594  }
595 
596  /* Turn on voltage regulator and reset. */
597  SET_VREG_ACTIVE();
598  clock_delay(250);
599  SET_RESET_ACTIVE();
600  clock_delay(127);
601  SET_RESET_INACTIVE();
602  clock_delay(125);
603 
604 
605  /* Turn on the crystal oscillator. */
606  strobe(CC2420_SXOSCON);
607  /* And wait until it stabilizes */
608  wait_for_status(BV(CC2420_XOSC16M_STABLE));
609 
610  /* Set auto-ack and frame filtering */
611  set_auto_ack(CC2420_CONF_AUTOACK);
612  set_frame_filtering(CC2420_CONF_AUTOACK);
613 
614  /* Enabling CRC in hardware; this is required by AUTOACK anyway
615  and provides us with RSSI and link quality indication (LQI)
616  information. */
617  reg = getreg(CC2420_MDMCTRL0);
618  reg |= AUTOCRC;
619  setreg(CC2420_MDMCTRL0, reg);
620 
621  /* Set transmission turnaround time to the lower setting (8 symbols
622  = 0.128 ms) instead of the default (12 symbols = 0.192 ms). */
623  /* reg = getreg(CC2420_TXCTRL);
624  reg &= ~(1 << 13);
625  setreg(CC2420_TXCTRL, reg);*/
626 
627 
628  /* Change default values as recomended in the data sheet, */
629  /* correlation threshold = 20, RX bandpass filter = 1.3uA. */
630  setreg(CC2420_MDMCTRL1, CORR_THR(20));
631  reg = getreg(CC2420_RXCTRL1);
632  reg |= RXBPF_LOCUR;
633  setreg(CC2420_RXCTRL1, reg);
634 
635  /* Set the FIFOP threshold to maximum. */
636  setreg(CC2420_IOCFG0, FIFOP_THR(127));
637 
638  init_security();
639 
640  cc2420_set_pan_addr(0xffff, 0x0000, NULL);
641  cc2420_set_channel(IEEE802154_DEFAULT_CHANNEL);
642  cc2420_set_cca_threshold(CC2420_CONF_CCA_THRESH);
643 
644  flushrx();
645 
646  set_poll_mode(0);
647 
648  process_start(&cc2420_process, NULL);
649  return 1;
650 }
651 /*---------------------------------------------------------------------------*/
652 static int
653 cc2420_transmit(unsigned short payload_len)
654 {
655  int i;
656 
657  GET_LOCK();
658 
659  /* The TX FIFO can only hold one packet. Make sure to not overrun
660  * FIFO by waiting for transmission to start here and synchronizing
661  * with the CC2420_TX_ACTIVE check in cc2420_send.
662  *
663  * Note that we may have to wait up to 320 us (20 symbols) before
664  * transmission starts.
665  */
666 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
667 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
668 #else
669 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
670 #endif
671 
672  if(send_on_cca) {
673  strobe(CC2420_SRXON);
674  wait_for_status(BV(CC2420_RSSI_VALID));
675  strobe(CC2420_STXONCCA);
676  } else {
677  strobe(CC2420_STXON);
678  }
679  for(i = LOOP_20_SYMBOLS; i > 0; i--) {
680  if(CC2420_SFD_IS_1) {
681  if(!(get_status() & BV(CC2420_TX_ACTIVE))) {
682  /* SFD went high but we are not transmitting. This means that
683  we just started receiving a packet, so we drop the
684  transmission. */
685  RELEASE_LOCK();
686  return RADIO_TX_COLLISION;
687  }
688  if(receive_on) {
689  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
690  }
691  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
692  /* We wait until transmission has ended so that we get an
693  accurate measurement of the transmission time.*/
694  wait_for_transmission();
695 
696  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
697  if(receive_on) {
698  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
699  } else {
700  /* We need to explicitly turn off the radio,
701  * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
702  off();
703  }
704 
705  RELEASE_LOCK();
706  return RADIO_TX_OK;
707  }
708  }
709 
710  /* If we send with cca (cca_on_send), we get here if the packet wasn't
711  transmitted because of other channel activity. */
712  PRINTF("cc2420: do_send() transmission never started\n");
713 
714  RELEASE_LOCK();
715  return RADIO_TX_COLLISION;
716 }
717 /*---------------------------------------------------------------------------*/
718 static int
719 cc2420_prepare(const void *payload, unsigned short payload_len)
720 {
721  uint8_t total_len;
722 
723  GET_LOCK();
724 
725  PRINTF("cc2420: sending %d bytes\n", payload_len);
726 
727  /* Wait for any previous transmission to finish. */
728  /* while(status() & BV(CC2420_TX_ACTIVE));*/
729 
730  /* Write packet to TX FIFO. */
731  strobe(CC2420_SFLUSHTX);
732 
733  total_len = payload_len + CHECKSUM_LEN;
734  write_fifo_buf(&total_len, 1);
735  write_fifo_buf(payload, payload_len);
736 
737  RELEASE_LOCK();
738  return 0;
739 }
740 /*---------------------------------------------------------------------------*/
741 static int
742 cc2420_send(const void *payload, unsigned short payload_len)
743 {
744  cc2420_prepare(payload, payload_len);
745  return cc2420_transmit(payload_len);
746 }
747 /*---------------------------------------------------------------------------*/
748 int
749 cc2420_off(void)
750 {
751  /* Don't do anything if we are already turned off. */
752  if(receive_on == 0) {
753  return 1;
754  }
755 
756  /* If we are called when the driver is locked, we indicate that the
757  radio should be turned off when the lock is unlocked. */
758  if(locked) {
759  /* printf("Off when locked (%d)\n", locked);*/
760  lock_off = 1;
761  return 1;
762  }
763 
764  GET_LOCK();
765  /* If we are currently receiving a packet (indicated by SFD == 1),
766  we don't actually switch the radio off now, but signal that the
767  driver should switch off the radio once the packet has been
768  received and processed, by setting the 'lock_off' variable. */
769  if(get_status() & BV(CC2420_TX_ACTIVE)) {
770  lock_off = 1;
771  } else {
772  off();
773  }
774  RELEASE_LOCK();
775  return 1;
776 }
777 /*---------------------------------------------------------------------------*/
778 int
779 cc2420_on(void)
780 {
781  if(receive_on) {
782  return 1;
783  }
784  if(locked) {
785  lock_on = 1;
786  return 1;
787  }
788 
789  GET_LOCK();
790  on();
791  RELEASE_LOCK();
792  return 1;
793 }
794 /*---------------------------------------------------------------------------*/
795 int
796 cc2420_get_channel(void)
797 {
798  return channel;
799 }
800 /*---------------------------------------------------------------------------*/
801 int
802 cc2420_set_channel(int c)
803 {
804  uint16_t f;
805 
806  GET_LOCK();
807  /*
808  * Subtract the base channel (11), multiply by 5, which is the
809  * channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
810  */
811  channel = c;
812 
813  f = 5 * (c - 11) + 357 + 0x4000;
814 
815  /* Wait for any transmission to end. */
816  wait_for_transmission();
817 
818  setreg(CC2420_FSCTRL, f);
819 
820  /* If we are in receive mode, we issue an SRXON command to ensure
821  that the VCO is calibrated. */
822  if(receive_on) {
823  strobe(CC2420_SRXON);
824  }
825 
826  RELEASE_LOCK();
827  return 1;
828 }
829 /*---------------------------------------------------------------------------*/
830 void
831 cc2420_set_pan_addr(unsigned pan,
832  unsigned addr,
833  const uint8_t *ieee_addr)
834 {
835  GET_LOCK();
836 
837  write_ram((uint8_t *) &pan, CC2420RAM_PANID, 2, WRITE_RAM_IN_ORDER);
838  write_ram((uint8_t *) &addr, CC2420RAM_SHORTADDR, 2, WRITE_RAM_IN_ORDER);
839 
840  if(ieee_addr != NULL) {
841  write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE);
842  }
843  RELEASE_LOCK();
844 }
845 /*---------------------------------------------------------------------------*/
846 /*
847  * Interrupt leaves frame intact in FIFO.
848  */
849 int
851 {
852  CC2420_CLEAR_FIFOP_INT();
853  process_poll(&cc2420_process);
854 
855  last_packet_timestamp = cc2420_sfd_start_time;
856  return 1;
857 }
858 /*---------------------------------------------------------------------------*/
859 PROCESS_THREAD(cc2420_process, ev, data)
860 {
861  int len;
862  PROCESS_BEGIN();
863 
864  PRINTF("cc2420_process: started\n");
865 
866  while(1) {
867  PROCESS_YIELD_UNTIL(!poll_mode && ev == PROCESS_EVENT_POLL);
868 
869  PRINTF("cc2420_process: calling receiver callback\n");
870 
871  packetbuf_clear();
872  packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
873  len = cc2420_read(packetbuf_dataptr(), PACKETBUF_SIZE);
874 
876 
877  NETSTACK_MAC.input();
878  }
879 
880  PROCESS_END();
881 }
882 /*---------------------------------------------------------------------------*/
883 static int
884 cc2420_read(void *buf, unsigned short bufsize)
885 {
886  uint8_t footer[FOOTER_LEN];
887  uint8_t len;
888 
889  if(!CC2420_FIFOP_IS_1) {
890  return 0;
891  }
892 
893  GET_LOCK();
894 
895  getrxdata(&len, 1);
896 
897  if(len > CC2420_MAX_PACKET_LEN) {
898  /* Oops, we must be out of sync. */
899  } else if(len <= FOOTER_LEN) {
900  /* Packet too short */
901  } else if(len - FOOTER_LEN > bufsize) {
902  /* Packet too long */
903  } else {
904  getrxdata((uint8_t *) buf, len - FOOTER_LEN);
905  getrxdata(footer, FOOTER_LEN);
906 
907  if(footer[1] & FOOTER1_CRC_OK) {
908  cc2420_last_rssi = footer[0] + RSSI_OFFSET;
909  cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
910  if(!poll_mode) {
911  /* Not in poll mode: packetbuf should not be accessed in interrupt context.
912  * In poll mode, the last packet RSSI and link quality can be obtained through
913  * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
914  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
915  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
916  }
917  } else {
918  len = FOOTER_LEN;
919  }
920 
921  if(!poll_mode) {
922  if(CC2420_FIFOP_IS_1) {
923  if(!CC2420_FIFO_IS_1) {
924  /* Clean up in case of FIFO overflow! This happens for every
925  * full length frame and is signaled by FIFOP = 1 and FIFO =
926  * 0. */
927  flushrx();
928  } else {
929  /* Another packet has been received and needs attention. */
930  process_poll(&cc2420_process);
931  }
932  }
933  }
934 
935  RELEASE_LOCK();
936  return len - FOOTER_LEN;
937  }
938 
939  flushrx();
940  RELEASE_LOCK();
941  return 0;
942 }
943 /*---------------------------------------------------------------------------*/
944 void
945 cc2420_set_txpower(uint8_t power)
946 {
947  GET_LOCK();
948  set_txpower(power);
949  RELEASE_LOCK();
950 }
951 /*---------------------------------------------------------------------------*/
952 int
953 cc2420_get_txpower(void)
954 {
955  int power;
956  GET_LOCK();
957  power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
958  RELEASE_LOCK();
959  return power;
960 }
961 /*---------------------------------------------------------------------------*/
962 int
963 cc2420_rssi(void)
964 {
965  int rssi;
966  int radio_was_off = 0;
967 
968  if(locked) {
969  return 0;
970  }
971 
972  GET_LOCK();
973 
974  if(!receive_on) {
975  radio_was_off = 1;
976  cc2420_on();
977  }
978  wait_for_status(BV(CC2420_RSSI_VALID));
979 
980  rssi = (int)((signed char) getreg(CC2420_RSSI));
981  rssi += RSSI_OFFSET;
982 
983  if(radio_was_off) {
984  cc2420_off();
985  }
986  RELEASE_LOCK();
987  return rssi;
988 }
989 /*---------------------------------------------------------------------------*/
990 static int
991 cc2420_cca(void)
992 {
993  int cca;
994  int radio_was_off = 0;
995 
996  /* If the radio is locked by an underlying thread (because we are
997  being invoked through an interrupt), we preted that the coast is
998  clear (i.e., no packet is currently being transmitted by a
999  neighbor). */
1000  if(locked) {
1001  return 1;
1002  }
1003 
1004  GET_LOCK();
1005  if(!receive_on) {
1006  radio_was_off = 1;
1007  cc2420_on();
1008  }
1009 
1010  /* Make sure that the radio really got turned on. */
1011  if(!receive_on) {
1012  RELEASE_LOCK();
1013  if(radio_was_off) {
1014  cc2420_off();
1015  }
1016  return 1;
1017  }
1018 
1019  wait_for_status(BV(CC2420_RSSI_VALID));
1020 
1021  cca = CC2420_CCA_IS_1;
1022 
1023  if(radio_was_off) {
1024  cc2420_off();
1025  }
1026  RELEASE_LOCK();
1027  return cca;
1028 }
1029 /*---------------------------------------------------------------------------*/
1030 int
1031 cc2420_receiving_packet(void)
1032 {
1033  return CC2420_SFD_IS_1;
1034 }
1035 /*---------------------------------------------------------------------------*/
1036 static int
1037 pending_packet(void)
1038 {
1039  return CC2420_FIFOP_IS_1;
1040 }
1041 /*---------------------------------------------------------------------------*/
1042 static int
1043 get_cca_threshold(void)
1044 {
1045  int value;
1046 
1047  GET_LOCK();
1048  value = (int8_t)(getreg(CC2420_RSSI) >> 8);
1049  RELEASE_LOCK();
1050  return value;
1051 }
1052 /*---------------------------------------------------------------------------*/
1053 void
1054 cc2420_set_cca_threshold(int value)
1055 {
1056  uint16_t shifted = value << 8;
1057  GET_LOCK();
1058  setreg(CC2420_RSSI, shifted);
1059  RELEASE_LOCK();
1060 }
1061 /*---------------------------------------------------------------------------*/
1062 /* Set or unset frame autoack */
1063 static void
1064 set_auto_ack(uint8_t enable)
1065 {
1066  GET_LOCK();
1067 
1068  uint16_t reg = getreg(CC2420_MDMCTRL0);
1069  if(enable) {
1070  reg |= AUTOACK;
1071  } else {
1072  reg &= ~(AUTOACK);
1073  }
1074 
1075  setreg(CC2420_MDMCTRL0, reg);
1076  RELEASE_LOCK();
1077 }
1078 /*---------------------------------------------------------------------------*/
1079 /* Set or unset frame filtering */
1080 static void
1081 set_frame_filtering(uint8_t enable)
1082 {
1083  GET_LOCK();
1084 
1085  /* Turn on/off address decoding. */
1086  uint16_t reg = getreg(CC2420_MDMCTRL0);
1087  if(enable) {
1088  reg |= ADR_DECODE;
1089  } else {
1090  reg &= ~(ADR_DECODE);
1091  }
1092 
1093  setreg(CC2420_MDMCTRL0, reg);
1094  RELEASE_LOCK();
1095 }
1096 /*---------------------------------------------------------------------------*/
1097 /* Enable or disable radio interrupts (both FIFOP and SFD timer capture) */
1098 static void
1099 set_poll_mode(uint8_t enable)
1100 {
1101  GET_LOCK();
1102  poll_mode = enable;
1103  if(enable) {
1104  /* Disable FIFOP interrupt */
1105  CC2420_CLEAR_FIFOP_INT();
1106  CC2420_DISABLE_FIFOP_INT();
1107  } else {
1108  /* Initialize and enable FIFOP interrupt */
1109  CC2420_FIFOP_INT_INIT();
1110  CC2420_ENABLE_FIFOP_INT();
1111  CC2420_CLEAR_FIFOP_INT();
1112  }
1113  RELEASE_LOCK();
1114 }
1115 /*---------------------------------------------------------------------------*/
1116 /* Enable or disable CCA before sending */
1117 static void
1118 set_send_on_cca(uint8_t enable)
1119 {
1120  send_on_cca = enable;
1121 }
1122 /*---------------------------------------------------------------------------*/
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:290
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
CC2420 driver header file
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:116
Header file for the energy estimation mechanism
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
int cc2420_interrupt(void)
Interrupt function, called from the simple-cc2420-arch driver.
Definition: cc2420.c:850
Structure of AES drivers.
Definition: aes-128.h:57
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:283
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:271
void(* encrypt)(uint8_t *plaintext_and_result)
Encrypts.
Definition: aes-128.h:67
The structure of a device driver for a radio in Contiki.
Definition: radio.h:247
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:160
void cc2420_set_txpower(uint8_t power)
Definition: cc2420.c:945
void(* input)(void)
Callback for getting notified of incoming packet.
Definition: mac.h:72
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
int(* off)(void)
Turn the radio off.
Definition: radio.h:277
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:66
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
Definition: clock.c:164
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:214
Basic SPI macros
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
Definition: radio.h:226
static int config(int type, int c, nrf_drv_gpiote_pin_t pin)
Configuration function for the button sensor for all buttons.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:280
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1035
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:296
Header file for the LED HAL.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
int(* on)(void)
Turn the radio on.
Definition: radio.h:274
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void(* set_key)(const uint8_t *key)
Sets the current key.
Definition: aes-128.h:62