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