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