44 #include "cc2420_const.h" 49 enum write_ram_order {
59 #define PRINTF(...) printf(__VA_ARGS__) 61 #define PRINTF(...) do {} while (0) 64 #define DEBUG_LEDS DEBUG 68 #define LEDS_ON(x) leds_on(x) 69 #define LEDS_OFF(x) leds_off(x) 78 struct output_config {
83 static const struct output_config output_power[] = {
93 #define OUTPUT_NUM (sizeof(output_power) / sizeof(struct output_config)) 94 #define OUTPUT_POWER_MAX 0 95 #define OUTPUT_POWER_MIN -25 97 void cc2420_arch_init(
void);
99 int cc2420_authority_level_of_sender;
101 volatile uint8_t cc2420_sfd_counter;
102 volatile uint16_t cc2420_sfd_start_time;
103 volatile uint16_t cc2420_sfd_end_time;
105 static volatile uint16_t last_packet_timestamp;
107 PROCESS(cc2420_process,
"CC2420 driver");
110 #define AUTOACK (1 << 4) 111 #define AUTOCRC (1 << 5) 112 #define ADR_DECODE (1 << 11) 113 #define RXFIFO_PROTECTION (1 << 9) 114 #define CORR_THR(n) (((n) & 0x1f) << 6) 115 #define FIFOP_THR(n) ((n) & 0x7f) 116 #define RXBPF_LOCUR (1 << 13); 119 int cc2420_off(
void);
121 static int cc2420_read(
void *buf,
unsigned short bufsize);
123 static int cc2420_prepare(
const void *data,
unsigned short len);
124 static int cc2420_transmit(
unsigned short len);
125 static int cc2420_send(
const void *data,
unsigned short len);
127 static int cc2420_receiving_packet(
void);
128 static int pending_packet(
void);
129 static int get_cca_threshold(
void);
130 static int cc2420_cca(
void);
131 static uint16_t getreg(
enum cc2420_register regname);
133 static void set_frame_filtering(uint8_t enable);
134 static void set_poll_mode(uint8_t enable);
135 static void set_send_on_cca(uint8_t enable);
136 static void set_auto_ack(uint8_t enable);
138 signed char cc2420_last_rssi;
139 uint8_t cc2420_last_correlation;
141 static uint8_t receive_on;
145 static uint8_t
volatile poll_mode = 0;
147 static uint8_t send_on_cca = WITH_SEND_CCA;
149 static radio_result_t
155 return RADIO_RESULT_INVALID_VALUE;
158 case RADIO_PARAM_POWER_MODE:
159 *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
160 return RADIO_RESULT_OK;
161 case RADIO_PARAM_CHANNEL:
162 *value = cc2420_get_channel();
163 return RADIO_RESULT_OK;
164 case RADIO_PARAM_RX_MODE:
166 if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
169 if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
170 *value |= RADIO_RX_MODE_AUTOACK;
173 *value |= RADIO_RX_MODE_POLL_MODE;
175 return RADIO_RESULT_OK;
176 case RADIO_PARAM_TX_MODE:
181 return RADIO_RESULT_OK;
182 case RADIO_PARAM_TXPOWER:
183 v = cc2420_get_txpower();
184 *value = OUTPUT_POWER_MIN;
186 for(i = 0; i < OUTPUT_NUM; i++) {
187 if(v >= output_power[i].
config) {
188 *value = output_power[i].power;
192 return RADIO_RESULT_OK;
193 case RADIO_PARAM_CCA_THRESHOLD:
194 *value = get_cca_threshold() + RSSI_OFFSET;
195 return RADIO_RESULT_OK;
196 case RADIO_PARAM_RSSI:
198 *value = cc2420_rssi();
199 return RADIO_RESULT_OK;
200 case RADIO_PARAM_LAST_RSSI:
202 *value = cc2420_last_rssi;
203 return RADIO_RESULT_OK;
204 case RADIO_PARAM_LAST_LINK_QUALITY:
206 *value = cc2420_last_correlation;
207 return RADIO_RESULT_OK;
208 case RADIO_CONST_CHANNEL_MIN:
210 return RADIO_RESULT_OK;
211 case RADIO_CONST_CHANNEL_MAX:
213 return RADIO_RESULT_OK;
214 case RADIO_CONST_TXPOWER_MIN:
215 *value = OUTPUT_POWER_MIN;
216 return RADIO_RESULT_OK;
217 case RADIO_CONST_TXPOWER_MAX:
218 *value = OUTPUT_POWER_MAX;
219 return RADIO_RESULT_OK;
221 return RADIO_RESULT_NOT_SUPPORTED;
225 static radio_result_t
231 case RADIO_PARAM_POWER_MODE:
232 if(value == RADIO_POWER_MODE_ON) {
234 return RADIO_RESULT_OK;
236 if(value == RADIO_POWER_MODE_OFF) {
238 return RADIO_RESULT_OK;
240 return RADIO_RESULT_INVALID_VALUE;
241 case RADIO_PARAM_CHANNEL:
242 if(value < 11 || value > 26) {
243 return RADIO_RESULT_INVALID_VALUE;
245 cc2420_set_channel(value);
246 return RADIO_RESULT_OK;
247 case RADIO_PARAM_RX_MODE:
249 RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
250 return RADIO_RESULT_INVALID_VALUE;
253 set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
254 set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
255 return RADIO_RESULT_OK;
256 case RADIO_PARAM_TX_MODE:
258 return RADIO_RESULT_INVALID_VALUE;
261 return RADIO_RESULT_OK;
262 case RADIO_PARAM_TXPOWER:
263 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
264 return RADIO_RESULT_INVALID_VALUE;
267 for(i = 1; i < OUTPUT_NUM; i++) {
268 if(value > output_power[i].power) {
273 return RADIO_RESULT_OK;
274 case RADIO_PARAM_CCA_THRESHOLD:
275 cc2420_set_cca_threshold(value - RSSI_OFFSET);
276 return RADIO_RESULT_OK;
278 return RADIO_RESULT_NOT_SUPPORTED;
282 static radio_result_t
283 get_object(radio_param_t param,
void *dest,
size_t size)
285 if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
286 #if CC2420_CONF_SFD_TIMESTAMPS 287 if(size !=
sizeof(rtimer_clock_t) || !dest) {
288 return RADIO_RESULT_INVALID_VALUE;
290 *(rtimer_clock_t*)dest = cc2420_sfd_start_time;
291 return RADIO_RESULT_OK;
293 return RADIO_RESULT_NOT_SUPPORTED;
296 return RADIO_RESULT_NOT_SUPPORTED;
299 static radio_result_t
300 set_object(radio_param_t param,
const void *src,
size_t size)
302 return RADIO_RESULT_NOT_SUPPORTED;
313 cc2420_receiving_packet,
326 strobe(
enum cc2420_register regname)
330 CC2420_SPI_DISABLE();
335 getreg(
enum cc2420_register regname)
340 SPI_WRITE(regname | 0x40);
341 value = (uint8_t)SPI_RXBUF;
344 value = SPI_RXBUF << 8;
348 CC2420_SPI_DISABLE();
359 setreg(
enum cc2420_register regname, uint16_t value)
362 SPI_WRITE_FAST(regname);
363 SPI_WRITE_FAST((uint8_t) (value >> 8));
364 SPI_WRITE_FAST((uint8_t) (value & 0xff));
365 SPI_WAITFORTx_ENDED();
367 CC2420_SPI_DISABLE();
371 read_ram(uint8_t *buffer, uint16_t adr, uint16_t count)
376 SPI_WRITE(0x80 | ((adr) & 0x7f));
377 SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20);
379 for(i = 0; i < count; i++) {
380 SPI_READ(((uint8_t*) buffer)[i]);
382 CC2420_SPI_DISABLE();
387 write_ram(
const uint8_t *buffer,
390 enum write_ram_order order)
395 SPI_WRITE_FAST(0x80 | (adr & 0x7f));
396 SPI_WRITE_FAST((adr >> 1) & 0xc0);
397 if(order == WRITE_RAM_IN_ORDER) {
398 for(i = 0; i < count; i++) {
399 SPI_WRITE_FAST((buffer)[i]);
402 for(i = count; i > 0; i--) {
403 SPI_WRITE_FAST((buffer)[i - 1]);
406 SPI_WAITFORTx_ENDED();
407 CC2420_SPI_DISABLE();
411 write_fifo_buf(
const uint8_t *buffer, uint16_t count)
416 SPI_WRITE_FAST(CC2420_TXFIFO);
417 for(i = 0; i < count; i++) {
418 SPI_WRITE_FAST((buffer)[i]);
420 SPI_WAITFORTx_ENDED();
421 CC2420_SPI_DISABLE();
431 SPI_WRITE(CC2420_SNOP);
433 CC2420_SPI_DISABLE();
439 getrxdata(uint8_t *buffer,
int count)
444 SPI_WRITE(CC2420_RXFIFO | 0x40);
446 for(i = 0; i < count; i++) {
450 CC2420_SPI_DISABLE();
458 getrxdata(&dummy, 1);
459 strobe(CC2420_SFLUSHRX);
460 strobe(CC2420_SFLUSHRX);
467 wait_for_status(uint8_t status_bit)
471 while(!(get_status() & status_bit)
472 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
476 wait_for_transmission(
void)
480 while((get_status() & BV(CC2420_TX_ACTIVE))
481 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
488 CC2420_ENABLE_FIFOP_INT();
491 strobe(CC2420_SRXON);
493 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
504 wait_for_transmission();
506 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
507 strobe(CC2420_SRFOFF);
509 CC2420_DISABLE_FIFOP_INT();
512 if(!CC2420_FIFOP_IS_1) {
517 static uint8_t locked, lock_on, lock_off;
518 #define GET_LOCK() locked++ 519 static void RELEASE_LOCK(
void) {
537 setreg(CC2420_SECCTRL0, 0);
538 setreg(CC2420_SECCTRL1, 0);
542 set_key(
const uint8_t *key)
546 write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE);
552 encrypt(uint8_t *plaintext_and_result)
556 write_ram(plaintext_and_result,
562 while(get_status() & BV(CC2420_ENC_BUSY));
564 read_ram(plaintext_and_result, CC2420RAM_SABUF, 16);
575 set_txpower(uint8_t power)
579 reg = getreg(CC2420_TXCTRL);
580 reg = (reg & 0xffe0) | (power & 0x1f);
581 setreg(CC2420_TXCTRL, reg);
591 CC2420_DISABLE_FIFOP_INT();
592 CC2420_FIFOP_INT_INIT();
601 SET_RESET_INACTIVE();
606 strobe(CC2420_SXOSCON);
608 wait_for_status(BV(CC2420_XOSC16M_STABLE));
611 set_auto_ack(CC2420_CONF_AUTOACK);
612 set_frame_filtering(CC2420_CONF_AUTOACK);
617 reg = getreg(CC2420_MDMCTRL0);
619 setreg(CC2420_MDMCTRL0, reg);
630 setreg(CC2420_MDMCTRL1, CORR_THR(20));
631 reg = getreg(CC2420_RXCTRL1);
633 setreg(CC2420_RXCTRL1, reg);
636 setreg(CC2420_IOCFG0, FIFOP_THR(127));
640 cc2420_set_pan_addr(0xffff, 0x0000, NULL);
642 cc2420_set_cca_threshold(CC2420_CONF_CCA_THRESH);
653 cc2420_transmit(
unsigned short payload_len)
666 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT 667 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!! 669 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT 673 strobe(CC2420_SRXON);
674 wait_for_status(BV(CC2420_RSSI_VALID));
675 strobe(CC2420_STXONCCA);
677 strobe(CC2420_STXON);
679 for(i = LOOP_20_SYMBOLS; i > 0; i--) {
680 if(CC2420_SFD_IS_1) {
681 if(!(get_status() & BV(CC2420_TX_ACTIVE))) {
686 return RADIO_TX_COLLISION;
689 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
691 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
694 wait_for_transmission();
696 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
698 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
712 PRINTF(
"cc2420: do_send() transmission never started\n");
715 return RADIO_TX_COLLISION;
719 cc2420_prepare(
const void *payload,
unsigned short payload_len)
725 PRINTF(
"cc2420: sending %d bytes\n", payload_len);
731 strobe(CC2420_SFLUSHTX);
733 total_len = payload_len + CHECKSUM_LEN;
734 write_fifo_buf(&total_len, 1);
735 write_fifo_buf(payload, payload_len);
742 cc2420_send(
const void *payload,
unsigned short payload_len)
744 cc2420_prepare(payload, payload_len);
745 return cc2420_transmit(payload_len);
752 if(receive_on == 0) {
769 if(get_status() & BV(CC2420_TX_ACTIVE)) {
796 cc2420_get_channel(
void)
802 cc2420_set_channel(
int c)
813 f = 5 * (c - 11) + 357 + 0x4000;
816 wait_for_transmission();
818 setreg(CC2420_FSCTRL, f);
823 strobe(CC2420_SRXON);
831 cc2420_set_pan_addr(
unsigned pan,
833 const uint8_t *ieee_addr)
837 write_ram((uint8_t *) &pan, CC2420RAM_PANID, 2, WRITE_RAM_IN_ORDER);
838 write_ram((uint8_t *) &addr, CC2420RAM_SHORTADDR, 2, WRITE_RAM_IN_ORDER);
840 if(ieee_addr != NULL) {
841 write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE);
852 CC2420_CLEAR_FIFOP_INT();
855 last_packet_timestamp = cc2420_sfd_start_time;
864 PRINTF(
"cc2420_process: started\n");
869 PRINTF(
"cc2420_process: calling receiver callback\n");
872 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
877 NETSTACK_MAC.
input();
884 cc2420_read(
void *buf,
unsigned short bufsize)
886 uint8_t footer[FOOTER_LEN];
889 if(!CC2420_FIFOP_IS_1) {
897 if(len > CC2420_MAX_PACKET_LEN) {
899 }
else if(len <= FOOTER_LEN) {
901 }
else if(len - FOOTER_LEN > bufsize) {
904 getrxdata((uint8_t *) buf, len - FOOTER_LEN);
905 getrxdata(footer, FOOTER_LEN);
907 if(footer[1] & FOOTER1_CRC_OK) {
908 cc2420_last_rssi = footer[0] + RSSI_OFFSET;
909 cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
914 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
915 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
922 if(CC2420_FIFOP_IS_1) {
923 if(!CC2420_FIFO_IS_1) {
936 return len - FOOTER_LEN;
953 cc2420_get_txpower(
void)
957 power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
966 int radio_was_off = 0;
978 wait_for_status(BV(CC2420_RSSI_VALID));
980 rssi = (int)((
signed char) getreg(CC2420_RSSI));
994 int radio_was_off = 0;
1019 wait_for_status(BV(CC2420_RSSI_VALID));
1021 cca = CC2420_CCA_IS_1;
1031 cc2420_receiving_packet(
void)
1033 return CC2420_SFD_IS_1;
1037 pending_packet(
void)
1039 return CC2420_FIFOP_IS_1;
1043 get_cca_threshold(
void)
1048 value = (int8_t)(getreg(CC2420_RSSI) >> 8);
1054 cc2420_set_cca_threshold(
int value)
1056 uint16_t shifted = value << 8;
1058 setreg(CC2420_RSSI, shifted);
1064 set_auto_ack(uint8_t enable)
1068 uint16_t reg = getreg(CC2420_MDMCTRL0);
1075 setreg(CC2420_MDMCTRL0, reg);
1081 set_frame_filtering(uint8_t enable)
1086 uint16_t reg = getreg(CC2420_MDMCTRL0);
1090 reg &= ~(ADR_DECODE);
1093 setreg(CC2420_MDMCTRL0, reg);
1099 set_poll_mode(uint8_t enable)
1105 CC2420_CLEAR_FIFOP_INT();
1106 CC2420_DISABLE_FIFOP_INT();
1109 CC2420_FIFOP_INT_INIT();
1110 CC2420_ENABLE_FIFOP_INT();
1111 CC2420_CLEAR_FIFOP_INT();
1118 set_send_on_cca(uint8_t enable)
1120 send_on_cca = enable;
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
CC2420 driver header file
#define PROCESS(name, strname)
Declare a process.
void packetbuf_clear(void)
Clear and reset the packetbuf.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Header file for the energy estimation mechanism
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
int cc2420_interrupt(void)
Interrupt function, called from the simple-cc2420-arch driver.
Structure of AES drivers.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
void(* encrypt)(uint8_t *plaintext_and_result)
Encrypts.
The structure of a device driver for a radio in Contiki.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
#define RTIMER_NOW()
Get the current clock time.
void cc2420_set_txpower(uint8_t power)
void(* input)(void)
Callback for getting notified of incoming packet.
void process_poll(struct process *p)
Request a process to be polled.
int(* off)(void)
Turn the radio off.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
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.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Header file for the LED HAL.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
int(* on)(void)
Turn the radio on.
void process_start(struct process *p, process_data_t data)
Start a process.
void(* set_key)(const uint8_t *key)
Sets the current key.