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