Contiki 3.x
cc2530-rf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, George Oikonomou - <oikonomou@users.sourceforge.net>
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  * \file
34  * Implementation of the cc2530 RF driver
35  *
36  * \author
37  * George Oikonomou - <oikonomou@users.sourceforge.net>
38  */
39 #include "contiki.h"
40 #include "dev/radio.h"
41 #include "dev/cc2530-rf.h"
42 #include "cc253x.h"
43 #include "sfr-bits.h"
44 #include "sys/clock.h"
45 #include "sys/rtimer.h"
46 
47 #include "net/packetbuf.h"
48 #include "net/rime/rimestats.h"
49 #include "net/linkaddr.h"
50 #include "net/netstack.h"
51 
52 #include <string.h>
53 /*---------------------------------------------------------------------------*/
54 #define CHECKSUM_LEN 2
55 /*---------------------------------------------------------------------------*/
56 #if CC2530_RF_CONF_LEDS
57 #define CC2530_RF_LEDS CC2530_RF_CONF_LEDS
58 #else
59 #define CC2530_RF_LEDS 0
60 #endif
61 
62 #if CC2530_RF_LEDS
63 #include "dev/leds.h"
64 #define RF_RX_LED_ON() leds_on(LEDS_RED);
65 #define RF_RX_LED_OFF() leds_off(LEDS_RED);
66 #define RF_TX_LED_ON() leds_on(LEDS_GREEN);
67 #define RF_TX_LED_OFF() leds_off(LEDS_GREEN);
68 #else
69 #define RF_RX_LED_ON()
70 #define RF_RX_LED_OFF()
71 #define RF_TX_LED_ON()
72 #define RF_TX_LED_OFF()
73 #endif
74 /*---------------------------------------------------------------------------*/
75 #define DEBUG 0
76 #if DEBUG
77 #include "debug.h"
78 #define PUTSTRING(...) putstring(__VA_ARGS__)
79 #define PUTHEX(...) puthex(__VA_ARGS__)
80 #else
81 #define PUTSTRING(...)
82 #define PUTHEX(...)
83 #endif
84 /*---------------------------------------------------------------------------*/
85 /* Local RF Flags */
86 #define RX_ACTIVE 0x80
87 #define WAS_OFF 0x10
88 #define RF_ON 0x01
89 
90 /* Bit Masks for the last byte in the RX FIFO */
91 #define CRC_BIT_MASK 0x80
92 #define LQI_BIT_MASK 0x7F
93 /* RSSI Offset */
94 #define RSSI_OFFSET 73
95 
96 /* 192 ms, radio off -> on interval */
97 #define ONOFF_TIME RTIMER_ARCH_SECOND / 3125
98 
99 #define CC2530_RF_CHANNEL_SET_ERROR -1
100 
101 #define CC2530_RF_TX_POWER_TXCTRL_MIN_VAL 0x09 /* Value for min TX Power */
102 #define CC2530_RF_TX_POWER_TXCTRL_DEF_VAL 0x69 /* Reset Value */
103 /*---------------------------------------------------------------------------*/
104 #if CC2530_RF_CONF_HEXDUMP
105 #include "dev/io-arch.h"
106 static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /* Snif */
107 #endif
108 /*---------------------------------------------------------------------------*/
109 #ifdef CC2530_RF_CONF_AUTOACK
110 #define CC2530_RF_AUTOACK CC2530_RF_CONF_AUTOACK
111 #else
112 #define CC2530_RF_AUTOACK 1
113 #endif
114 /*---------------------------------------------------------------------------*/
115 static uint8_t CC_AT_DATA rf_flags;
116 
117 static int on(void); /* prepare() needs our prototype */
118 static int off(void); /* transmit() needs our prototype */
119 static int channel_clear(void); /* transmit() needs our prototype */
120 /*---------------------------------------------------------------------------*/
121 /* TX Power dBm lookup table. Values from SmartRF Studio v1.16.0 */
122 typedef struct output_config {
123  radio_value_t power;
124  uint8_t txpower_val;
125 } output_config_t;
126 
127 static const output_config_t output_power[] = {
128  { 5, 0xF5 }, /* 4.5 */
129  { 3, 0xE5 }, /* 2.5 */
130  { 1, 0xD5 },
131  { 0, 0xC5 }, /* -0.5 */
132  { -1, 0xB5 }, /* -1.5 */
133  { -3, 0xA5 },
134  { -4, 0x95 },
135  { -6, 0x85 },
136  { -8, 0x75 },
137  {-10, 0x65 },
138  {-12, 0x55 },
139  {-14, 0x45 },
140  {-16, 0x35 },
141  {-18, 0x25 },
142  {-20, 0x15 },
143  {-22, 0x05 },
144  {-28, 0x05 }, /* TXCTRL must be set to 0x09 */
145 };
146 
147 #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t))
148 
149 /* Max and Min Output Power in dBm */
150 #define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].power)
151 #define OUTPUT_POWER_MAX (output_power[0].power)
152 /*---------------------------------------------------------------------------*/
153 /**
154  * \brief Get the current operating channel
155  * \return Returns a value in [11,26] representing the current channel
156  */
157 static uint8_t
158 get_channel()
159 {
160  return (uint8_t)((FREQCTRL + 44) / 5);
161 }
162 /*---------------------------------------------------------------------------*/
163 /**
164  * \brief Set the current operating channel
165  * \param channel The desired channel as a value in [11,26]
166  * \return Returns a value in [11,26] representing the current channel
167  * or a negative value if \e channel was out of bounds
168  */
169 static int8_t
170 set_channel(uint8_t channel)
171 {
172  PUTSTRING("RF: Set Chan\n");
173 
174  if((channel < CC2530_RF_CHANNEL_MIN) || (channel > CC2530_RF_CHANNEL_MAX)) {
175  return CC2530_RF_CHANNEL_SET_ERROR;
176  }
177 
178  /* Changes to FREQCTRL take effect after the next recalibration */
179  /* Changes to FREQCTRL take effect after the next recalibration */
180  off();
181  FREQCTRL = (CC2530_RF_CHANNEL_MIN
182  + (channel - CC2530_RF_CHANNEL_MIN) * CC2530_RF_CHANNEL_SPACING);
183  on();
184 
185  return (int8_t)channel;
186 }
187 /*---------------------------------------------------------------------------*/
188 static radio_value_t
189 get_pan_id(void)
190 {
191  return (radio_value_t)(PAN_ID1 << 8 | PAN_ID0);
192 }
193 /*---------------------------------------------------------------------------*/
194 static void
195 set_pan_id(uint16_t pan)
196 {
197  PAN_ID0 = pan & 0xFF;
198  PAN_ID1 = pan >> 8;
199 }
200 /*---------------------------------------------------------------------------*/
201 static radio_value_t
202 get_short_addr(void)
203 {
204  return (radio_value_t)(SHORT_ADDR1 << 8 | SHORT_ADDR0);
205 }
206 /*---------------------------------------------------------------------------*/
207 static void
208 set_short_addr(uint16_t addr)
209 {
210  SHORT_ADDR0 = addr & 0xFF;
211  SHORT_ADDR1 = addr >> 8;
212 }
213 /*---------------------------------------------------------------------------*/
214 /**
215  * \brief Reads the current signal strength (RSSI)
216  * \return The current RSSI in dBm
217  *
218  * This function reads the current RSSI on the currently configured
219  * channel.
220  */
221 static radio_value_t
222 get_rssi(void)
223 {
224  int8_t rssi;
225 
226  /* If we are off, turn on first */
227  if(RXENABLE == 0) {
228  rf_flags |= WAS_OFF;
229  on();
230  }
231 
232  /* Wait on RSSI_VALID */
233  while((RSSISTAT & RSSISTAT_RSSI_VALID) == 0);
234 
235  rssi = (radio_value_t)RSSI - RSSI_OFFSET;
236 
237  /* If we were off, turn back off */
238  if((rf_flags & WAS_OFF) == WAS_OFF) {
239  rf_flags &= ~WAS_OFF;
240  off();
241  }
242 
243  return rssi;
244 }
245 /*---------------------------------------------------------------------------*/
246 /* Returns the current CCA threshold in dBm */
247 static radio_value_t
248 get_cca_threshold(void)
249 {
250  return (int8_t)CCACTRL0 - RSSI_OFFSET;
251 }
252 /*---------------------------------------------------------------------------*/
253 /* Sets the CCA threshold in dBm */
254 static void
255 set_cca_threshold(radio_value_t value)
256 {
257  CCACTRL0 = (value + RSSI_OFFSET) & 0xFF;
258 }
259 /*---------------------------------------------------------------------------*/
260 /* Returns the current TX power in dBm */
261 static radio_value_t
262 get_tx_power(void)
263 {
264  int i;
265  uint8_t reg_val = TXPOWER;
266 
267  if(TXCTRL == CC2530_RF_TX_POWER_TXCTRL_MIN_VAL) {
268  return OUTPUT_POWER_MIN;
269  }
270 
271  /*
272  * Find the TXPOWER value in the lookup table
273  * If the value has been written with set_tx_power, we should be able to
274  * find the exact value. However, in case the register has been written in
275  * a different fashion, we return the immediately lower value of the lookup
276  */
277  for(i = 0; i < OUTPUT_CONFIG_COUNT; i++) {
278  if(reg_val >= output_power[i].txpower_val) {
279  return output_power[i].power;
280  }
281  }
282  return OUTPUT_POWER_MIN;
283 }
284 /*---------------------------------------------------------------------------*/
285 /*
286  * Set TX power to 'at least' power dBm
287  * This works with a lookup table. If the value of 'power' does not exist in
288  * the lookup table, TXPOWER will be set to the immediately higher available
289  * value
290  */
291 static void
292 set_tx_power(radio_value_t power)
293 {
294  int i;
295 
296  if(power <= output_power[OUTPUT_CONFIG_COUNT - 1].power) {
297  TXCTRL = CC2530_RF_TX_POWER_TXCTRL_MIN_VAL;
298  TXPOWER = output_power[OUTPUT_CONFIG_COUNT - 1].txpower_val;
299  return;
300  }
301 
302  for(i = OUTPUT_CONFIG_COUNT - 2; i >= 0; --i) {
303  if(power <= output_power[i].power) {
304  /* Perhaps an earlier call set TXCTRL to 0x09. Restore */
305  TXCTRL = CC2530_RF_TX_POWER_TXCTRL_DEF_VAL;
306  TXPOWER = output_power[i].txpower_val;
307  return;
308  }
309  }
310 }
311 /*---------------------------------------------------------------------------*/
312 static void
313 set_frame_filtering(uint8_t enable)
314 {
315  if(enable) {
316  FRMFILT0 |= FRMFILT0_FRAME_FILTER_EN;
317  } else {
318  FRMFILT0 &= ~FRMFILT0_FRAME_FILTER_EN;
319  }
320 }
321 /*---------------------------------------------------------------------------*/
322 static void
323 set_auto_ack(uint8_t enable)
324 {
325  if(enable) {
326  FRMCTRL0 |= FRMCTRL0_AUTOACK;
327  } else {
328  FRMCTRL0 &= ~FRMCTRL0_AUTOACK;
329  }
330 }
331 /*---------------------------------------------------------------------------*/
332 /* Netstack API radio driver functions */
333 /*---------------------------------------------------------------------------*/
334 static int
335 init(void)
336 {
337  PUTSTRING("RF: Init\n");
338 
339  if(rf_flags & RF_ON) {
340  return 0;
341  }
342 
343 #if CC2530_RF_LOW_POWER_RX
344  /* Reduce RX power consumption current to 20mA at the cost of sensitivity */
345  RXCTRL = 0x00;
346  FSCTRL = 0x50;
347 #else
348  RXCTRL = 0x3F;
349  FSCTRL = 0x55;
350 #endif /* CC2530_RF_LOW_POWER_RX */
351 
352  CCACTRL0 = CC2530_RF_CCA_THRES;
353 
354  /*
355  * According to the user guide, these registers must be updated from their
356  * defaults for optimal performance
357  *
358  * Table 23-6, Sec. 23.15.1, p. 259
359  */
360  TXFILTCFG = 0x09; /* TX anti-aliasing filter */
361  AGCCTRL1 = 0x15; /* AGC target value */
362  FSCAL1 = 0x00; /* Reduce the VCO leakage */
363 
364  /* Auto ACKs and CRC calculation, default RX and TX modes with FIFOs */
365  FRMCTRL0 = FRMCTRL0_AUTOCRC;
366 #if CC2530_RF_AUTOACK
367  FRMCTRL0 |= FRMCTRL0_AUTOACK;
368 #endif
369 
370  /* Disable source address matching and autopend */
371  SRCMATCH = 0; /* investigate */
372 
373  /* MAX FIFOP threshold */
374  FIFOPCTRL = CC2530_RF_MAX_PACKET_LEN;
375 
376  TXPOWER = CC2530_RF_TX_POWER;
377 
378  RF_TX_LED_OFF();
379  RF_RX_LED_OFF();
380 
381  rf_flags |= RF_ON;
382 
383  return 1;
384 }
385 /*---------------------------------------------------------------------------*/
386 static int
387 prepare(const void *payload, unsigned short payload_len)
388 {
389  uint8_t i;
390 
391  PUTSTRING("RF: Prepare 0x");
392  PUTHEX(payload_len + CHECKSUM_LEN);
393  PUTSTRING(" bytes\n");
394 
395  /*
396  * When we transmit in very quick bursts, make sure previous transmission
397  * is not still in progress before re-writing to the TX FIFO
398  */
399  while(FSMSTAT1 & FSMSTAT1_TX_ACTIVE);
400 
401  if((rf_flags & RX_ACTIVE) == 0) {
402  on();
403  }
404 
405  CC2530_CSP_ISFLUSHTX();
406 
407  PUTSTRING("RF: data = ");
408  /* Send the phy length byte first */
409  RFD = payload_len + CHECKSUM_LEN; /* Payload plus FCS */
410  for(i = 0; i < payload_len; i++) {
411  RFD = ((unsigned char *)(payload))[i];
412  PUTHEX(((unsigned char *)(payload))[i]);
413  }
414  PUTSTRING("\n");
415 
416  /* Leave space for the FCS */
417  RFD = 0;
418  RFD = 0;
419 
420  return 0;
421 }
422 /*---------------------------------------------------------------------------*/
423 static int
424 transmit(unsigned short transmit_len)
425 {
426  uint8_t counter;
427  int ret = RADIO_TX_ERR;
428  rtimer_clock_t t0;
429  transmit_len; /* hush the warning */
430 
431  if(!(rf_flags & RX_ACTIVE)) {
432  t0 = RTIMER_NOW();
433  on();
434  rf_flags |= WAS_OFF;
435  while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
436  }
437 
438  if(channel_clear() == CC2530_RF_CCA_BUSY) {
439  RIMESTATS_ADD(contentiondrop);
440  return RADIO_TX_COLLISION;
441  }
442 
443  /*
444  * prepare() double checked that TX_ACTIVE is low. If SFD is high we are
445  * receiving. Abort transmission and bail out with RADIO_TX_COLLISION
446  */
447  if(FSMSTAT1 & FSMSTAT1_SFD) {
448  RIMESTATS_ADD(contentiondrop);
449  return RADIO_TX_COLLISION;
450  }
451 
452  /* Start the transmission */
453  RF_TX_LED_ON();
454  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
455  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
456 
457  CC2530_CSP_ISTXON();
458 
459  counter = 0;
460  while(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE) && (counter++ < 3)) {
461  clock_delay_usec(6);
462  }
463 
464  if(!(FSMSTAT1 & FSMSTAT1_TX_ACTIVE)) {
465  PUTSTRING("RF: TX never active.\n");
466  CC2530_CSP_ISFLUSHTX();
467  ret = RADIO_TX_ERR;
468  } else {
469  /* Wait for the transmission to finish */
470  while(FSMSTAT1 & FSMSTAT1_TX_ACTIVE);
471  ret = RADIO_TX_OK;
472  }
473  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
474  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
475 
476  if(rf_flags & WAS_OFF) {
477  off();
478  }
479 
480  RIMESTATS_ADD(lltx);
481 
482  RF_TX_LED_OFF();
483 
484  /* OK, sent. We are now ready to send more */
485  return ret;
486 }
487 /*---------------------------------------------------------------------------*/
488 static int
489 send(void *payload, unsigned short payload_len)
490 {
491  prepare(payload, payload_len);
492  return transmit(payload_len);
493 }
494 /*---------------------------------------------------------------------------*/
495 static int
496 read(void *buf, unsigned short bufsize)
497 {
498  uint8_t i;
499  uint8_t len;
500  uint8_t crc_corr;
501  int8_t rssi;
502 
503  PUTSTRING("RF: Read\n");
504 
505  /* Check the length */
506  len = RFD;
507 
508  /* Check for validity */
509  if(len > CC2530_RF_MAX_PACKET_LEN) {
510  /* Oops, we must be out of sync. */
511  PUTSTRING("RF: bad sync\n");
512 
513  RIMESTATS_ADD(badsynch);
514  CC2530_CSP_ISFLUSHRX();
515  return 0;
516  }
517 
518  if(len <= CC2530_RF_MIN_PACKET_LEN) {
519  PUTSTRING("RF: too short\n");
520 
521  RIMESTATS_ADD(tooshort);
522  CC2530_CSP_ISFLUSHRX();
523  return 0;
524  }
525 
526  if(len - CHECKSUM_LEN > bufsize) {
527  PUTSTRING("RF: too long\n");
528 
529  RIMESTATS_ADD(toolong);
530  CC2530_CSP_ISFLUSHRX();
531  return 0;
532  }
533 
534 #if CC2530_RF_CONF_HEXDUMP
535  /* If we reach here, chances are the FIFO is holding a valid frame */
536  io_arch_writeb(magic[0]);
537  io_arch_writeb(magic[1]);
538  io_arch_writeb(magic[2]);
539  io_arch_writeb(magic[3]);
540  io_arch_writeb(len);
541 #endif
542 
543  RF_RX_LED_ON();
544 
545  PUTSTRING("RF: read (0x");
546  PUTHEX(len);
547  PUTSTRING(" bytes) = ");
548  len -= CHECKSUM_LEN;
549  for(i = 0; i < len; ++i) {
550  ((unsigned char *)(buf))[i] = RFD;
551 #if CC2530_RF_CONF_HEXDUMP
552  io_arch_writeb(((unsigned char *)(buf))[i]);
553 #endif
554  PUTHEX(((unsigned char *)(buf))[i]);
555  }
556  PUTSTRING("\n");
557 
558  /* Read the RSSI and CRC/Corr bytes */
559  rssi = ((int8_t) RFD) - RSSI_OFFSET;
560  crc_corr = RFD;
561 
562 #if CC2530_RF_CONF_HEXDUMP
563  io_arch_writeb(rssi);
564  io_arch_writeb(crc_corr);
565  io_arch_flush();
566 #endif
567 
568  /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
569  if(crc_corr & CRC_BIT_MASK) {
570  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
571  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
572  RIMESTATS_ADD(llrx);
573  } else {
574  RIMESTATS_ADD(badcrc);
575  CC2530_CSP_ISFLUSHRX();
576  RF_RX_LED_OFF();
577  return 0;
578  }
579 
580  /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
581  if((FSMSTAT1 & (FSMSTAT1_FIFO | FSMSTAT1_FIFOP)) == FSMSTAT1_FIFOP) {
582  /*
583  * If we reach here means that there might be more intact packets in the
584  * FIFO despite the overflow. This can happen with bursts of small packets.
585  *
586  * Only flush if the FIFO is actually empty. If not, then next pass we will
587  * pick up one more packet or flush due to an error.
588  */
589  if(!RXFIFOCNT) {
590  CC2530_CSP_ISFLUSHRX();
591  }
592  }
593 
594  RF_RX_LED_OFF();
595 
596  return (len);
597 }
598 /*---------------------------------------------------------------------------*/
599 static int
600 channel_clear(void)
601 {
602  if(FSMSTAT1 & FSMSTAT1_CCA) {
603  return CC2530_RF_CCA_CLEAR;
604  }
605  return CC2530_RF_CCA_BUSY;
606 }
607 /*---------------------------------------------------------------------------*/
608 static int
609 receiving_packet(void)
610 {
611  PUTSTRING("RF: Receiving\n");
612 
613  /*
614  * SFD high while transmitting and receiving.
615  * TX_ACTIVE high only when transmitting
616  *
617  * FSMSTAT1 & (TX_ACTIVE | SFD) == SFD <=> receiving
618  */
619  return (FSMSTAT1 & (FSMSTAT1_TX_ACTIVE | FSMSTAT1_SFD) == FSMSTAT1_SFD);
620 }
621 /*---------------------------------------------------------------------------*/
622 static int
623 pending_packet(void)
624 {
625  return (FSMSTAT1 & FSMSTAT1_FIFOP);
626 }
627 /*---------------------------------------------------------------------------*/
628 static int
629 on(void)
630 {
631  if(!(rf_flags & RX_ACTIVE)) {
632  CC2530_CSP_ISFLUSHRX();
633  CC2530_CSP_ISRXON();
634 
635  rf_flags |= RX_ACTIVE;
636  }
637 
638  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
639  return 1;
640 }
641 /*---------------------------------------------------------------------------*/
642 static int
643 off(void)
644 {
645  CC2530_CSP_ISRFOFF();
646  CC2530_CSP_ISFLUSHRX();
647 
648  rf_flags &= ~RX_ACTIVE;
649 
650  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
651  return 1;
652 }
653 /*---------------------------------------------------------------------------*/
654 static radio_result_t
655 get_value(radio_param_t param, radio_value_t *value)
656 {
657  if(!value) {
658  return RADIO_RESULT_INVALID_VALUE;
659  }
660 
661  switch(param) {
662  case RADIO_PARAM_POWER_MODE:
663  *value = RXENABLE == 0 ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON;
664  return RADIO_RESULT_OK;
665  case RADIO_PARAM_CHANNEL:
666  *value = (radio_value_t)get_channel();
667  return RADIO_RESULT_OK;
668  case RADIO_PARAM_PAN_ID:
669  *value = get_pan_id();
670  return RADIO_RESULT_OK;
671  case RADIO_PARAM_16BIT_ADDR:
672  *value = get_short_addr();
673  return RADIO_RESULT_OK;
674  case RADIO_PARAM_RX_MODE:
675  *value = 0;
676  if(FRMFILT0 & FRMFILT0_FRAME_FILTER_EN) {
678  }
679  if(FRMCTRL0 & FRMCTRL0_AUTOACK) {
680  *value |= RADIO_RX_MODE_AUTOACK;
681  }
682  return RADIO_RESULT_OK;
683  case RADIO_PARAM_TXPOWER:
684  *value = get_tx_power();
685  return RADIO_RESULT_OK;
686  case RADIO_PARAM_CCA_THRESHOLD:
687  *value = get_cca_threshold();
688  return RADIO_RESULT_OK;
689  case RADIO_PARAM_RSSI:
690  *value = get_rssi();
691  return RADIO_RESULT_OK;
692  case RADIO_CONST_CHANNEL_MIN:
693  *value = CC2530_RF_CHANNEL_MIN;
694  return RADIO_RESULT_OK;
695  case RADIO_CONST_CHANNEL_MAX:
696  *value = CC2530_RF_CHANNEL_MAX;
697  return RADIO_RESULT_OK;
698  case RADIO_CONST_TXPOWER_MIN:
699  *value = OUTPUT_POWER_MIN;
700  return RADIO_RESULT_OK;
701  case RADIO_CONST_TXPOWER_MAX:
702  *value = OUTPUT_POWER_MAX;
703  return RADIO_RESULT_OK;
704  default:
705  return RADIO_RESULT_NOT_SUPPORTED;
706  }
707 }
708 /*---------------------------------------------------------------------------*/
709 static radio_result_t
710 set_value(radio_param_t param, radio_value_t value)
711 {
712  switch(param) {
713  case RADIO_PARAM_POWER_MODE:
714  if(value == RADIO_POWER_MODE_ON) {
715  on();
716  return RADIO_RESULT_OK;
717  }
718  if(value == RADIO_POWER_MODE_OFF) {
719  off();
720  return RADIO_RESULT_OK;
721  }
722  return RADIO_RESULT_INVALID_VALUE;
723  case RADIO_PARAM_CHANNEL:
724  if(value < CC2530_RF_CHANNEL_MIN || value > CC2530_RF_CHANNEL_MAX) {
725  return RADIO_RESULT_INVALID_VALUE;
726  }
727  if(set_channel(value) == CC2530_RF_CHANNEL_SET_ERROR) {
728  return RADIO_RESULT_ERROR;
729  }
730  return RADIO_RESULT_OK;
731  case RADIO_PARAM_PAN_ID:
732  set_pan_id(value & 0xffff);
733  return RADIO_RESULT_OK;
734  case RADIO_PARAM_16BIT_ADDR:
735  set_short_addr(value & 0xffff);
736  return RADIO_RESULT_OK;
737  case RADIO_PARAM_RX_MODE:
738  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
739  RADIO_RX_MODE_AUTOACK)) {
740  return RADIO_RESULT_INVALID_VALUE;
741  }
742 
743  set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
744  set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
745 
746  return RADIO_RESULT_OK;
747  case RADIO_PARAM_TXPOWER:
748  if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
749  return RADIO_RESULT_INVALID_VALUE;
750  }
751 
752  set_tx_power(value);
753  return RADIO_RESULT_OK;
754  case RADIO_PARAM_CCA_THRESHOLD:
755  set_cca_threshold(value);
756  return RADIO_RESULT_OK;
757  default:
758  return RADIO_RESULT_NOT_SUPPORTED;
759  }
760 }
761 /*---------------------------------------------------------------------------*/
762 static radio_result_t
763 get_object(radio_param_t param, void *dest, size_t size)
764 {
765  uint8_t *target;
766  int i;
767 
768  if(param == RADIO_PARAM_64BIT_ADDR) {
769  if(size != 8 || !dest) {
770  return RADIO_RESULT_INVALID_VALUE;
771  }
772 
773  target = dest;
774  for(i = 0; i < 8; i++) {
775  target[i] = ((uint8_t *)&EXT_ADDR0)[7 - i] & 0xFF;
776  }
777 
778  return RADIO_RESULT_OK;
779  }
780  return RADIO_RESULT_NOT_SUPPORTED;
781 }
782 /*---------------------------------------------------------------------------*/
783 static radio_result_t
784 set_object(radio_param_t param, const void *src, size_t size)
785 {
786  int i;
787 
788  if(param == RADIO_PARAM_64BIT_ADDR) {
789  if(size != 8 || !src) {
790  return RADIO_RESULT_INVALID_VALUE;
791  }
792 
793  for(i = 0; i < 8; i++) {
794  ((uint8_t *)&EXT_ADDR0)[i] = ((uint8_t *)src)[7 - i];
795  }
796 
797  return RADIO_RESULT_OK;
798  }
799  return RADIO_RESULT_NOT_SUPPORTED;
800 }
801 /*---------------------------------------------------------------------------*/
802 const struct radio_driver cc2530_rf_driver = {
803  init,
804  prepare,
805  transmit,
806  send,
807  read,
811  on,
812  off,
813  get_value,
814  set_value,
815  get_object,
816  set_object
817 };
818 /*---------------------------------------------------------------------------*/
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:193
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
Header file for the radio API
Header file for the Rime buffer (packetbuf) management
The structure of a device driver for a radio in Contiki.
Definition: radio.h:225
Definitions for TI/Chipcon cc2530, cc2531 and cc2533 SFR registers.
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:249
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
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:230
int(* send)(const void *payload, unsigned short payload_len)
Prepare &amp; transmit a packet.
Definition: radio.h:236
Header file with definitions of bit masks for some cc2530 SFRs
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:246
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Definition: radio.h:243
Header file for the real-time timer module.
int(* on)(void)
Turn the radio on.
Definition: radio.h:252
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:258
Platform-specific header file which switches between UART and USB input/output, depending on whether we are building for the cc2531 USB dongle or the SmartRF
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:268
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:233
Implementation of the cc2530 RF driver
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:133
Header file for Rime statistics
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:274
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:261
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:239
int(* off)(void)
Turn the radio off.
Definition: radio.h:255
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Rime address representation