From 5112082a4828d472c48653859bc61e8d0ba74ca7 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 28 Mar 2014 19:51:32 +0100 Subject: [PATCH 01/30] Extended radio API definitions with support for setting channel, pan id, etc. --- core/dev/radio.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/core/dev/radio.h b/core/dev/radio.h index 69eee756e..eed4f0929 100644 --- a/core/dev/radio.h +++ b/core/dev/radio.h @@ -54,13 +54,58 @@ #ifndef RADIO_H_ #define RADIO_H_ +#include + +typedef int radio_value_t; +typedef unsigned radio_param_t; + +enum { + RADIO_PARAM_POWER_MODE, + RADIO_PARAM_CHANNEL, + RADIO_PARAM_PAN_ID, + RADIO_PARAM_16BIT_ADDR, + /** Address handler take care of address filtering and sending autoack */ + RADIO_PARAM_ADDRESS_HANDLER, + /** Transmission power in dBm */ + RADIO_PARAM_TXPOWER, + /** Received signal strength in dBm */ + RADIO_PARAM_RSSI, + + /** 64 bit addresses need to be used with radio.get_object()/set_object() */ + RADIO_PARAM_64BIT_ADDR, + + /** Constants (read only) */ + RADIO_CONST_CHANNEL_MIN, + RADIO_CONST_CHANNEL_MAX, + RADIO_CONST_TXPOWER_MIN, + RADIO_CONST_TXPOWER_MAX +}; + +/* Radio power modes */ +enum { + RADIO_POWER_MODE_OFF, + RADIO_POWER_MODE_ON +}; + +/* Bit flags for the address handler */ +#define RADIO_ADDRESS_HANDLER_FILTER 1 +#define RADIO_ADDRESS_HANDLER_AUTOACK 2 + +/* Radio return values when setting or getting radio parameters. */ +typedef enum { + RADIO_RESULT_OK, + RADIO_RESULT_NOT_SUPPORTED, + RADIO_RESULT_INVALID_VALUE, + RADIO_RESULT_ERROR +} radio_result_t; + /** * The structure of a device driver for a radio in Contiki. */ struct radio_driver { int (* init)(void); - + /** Prepare the radio with a packet to be sent. */ int (* prepare)(const void *payload, unsigned short payload_len); @@ -88,6 +133,22 @@ struct radio_driver { /** Turn the radio off. */ int (* off)(void); + + /** Get a radio parameter */ + radio_result_t (* get_value)(radio_param_t param, radio_value_t *value); + + /** Set a radio parameter */ + radio_result_t (* set_value)(radio_param_t param, radio_value_t value); + + /** Get a radio object (for example a 64 bit address) */ + radio_result_t (* get_object)(radio_param_t param, void *dest, size_t size); + + /** Set a radio object (for example a 64 bit address). The data + is copied and the object memory will not be accessed after the call. + */ + radio_result_t (* set_object)(radio_param_t param, const void *src, + size_t size); + }; /* Generic radio return values. */ From fa908dcaffdcea62a933f01562bf8cd2e7313e17 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:11:03 +0200 Subject: [PATCH 02/30] Added extended radio API implementation for STM32W --- cpu/stm32w108/dev/stm32w-radio.c | 126 +++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/cpu/stm32w108/dev/stm32w-radio.c b/cpu/stm32w108/dev/stm32w-radio.c index 3e2d3c975..aaee47ce4 100644 --- a/cpu/stm32w108/dev/stm32w-radio.c +++ b/cpu/stm32w108/dev/stm32w-radio.c @@ -264,6 +264,128 @@ static int stm32w_radio_off(void); static int add_to_rxbuf(uint8_t * src); static int read_from_rxbuf(void *dest, unsigned short len); + +/*--------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + switch(param) { + case RADIO_PARAM_POWER_MODE: + *value = onoroff == ON ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = ST_RadioGetChannel(); + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + *value = ST_RadioGetPanId(); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + *value = ST_RadioGetNodeId(); + return RADIO_RESULT_OK; + case RADIO_PARAM_ADDRESS_HANDLER: + *value = 0; + if(ST_RadioAddressFilteringEnabled()) { + *value |= RADIO_ADDRESS_HANDLER_FILTER; + } + if(ST_RadioAutoAckEnabled()) { + *value |= RADIO_ADDRESS_HANDLER_AUTOACK; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + *value = ST_RadioGetPower(); + return RADIO_RESULT_OK; + case RADIO_PARAM_RSSI: + *value = ST_RadioEnergyDetection(); + return RADIO_RESULT_OK; + + case RADIO_CONST_CHANNEL_MIN: + *value = 11; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = 26; + return RADIO_RESULT_OK; + + case RADIO_CONST_TXPOWER_MIN: + *value = MIN_RADIO_POWER; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = MAX_RADIO_POWER; + return RADIO_RESULT_OK; + + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*--------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + stm32w_radio_on(); + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + stm32w_radio_off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < 11 || value > 26) { + return RADIO_RESULT_INVALID_VALUE; + } + if(ST_RadioSetChannel(value) != ST_SUCCESS) { + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + ST_RadioSetPanId(value & 0xffff); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + ST_RadioSetNodeId(value & 0xffff); + return RADIO_RESULT_OK; + case RADIO_PARAM_ADDRESS_HANDLER: + ST_RadioEnableAddressFiltering((value & RADIO_ADDRESS_HANDLER_FILTER) != 0); + ST_RadioEnableAutoAck((value & RADIO_ADDRESS_HANDLER_AUTOACK) != 0); + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) { + return RADIO_RESULT_INVALID_VALUE; + } + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*--------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + uint8_t *eui64; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size < 8 || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + eui64 = ST_RadioGetEui64(); + if(!eui64) { + return RADIO_RESULT_ERROR; + } + memcpy(dest, eui64, 8); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*--------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} /*--------------------------------------------------------------------------*/ const struct radio_driver stm32w_radio_driver = { stm32w_radio_init, @@ -276,6 +398,10 @@ const struct radio_driver stm32w_radio_driver = { stm32w_radio_pending_packet, stm32w_radio_on, stm32w_radio_off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ static int From 087416572274520ce4d871be6e24df8ad0afaeeb Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 15:22:17 +0200 Subject: [PATCH 03/30] Added stub for extended radio API for CC2420 --- dev/cc2420/cc2420.c | 72 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index f3f1cc7cf..9646529e0 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -148,6 +148,70 @@ static int cc2420_cca(void); signed char cc2420_last_rssi; uint8_t cc2420_last_correlation; +static uint8_t receive_on; +static int channel; + +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + switch(param) { + case RADIO_PARAM_POWER_MODE: + *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = cc2420_get_channel(); + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MIN: + *value = 11; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = 26; + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} + +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + cc2420_on(); + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + cc2420_off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < 11 || value > 26) { + return RADIO_RESULT_INVALID_VALUE; + } + cc2420_set_channel(value); + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} + +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} + +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} + const struct radio_driver cc2420_driver = { cc2420_init, @@ -162,12 +226,12 @@ const struct radio_driver cc2420_driver = pending_packet, cc2420_on, cc2420_off, + get_value, + set_value, + get_object, + set_object }; -static uint8_t receive_on; - -static int channel; - /*---------------------------------------------------------------------------*/ static void From 9d01fbf7359990549d719569c572232a5cf62c7c Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 15:42:35 +0200 Subject: [PATCH 04/30] Added stub for extended radio API for CC2520 --- dev/cc2520/cc2520.c | 72 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/dev/cc2520/cc2520.c b/dev/cc2520/cc2520.c index 561236b08..249bc6ad6 100644 --- a/dev/cc2520/cc2520.c +++ b/dev/cc2520/cc2520.c @@ -115,6 +115,70 @@ static int cc2520_cca(void); signed char cc2520_last_rssi; uint8_t cc2520_last_correlation; +static uint8_t receive_on; +static int channel; + +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + switch(param) { + case RADIO_PARAM_POWER_MODE: + *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = cc2520_get_channel(); + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MIN: + *value = 11; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = 26; + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} + +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + cc2520_on(); + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + cc2520_off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < 11 || value > 26) { + return RADIO_RESULT_INVALID_VALUE; + } + cc2520_set_channel(value); + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} + +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} + +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} + const struct radio_driver cc2520_driver = { cc2520_init, @@ -129,12 +193,12 @@ const struct radio_driver cc2520_driver = pending_packet, cc2520_on, cc2520_off, + get_value, + set_value, + get_object, + set_object }; -static uint8_t receive_on; - -static int channel; - /*---------------------------------------------------------------------------*/ static void From 5f265ced2fd1de6e08e764b0d80979f1ca847843 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:14:50 +0200 Subject: [PATCH 05/30] Added stub for extended radio API for nullradio --- core/dev/nullradio.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/core/dev/nullradio.c b/core/dev/nullradio.c index c2b978f2b..7f17d5638 100644 --- a/core/dev/nullradio.c +++ b/core/dev/nullradio.c @@ -28,7 +28,7 @@ send(const void *payload, unsigned short payload_len) } /*---------------------------------------------------------------------------*/ static int -read(void *buf, unsigned short buf_len) +radio_read(void *buf, unsigned short buf_len) { return 0; } @@ -63,17 +63,45 @@ off(void) return 0; } /*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver nullradio_driver = { init, prepare, transmit, send, - read, + radio_read, channel_clear, receiving_packet, pending_packet, on, off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ From cb3e053232612bee216381587f731581bafdc363 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:22:33 +0200 Subject: [PATCH 06/30] Added stub for extended radio API for rf230 --- cpu/avr/radio/rf230bb/rf230bb.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c index fa9ed2e99..e3ed931f1 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.c +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -252,6 +252,31 @@ static int rf230_cca(void); uint8_t rf230_last_correlation,rf230_last_rssi,rf230_smallest_rssi; +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver rf230_driver = { rf230_init, @@ -263,7 +288,11 @@ const struct radio_driver rf230_driver = rf230_receiving_packet, rf230_pending_packet, rf230_on, - rf230_off + rf230_off, + get_value, + set_value, + get_object, + set_object }; uint8_t RF230_receive_on; From 1fdb04e10cb6ec58c97878b01b8c68d5e1729d0a Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:22:53 +0200 Subject: [PATCH 07/30] Added stub for extended radio API for cc2430 --- cpu/cc2430/dev/cc2430_rf.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cpu/cc2430/dev/cc2430_rf.c b/cpu/cc2430/dev/cc2430_rf.c index ac897c28c..7738cb34f 100644 --- a/cpu/cc2430/dev/cc2430_rf.c +++ b/cpu/cc2430/dev/cc2430_rf.c @@ -686,6 +686,30 @@ off(void) return 1; } /*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver cc2430_rf_driver = { init, prepare, @@ -697,6 +721,10 @@ const struct radio_driver cc2430_rf_driver = { pending_packet, on, off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ #if !NETSTACK_CONF_SHORTCUTS From a98e153e2330639d4d911aa6a125c83d0569e614 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:23:06 +0200 Subject: [PATCH 08/30] Added stub for extended radio API for cc2538 --- cpu/cc2538/dev/cc2538-rf.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index a42dd56a4..735464708 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -638,6 +638,30 @@ pending_packet(void) return (REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP); } /*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver cc2538_rf_driver = { init, prepare, @@ -649,6 +673,10 @@ const struct radio_driver cc2538_rf_driver = { pending_packet, on, off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ /** From 14ffa35b3f67be6e7cd78b6918d86eba6c4a3ece Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:23:17 +0200 Subject: [PATCH 09/30] Added stub for extended radio API for cc253x --- cpu/cc253x/dev/cc2530-rf.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cpu/cc253x/dev/cc2530-rf.c b/cpu/cc253x/dev/cc2530-rf.c index d9af05e1a..fe52d79c3 100644 --- a/cpu/cc253x/dev/cc2530-rf.c +++ b/cpu/cc253x/dev/cc2530-rf.c @@ -483,6 +483,30 @@ off(void) return 1; } /*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver cc2530_rf_driver = { init, prepare, @@ -494,5 +518,9 @@ const struct radio_driver cc2530_rf_driver = { pending_packet, on, off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ From 2dc4d060780a9ec610fb2c8e4b3dea4a87c988d7 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:23:35 +0200 Subject: [PATCH 10/30] Added stub for extended radio API for mc1322x --- cpu/mc1322x/contiki-maca.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cpu/mc1322x/contiki-maca.c b/cpu/mc1322x/contiki-maca.c index 7b05b7c1b..916ac8a22 100644 --- a/cpu/mc1322x/contiki-maca.c +++ b/cpu/mc1322x/contiki-maca.c @@ -79,6 +79,31 @@ int contiki_maca_channel_clear(void); int contiki_maca_receiving_packet(void); int contiki_maca_pending_packet(void); +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver contiki_maca_driver = { .init = contiki_maca_init, @@ -91,6 +116,10 @@ const struct radio_driver contiki_maca_driver = .channel_clear = contiki_maca_channel_clear, .on = contiki_maca_on_request, .off = contiki_maca_off_request, + .get_value = get_value, + .set_value = set_value, + .get_object = get_object, + .set_object = set_object }; static volatile uint8_t contiki_maca_request_on = 0; From 441beb8f74599d0173c0e2c45df5fc2b069334d6 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:23:45 +0200 Subject: [PATCH 11/30] Added stub for extended radio API for rl78 --- cpu/rl78/adf7023/adf7023-contiki.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cpu/rl78/adf7023/adf7023-contiki.c b/cpu/rl78/adf7023/adf7023-contiki.c index cf9b7d068..7fed45292 100644 --- a/cpu/rl78/adf7023/adf7023-contiki.c +++ b/cpu/rl78/adf7023/adf7023-contiki.c @@ -45,6 +45,31 @@ static unsigned char tx_buf[ADF7023_MAX_PACKET_SIZE]; static unsigned char rx_buf[ADF7023_MAX_PACKET_SIZE]; +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver adf7023_driver = { .init = adf7023_init, @@ -76,6 +101,11 @@ const struct radio_driver adf7023_driver = { /** Turn the radio off. */ .off = adf7023_off, + + .get_value = get_value, + .set_value = set_value, + .get_object = get_object, + .set_object = set_object }; int From b8a23564a3301e035f5519aa1ecbe9eeecee3613 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:23:52 +0200 Subject: [PATCH 12/30] Added stub for extended radio API for Cooja --- platform/cooja/dev/cooja-radio.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/platform/cooja/dev/cooja-radio.c b/platform/cooja/dev/cooja-radio.c index 4c5c53593..9a969016d 100644 --- a/platform/cooja/dev/cooja-radio.c +++ b/platform/cooja/dev/cooja-radio.c @@ -272,6 +272,30 @@ init(void) return 1; } /*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ const struct radio_driver cooja_radio_driver = { init, @@ -284,6 +308,10 @@ const struct radio_driver cooja_radio_driver = pending_packet, radio_on, radio_off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ SIM_INTERFACE(radio_interface, From fc6814a10467973b67d0f850d23e86b6bdf655b4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 1 Apr 2014 16:24:06 +0200 Subject: [PATCH 13/30] Added stub for extended radio API for seedeye --- platform/seedeye/dev/mrf24j40/mrf24j40.c | 31 +++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/platform/seedeye/dev/mrf24j40/mrf24j40.c b/platform/seedeye/dev/mrf24j40/mrf24j40.c index 3c8ad3f29..368d5e4d3 100644 --- a/platform/seedeye/dev/mrf24j40/mrf24j40.c +++ b/platform/seedeye/dev/mrf24j40/mrf24j40.c @@ -927,6 +927,31 @@ PROCESS_THREAD(mrf24j40_process, ev, data) PROCESS_END(); } +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + return RADIO_RESULT_NOT_SUPPORTED; +} + /*---------------------------------------------------------------------------*/ const struct radio_driver mrf24j40_driver = { mrf24j40_init, @@ -938,7 +963,11 @@ const struct radio_driver mrf24j40_driver = { mrf24j40_receiving_packet, mrf24j40_pending_packet, mrf24j40_on, - mrf24j40_off + mrf24j40_off, + get_value, + set_value, + get_object, + set_object }; /*---------------------------------------------------------------------------*/ From 2284ef5ef2168181044c90bac452bd4f4f094dc1 Mon Sep 17 00:00:00 2001 From: Nicolas Tsiftes Date: Mon, 7 Apr 2014 15:31:50 +0200 Subject: [PATCH 14/30] Enhanced the documentation. --- core/dev/radio.h | 143 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 22 deletions(-) diff --git a/core/dev/radio.h b/core/dev/radio.h index eed4f0929..05b87f225 100644 --- a/core/dev/radio.h +++ b/core/dev/radio.h @@ -49,6 +49,9 @@ * Header file for the radio API * \author * Adam Dunkels + * Joakim Eriksson + * Niclas Finne + * Nicolas Tsiftes */ #ifndef RADIO_H_ @@ -56,28 +59,106 @@ #include +/** + * Each radio has a set of parameters that designate the current + * configuration and state of the radio. Parameters can either have + * values of type radio_value_t, or, when this type is insufficient, a + * generic object that is specified by a memory pointer and the size + * of the object. + * + * The radio_value_t type is set to an integer type that can hold most + * values used to configure the radio, and is therefore the most + * common type used for a parameter. Certain parameters require + * objects of a considerably larger size than radio_value_t, however, + * and in these cases the documentation below for the parameter will + * indicate this. + * + * All radio parameters that can vary during runtime are prefixed by + * "RADIO_PARAM", whereas those "parameters" that are guaranteed to + * remain immutable are prefixed by "RADIO_CONST". Each mutable + * parameter has a set of valid parameter values. When attempting to + * set a parameter to an invalid value, the radio will return + * RADIO_RESULT_INVALID_VALUE. + * + * Some radios support only a subset of the defined radio parameters. + * When trying to set or get such an unsupported parameter, the radio + * will return RADIO_RESULT_NOT_SUPPORTED. + */ + typedef int radio_value_t; typedef unsigned radio_param_t; enum { + + /* Radio power mode determines if the radio is on + (RADIO_POWER_MODE_ON) or off (RADIO_POWER_MODE_OFF). */ RADIO_PARAM_POWER_MODE, + + /* + * Channel used for radio communication. The channel depends on the + * communication standard used by the radio. The values can range + * from RADIO_CONST_CHANNEL_MIN to RADIO_CONST_CHANNEL_MAX. + */ RADIO_PARAM_CHANNEL, + + /* Personal area network identifier, which is used by the address filter. */ RADIO_PARAM_PAN_ID, + + /* Short address (16 bits) for the radio, which is used by the address + filter. */ RADIO_PARAM_16BIT_ADDR, - /** Address handler take care of address filtering and sending autoack */ + + /* Address handler take care of address filtering and sending auto-ACK. + (See below for more information.) */ RADIO_PARAM_ADDRESS_HANDLER, - /** Transmission power in dBm */ + + /* + * Transmission power in dBm. The values can range from + * RADIO_CONST_TXPOWER_MIN to RADIO_CONST_TXPOWER_MAX. + * + * Some radios restrict the available values to a subset of this + * range. If an unavailable TXPOWER value is requested to be set, + * the radio may select another TXPOWER close to the requested + * one. When getting the value of this parameter, the actual value + * used by the radio will be returned. + */ RADIO_PARAM_TXPOWER, - /** Received signal strength in dBm */ + + /* + * Clear channel assessment threshold in dBm. This threshold + * determines the minimum RSSI level at which the radio will assume + * that there is a packet in the air. + * + * The CCA threshold must be set to a level above the noise floor of + * the deployment. Otherwise mechanisms such as send-on-CCA and + * low-power-listening duty cycling protocols may not work + * correctly. Hence, the default value of the system may not be + * optimal for any given deployment. + */ + RADIO_PARAM_CCA_THRESHOLD, + + /* Received signal strength indicator in dBm. */ RADIO_PARAM_RSSI, - /** 64 bit addresses need to be used with radio.get_object()/set_object() */ + /* + * Long (64 bits) address for the radio, which is used by the address filter. + * The address is specified in network byte order. + * + * Because this parameter value is larger than what fits in radio_value_t, + * it needs to be used with radio.get_object()/set_object(). + */ RADIO_PARAM_64BIT_ADDR, - /** Constants (read only) */ + /* Constants (read only) */ + + /* The lowest radio channel. */ RADIO_CONST_CHANNEL_MIN, + /* The highest radio channel. */ RADIO_CONST_CHANNEL_MAX, + + /* The minimum transmission power in dBm. */ RADIO_CONST_TXPOWER_MIN, + /* The maximum transmission power in dBm. */ RADIO_CONST_TXPOWER_MAX }; @@ -87,9 +168,22 @@ enum { RADIO_POWER_MODE_ON }; -/* Bit flags for the address handler */ -#define RADIO_ADDRESS_HANDLER_FILTER 1 -#define RADIO_ADDRESS_HANDLER_AUTOACK 2 +/** + * The address handler is an abstraction responsible for address + * filtering and automatic transmission of acknowledgements in the + * radio (if such operations are supported by the radio). + * + * There are different options that can be used like address filter + * on/off, autoack on/off. A single parameter is used to set them + * simultaneous as an atomic operation. + * + * To enable both address filter and transmissions of autoack: + * + * NETSTACK_RADIO.set_value(RADIO_PARAM_ADDRESS_HANDLER, + * RADIO_ADDRESS_HANDLER_FILTER | RADIO_ADDRESS_HANDLER_AUTOACK); + */ +#define RADIO_ADDRESS_HANDLER_FILTER (1 << 0) +#define RADIO_ADDRESS_HANDLER_AUTOACK (1 << 1) /* Radio return values when setting or getting radio parameters. */ typedef enum { @@ -99,6 +193,14 @@ typedef enum { RADIO_RESULT_ERROR } radio_result_t; +/* Radio return values for transmissions. */ +enum { + RADIO_TX_OK, + RADIO_TX_ERR, + RADIO_TX_COLLISION, + RADIO_TX_NOACK, +}; + /** * The structure of a device driver for a radio in Contiki. */ @@ -134,31 +236,28 @@ struct radio_driver { /** Turn the radio off. */ int (* off)(void); - /** Get a radio parameter */ + /** Get a radio parameter value. */ radio_result_t (* get_value)(radio_param_t param, radio_value_t *value); - /** Set a radio parameter */ + /** Set a radio parameter value. */ radio_result_t (* set_value)(radio_param_t param, radio_value_t value); - /** Get a radio object (for example a 64 bit address) */ + /** + * Get a radio parameter object. The argument 'dest' must point to a + * memory area of at least 'size' bytes, and this memory area will + * contain the parameter object if the function succeeds. + */ radio_result_t (* get_object)(radio_param_t param, void *dest, size_t size); - /** Set a radio object (for example a 64 bit address). The data - is copied and the object memory will not be accessed after the call. - */ + /** + * Set a radio parameter object. The memory area referred to by the + * argument 'src' will not be accessed after the function returns. + */ radio_result_t (* set_object)(radio_param_t param, const void *src, size_t size); }; -/* Generic radio return values. */ -enum { - RADIO_TX_OK, - RADIO_TX_ERR, - RADIO_TX_COLLISION, - RADIO_TX_NOACK, -}; - #endif /* RADIO_H_ */ From 4834816306c04295ab3f77fa2305d80ebb7414e6 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Mon, 7 Apr 2014 15:41:16 +0200 Subject: [PATCH 15/30] Added radio parameter RADIO_PARAM_CCA_THRESHOLD for STM32W --- cpu/stm32w108/dev/stm32w-radio.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpu/stm32w108/dev/stm32w-radio.c b/cpu/stm32w108/dev/stm32w-radio.c index aaee47ce4..53774ae1c 100644 --- a/cpu/stm32w108/dev/stm32w-radio.c +++ b/cpu/stm32w108/dev/stm32w-radio.c @@ -297,6 +297,9 @@ get_value(radio_param_t param, radio_value_t *value) case RADIO_PARAM_TXPOWER: *value = ST_RadioGetPower(); return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + *value = ST_RadioGetEdCcaThreshold(); + return RADIO_RESULT_OK; case RADIO_PARAM_RSSI: *value = ST_RadioEnergyDetection(); return RADIO_RESULT_OK; @@ -349,6 +352,10 @@ set_value(radio_param_t param, radio_value_t value) ST_RadioSetNodeId(value & 0xffff); return RADIO_RESULT_OK; case RADIO_PARAM_ADDRESS_HANDLER: + if(value & ~(RADIO_ADDRESS_HANDLER_FILTER | + RADIO_ADDRESS_HANDLER_AUTOACK)) { + return RADIO_RESULT_INVALID_VALUE; + } ST_RadioEnableAddressFiltering((value & RADIO_ADDRESS_HANDLER_FILTER) != 0); ST_RadioEnableAutoAck((value & RADIO_ADDRESS_HANDLER_AUTOACK) != 0); return RADIO_RESULT_OK; @@ -357,6 +364,9 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_INVALID_VALUE; } return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + ST_RadioSetEdCcaThreshold((int8_t)value); + return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; } From 8c0cdcfaec77444db3f1aef1e4e4a9bdb0d5be5a Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Mon, 7 Apr 2014 15:42:39 +0200 Subject: [PATCH 16/30] Added radio parameters RADIO_PARAM_RSSI and RADIO_PARAM_TXPOWER for cc2420 --- dev/cc2420/cc2420.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 9646529e0..64dbb0a7d 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -84,6 +84,9 @@ #define FOOTER1_CRC_OK 0x80 #define FOOTER1_CORRELATION 0x7f +/* The RSSI_OFFSET is approximate -45 (see CC2420 specification) */ +#define RSSI_OFFSET -45 + #define DEBUG 0 #if DEBUG #include @@ -103,6 +106,28 @@ #define LEDS_OFF(x) #endif +/* Conversion map between PA_LEVEL and output power in dBm + (from table 9 in CC2420 specification). +*/ +struct output_config { + int8_t power; + uint8_t config; +}; + +static const struct output_config output_power[] = { + { 0, 31 }, /* 0xff */ + { -1, 27 }, /* 0xfb */ + { -3, 23 }, /* 0xf7 */ + { -5, 19 }, /* 0xf3 */ + { -7, 15 }, /* 0xef */ + {-10, 11 }, /* 0xeb */ + {-15, 7 }, /* 0xe7 */ + {-25, 3 }, /* 0xe3 */ +}; +#define OUTPUT_NUM (sizeof(output_power) / sizeof(struct output_config)) +#define OUTPUT_POWER_MAX 0 +#define OUTPUT_POWER_MIN -25 + void cc2420_arch_init(void); /* XXX hack: these will be made as Chameleon packet attributes */ @@ -154,6 +179,8 @@ static int channel; static radio_result_t get_value(radio_param_t param, radio_value_t *value) { + int i, v; + if(!value) { return RADIO_RESULT_INVALID_VALUE; } @@ -164,12 +191,33 @@ get_value(radio_param_t param, radio_value_t *value) case RADIO_PARAM_CHANNEL: *value = cc2420_get_channel(); return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + v = cc2420_get_txpower(); + *value = OUTPUT_POWER_MIN; + /* Find the actual estimated output power in conversion table */ + for(i = 0; i < OUTPUT_NUM; i++) { + if(v >= output_power[i].config) { + *value = output_power[i].power; + break; + } + } + return RADIO_RESULT_OK; + case RADIO_PARAM_RSSI: + /* Return the RSSI value in dBm */ + *value = cc2420_rssi() + RSSI_OFFSET; + return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MIN: *value = 11; return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MAX: *value = 26; return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MIN: + *value = OUTPUT_POWER_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = OUTPUT_POWER_MAX; + return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; } @@ -178,6 +226,8 @@ get_value(radio_param_t param, radio_value_t *value) static radio_result_t set_value(radio_param_t param, radio_value_t value) { + int i; + switch(param) { case RADIO_PARAM_POWER_MODE: if(value == RADIO_POWER_MODE_ON) { @@ -195,6 +245,17 @@ set_value(radio_param_t param, radio_value_t value) } cc2420_set_channel(value); return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + /* Find the closest higher PA_LEVEL for the desired output power */ + for(i = 1; i < OUTPUT_NUM; i++) { + if(value > output_power[i].power) { + cc2420_set_txpower(output_power[i - 1].config); + return RADIO_RESULT_OK; + } + } + /* Set lowest output power */ + cc2420_set_txpower(output_power[OUTPUT_NUM - 1].config); + return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; } From 8ea9cb7693a8a2c1e4a7cd318dffb4b464db7a0e Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Mon, 7 Apr 2014 16:11:30 +0200 Subject: [PATCH 17/30] Split the radio parameter ADDRESS_HANDLER into RX_MODE and TX_MODE. --- core/dev/radio.h | 49 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/core/dev/radio.h b/core/dev/radio.h index 05b87f225..99ab240b1 100644 --- a/core/dev/radio.h +++ b/core/dev/radio.h @@ -108,9 +108,19 @@ enum { filter. */ RADIO_PARAM_16BIT_ADDR, - /* Address handler take care of address filtering and sending auto-ACK. - (See below for more information.) */ - RADIO_PARAM_ADDRESS_HANDLER, + /* + * Radio receiver mode determines if the radio has address filter + * (RADIO_RX_MODE_ADDRESS_FILTER) and auto-ACK (RADIO_RX_MODE_AUTOACK) + * enabled. This parameter is set as a bit mask. + */ + RADIO_PARAM_RX_MODE, + + /* + * Radio transmission mode determines if the radio has send on CCA + * (RADIO_TX_MODE_SEND_ON_CCA) enabled or not. This parameter is set + * as a bit mask. + */ + RADIO_PARAM_TX_MODE, /* * Transmission power in dBm. The values can range from @@ -169,21 +179,29 @@ enum { }; /** - * The address handler is an abstraction responsible for address - * filtering and automatic transmission of acknowledgements in the - * radio (if such operations are supported by the radio). + * The radio reception mode controls address filtering and automatic + * transmission of acknowledgements in the radio (if such operations + * are supported by the radio). A single parameter is used to allow + * setting these features simultaneously as an atomic operation. * - * There are different options that can be used like address filter - * on/off, autoack on/off. A single parameter is used to set them - * simultaneous as an atomic operation. + * To enable both address filter and transmissions of automatic + * acknowledgments: * - * To enable both address filter and transmissions of autoack: - * - * NETSTACK_RADIO.set_value(RADIO_PARAM_ADDRESS_HANDLER, - * RADIO_ADDRESS_HANDLER_FILTER | RADIO_ADDRESS_HANDLER_AUTOACK); + * NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, + * RADIO_RX_MODE_ADDRESS_FILTER | RADIO_RX_MODE_AUTOACK); */ -#define RADIO_ADDRESS_HANDLER_FILTER (1 << 0) -#define RADIO_ADDRESS_HANDLER_AUTOACK (1 << 1) +#define RADIO_RX_MODE_ADDRESS_FILTER (1 << 0) +#define RADIO_RX_MODE_AUTOACK (1 << 1) + +/** + * The radio transmission mode controls whether transmissions should + * be done using clear channel assessment (if supported by the + * radio). If send-on-CCA is enabled, the radio's send function will + * wait for a radio-specific time window for the channel to become + * clear. If this does not happen, the send function will return + * RADIO_TX_COLLISION. + */ +#define RADIO_TX_MODE_SEND_ON_CCA (1 << 0) /* Radio return values when setting or getting radio parameters. */ typedef enum { @@ -260,6 +278,5 @@ struct radio_driver { #endif /* RADIO_H_ */ - /** @} */ /** @} */ From 207f1987ee5c304d65200f44ff62192aae8945e2 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Mon, 7 Apr 2014 16:12:48 +0200 Subject: [PATCH 18/30] Implemented radio rx mode parameter for STM32W, changed the byte order of the 64 bit address to big-endian. --- cpu/stm32w108/dev/stm32w-radio.c | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/cpu/stm32w108/dev/stm32w-radio.c b/cpu/stm32w108/dev/stm32w-radio.c index 53774ae1c..07fbf1758 100644 --- a/cpu/stm32w108/dev/stm32w-radio.c +++ b/cpu/stm32w108/dev/stm32w-radio.c @@ -285,13 +285,13 @@ get_value(radio_param_t param, radio_value_t *value) case RADIO_PARAM_16BIT_ADDR: *value = ST_RadioGetNodeId(); return RADIO_RESULT_OK; - case RADIO_PARAM_ADDRESS_HANDLER: + case RADIO_PARAM_RX_MODE: *value = 0; if(ST_RadioAddressFilteringEnabled()) { - *value |= RADIO_ADDRESS_HANDLER_FILTER; + *value |= RADIO_RX_MODE_ADDRESS_FILTER; } if(ST_RadioAutoAckEnabled()) { - *value |= RADIO_ADDRESS_HANDLER_AUTOACK; + *value |= RADIO_RX_MODE_AUTOACK; } return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: @@ -305,10 +305,10 @@ get_value(radio_param_t param, radio_value_t *value) return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MIN: - *value = 11; + *value = ST_MIN_802_15_4_CHANNEL_NUMBER; return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MAX: - *value = 26; + *value = ST_MAX_802_15_4_CHANNEL_NUMBER; return RADIO_RESULT_OK; case RADIO_CONST_TXPOWER_MIN: @@ -338,7 +338,8 @@ set_value(radio_param_t param, radio_value_t value) } return RADIO_RESULT_INVALID_VALUE; case RADIO_PARAM_CHANNEL: - if(value < 11 || value > 26) { + if(value < ST_MIN_802_15_4_CHANNEL_NUMBER || + value > ST_MAX_802_15_4_CHANNEL_NUMBER) { return RADIO_RESULT_INVALID_VALUE; } if(ST_RadioSetChannel(value) != ST_SUCCESS) { @@ -351,15 +352,20 @@ set_value(radio_param_t param, radio_value_t value) case RADIO_PARAM_16BIT_ADDR: ST_RadioSetNodeId(value & 0xffff); return RADIO_RESULT_OK; - case RADIO_PARAM_ADDRESS_HANDLER: - if(value & ~(RADIO_ADDRESS_HANDLER_FILTER | - RADIO_ADDRESS_HANDLER_AUTOACK)) { + case RADIO_PARAM_RX_MODE: + if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | + RADIO_RX_MODE_AUTOACK)) { return RADIO_RESULT_INVALID_VALUE; } - ST_RadioEnableAddressFiltering((value & RADIO_ADDRESS_HANDLER_FILTER) != 0); - ST_RadioEnableAutoAck((value & RADIO_ADDRESS_HANDLER_AUTOACK) != 0); + ST_RadioEnableAddressFiltering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0); + ST_RadioEnableAutoAck((value & RADIO_RX_MODE_AUTOACK) != 0); return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: + if(value < MIN_RADIO_POWER) { + value = MIN_RADIO_POWER; + } else if(value > MAX_RADIO_POWER) { + value = MAX_RADIO_POWER; + } if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) { return RADIO_RESULT_INVALID_VALUE; } @@ -375,7 +381,9 @@ set_value(radio_param_t param, radio_value_t value) static radio_result_t get_object(radio_param_t param, void *dest, size_t size) { - uint8_t *eui64; + const uint8_t *eui64; + uint8_t *target; + int i; if(param == RADIO_PARAM_64BIT_ADDR) { if(size < 8 || !dest) { @@ -385,7 +393,10 @@ get_object(radio_param_t param, void *dest, size_t size) if(!eui64) { return RADIO_RESULT_ERROR; } - memcpy(dest, eui64, 8); + target = dest; + for(i = 0; i < 8; i++) { + target[i] = eui64[7 - i]; + } return RADIO_RESULT_OK; } return RADIO_RESULT_NOT_SUPPORTED; From 271ac4413fffafdc44d39e56ffef2472b2c42055 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 11 Apr 2014 12:58:49 +0200 Subject: [PATCH 19/30] Removed the unused function cc2420_cca_valid and replaced some macros with functions in CC2420. This reduces the code size with over 400 bytes. --- dev/cc2420/cc2420.c | 87 ++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 64dbb0a7d..4a95a2b7e 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -137,7 +137,7 @@ int cc2420_authority_level_of_sender; int cc2420_packets_seen, cc2420_packets_read; -static uint8_t volatile pending; +/* static uint8_t volatile pending; */ #define BUSYWAIT_UNTIL(cond, max_time) \ do { \ @@ -294,6 +294,12 @@ const struct radio_driver cc2420_driver = }; /*---------------------------------------------------------------------------*/ +static void +strobe(enum cc2420_register regname) +{ + CC2420_STROBE(regname); +} +/*---------------------------------------------------------------------------*/ static void getrxdata(void *buf, int len) @@ -310,15 +316,12 @@ flushrx(void) { uint8_t dummy; - CC2420_READ_FIFO_BYTE(dummy); - CC2420_STROBE(CC2420_SFLUSHRX); - CC2420_STROBE(CC2420_SFLUSHRX); -} -/*---------------------------------------------------------------------------*/ -static void -strobe(enum cc2420_register regname) -{ - CC2420_STROBE(regname); + getrxbyte(&dummy); + strobe(CC2420_SFLUSHRX); + strobe(CC2420_SFLUSHRX); + if(dummy) { + /* avoid unused variable compiler warning */ + } } /*---------------------------------------------------------------------------*/ static unsigned int @@ -329,6 +332,18 @@ status(void) return status; } /*---------------------------------------------------------------------------*/ +static void +wait_for_status(unsigned int mask) +{ + BUSYWAIT_UNTIL((status() & mask), RTIMER_SECOND / 10); +} +/*---------------------------------------------------------------------------*/ +static void +wait_for_not_status(unsigned int mask) +{ + BUSYWAIT_UNTIL(!(status() & mask), RTIMER_SECOND / 10); +} +/*---------------------------------------------------------------------------*/ static uint8_t locked, lock_on, lock_off; static void @@ -337,7 +352,7 @@ on(void) CC2420_ENABLE_FIFOP_INT(); strobe(CC2420_SRXON); - BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 100); + wait_for_status(BV(CC2420_XOSC16M_STABLE)); ENERGEST_ON(ENERGEST_TYPE_LISTEN); receive_on = 1; @@ -349,7 +364,7 @@ off(void) receive_on = 0; /* Wait for transmission to end before turning radio off. */ - BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10); + wait_for_not_status(BV(CC2420_TX_ACTIVE)); ENERGEST_OFF(ENERGEST_TYPE_LISTEN); strobe(CC2420_SRFOFF); @@ -390,6 +405,12 @@ setreg(enum cc2420_register regname, unsigned value) } /*---------------------------------------------------------------------------*/ static void +write_ram(const void *buf, uint16_t addr, int count) +{ + CC2420_WRITE_RAM(buf, addr, count); +} +/*---------------------------------------------------------------------------*/ +static void set_txpower(uint8_t power) { uint16_t reg; @@ -476,7 +497,6 @@ static int cc2420_transmit(unsigned short payload_len) { int i, txpower; - uint8_t total_len; #if CC2420_CONF_CHECKSUM uint16_t checksum; #endif /* CC2420_CONF_CHECKSUM */ @@ -491,8 +511,6 @@ cc2420_transmit(unsigned short payload_len) set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1); } - total_len = payload_len + AUX_LEN; - /* The TX FIFO can only hold one packet. Make sure to not overrun * FIFO by waiting for transmission to start here and synchronizing * with the CC2420_TX_ACTIVE check in cc2420_send. @@ -508,7 +526,7 @@ cc2420_transmit(unsigned short payload_len) #if WITH_SEND_CCA strobe(CC2420_SRXON); - BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10); + wait_for_status(BV(CC2420_RSSI_VALID)); strobe(CC2420_STXONCCA); #else /* WITH_SEND_CCA */ strobe(CC2420_STXON); @@ -521,7 +539,7 @@ cc2420_transmit(unsigned short payload_len) if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { /* Write timestamp to last two bytes of packet in TXFIFO. */ - CC2420_WRITE_RAM(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2); + write_ram(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2); } } @@ -538,7 +556,7 @@ cc2420_transmit(unsigned short payload_len) ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); /* We wait until transmission has ended so that we get an accurate measurement of the transmission time.*/ - BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10); + wait_for_not_status(BV(CC2420_TX_ACTIVE)); #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower()); @@ -685,10 +703,10 @@ cc2420_set_channel(int c) /* * Writing RAM requires crystal oscillator to be stable. */ - BUSYWAIT_UNTIL((status() & (BV(CC2420_XOSC16M_STABLE))), RTIMER_SECOND / 10); + wait_for_status(BV(CC2420_XOSC16M_STABLE)); /* Wait for any transmission to end. */ - BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10); + wait_for_not_status(BV(CC2420_TX_ACTIVE)); setreg(CC2420_FSCTRL, f); @@ -715,22 +733,22 @@ cc2420_set_pan_addr(unsigned pan, /* * Writing RAM requires crystal oscillator to be stable. */ - BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 10); + wait_for_status(BV(CC2420_XOSC16M_STABLE)); tmp[0] = pan & 0xff; tmp[1] = pan >> 8; - CC2420_WRITE_RAM(&tmp, CC2420RAM_PANID, 2); + write_ram(&tmp, CC2420RAM_PANID, 2); tmp[0] = addr & 0xff; tmp[1] = addr >> 8; - CC2420_WRITE_RAM(&tmp, CC2420RAM_SHORTADDR, 2); + write_ram(&tmp, CC2420RAM_SHORTADDR, 2); if(ieee_addr != NULL) { uint8_t tmp_addr[8]; /* LSB first, MSB last for 802.15.4 addresses in CC2420 */ for (f = 0; f < 8; f++) { tmp_addr[7 - f] = ieee_addr[f]; } - CC2420_WRITE_RAM(tmp_addr, CC2420RAM_IEEEADDR, 8); + write_ram(tmp_addr, CC2420RAM_IEEEADDR, 8); } RELEASE_LOCK(); } @@ -745,7 +763,7 @@ cc2420_interrupt(void) process_poll(&cc2420_process); last_packet_timestamp = cc2420_sfd_start_time; - pending++; + /* pending++; */ cc2420_packets_seen++; return 1; } @@ -790,7 +808,7 @@ cc2420_read(void *buf, unsigned short bufsize) return 0; }*/ - pending = 0; + /* pending = 0; */ GET_LOCK(); @@ -906,7 +924,7 @@ cc2420_rssi(void) radio_was_off = 1; cc2420_on(); } - BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100); + wait_for_status(BV(CC2420_RSSI_VALID)); rssi = (int)((signed char)getreg(CC2420_RSSI)); @@ -925,19 +943,6 @@ detected_energy(void) } */ /*---------------------------------------------------------------------------*/ -int -cc2420_cca_valid(void) -{ - int valid; - if(locked) { - return 1; - } - GET_LOCK(); - valid = !!(status() & BV(CC2420_RSSI_VALID)); - RELEASE_LOCK(); - return valid; -} -/*---------------------------------------------------------------------------*/ static int cc2420_cca(void) { @@ -967,7 +972,7 @@ cc2420_cca(void) return 1; } - BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100); + wait_for_status(BV(CC2420_RSSI_VALID)); cca = CC2420_CCA_IS_1; From f0c48c55ca2ca3058f0b50119beae4a083ea4e0a Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Sun, 13 Apr 2014 21:33:50 +0200 Subject: [PATCH 20/30] Fixed STM32W radio to return RADIO_RESULT_INVALID_VALUE if trying to set a transmission power outside the valid range instead of using closest valid value. --- cpu/stm32w108/dev/stm32w-radio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cpu/stm32w108/dev/stm32w-radio.c b/cpu/stm32w108/dev/stm32w-radio.c index 07fbf1758..4488b3a93 100644 --- a/cpu/stm32w108/dev/stm32w-radio.c +++ b/cpu/stm32w108/dev/stm32w-radio.c @@ -361,10 +361,8 @@ set_value(radio_param_t param, radio_value_t value) ST_RadioEnableAutoAck((value & RADIO_RX_MODE_AUTOACK) != 0); return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: - if(value < MIN_RADIO_POWER) { - value = MIN_RADIO_POWER; - } else if(value > MAX_RADIO_POWER) { - value = MAX_RADIO_POWER; + if(value < MIN_RADIO_POWER || value > MAX_RADIO_POWER) { + return RADIO_RESULT_INVALID_VALUE; } if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) { return RADIO_RESULT_INVALID_VALUE; From 132b8dde3bac9bfd6118d207fec41829ec3ab856 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Sun, 13 Apr 2014 21:43:37 +0200 Subject: [PATCH 21/30] Fixed CC2420 to return RADIO_RESULT_INVALID_VALUE if trying to set a transmission power outside the valid range instead of using closest valid value. --- dev/cc2420/cc2420.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 4a95a2b7e..6662eb1f1 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -246,15 +246,16 @@ set_value(radio_param_t param, radio_value_t value) cc2420_set_channel(value); return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: + if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } /* Find the closest higher PA_LEVEL for the desired output power */ for(i = 1; i < OUTPUT_NUM; i++) { if(value > output_power[i].power) { - cc2420_set_txpower(output_power[i - 1].config); - return RADIO_RESULT_OK; + break; } } - /* Set lowest output power */ - cc2420_set_txpower(output_power[OUTPUT_NUM - 1].config); + cc2420_set_txpower(output_power[i - 1].config); return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; From 0ec1eda75ed5c2c0e4cc5a4cf2bbe699817034b9 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sun, 13 Apr 2014 15:43:32 +0100 Subject: [PATCH 22/30] Implement extended RF API for the CC2538 --- cpu/cc2538/dev/cc2538-rf.c | 334 ++++++++++++++++++++++++++++++++----- cpu/cc2538/dev/cc2538-rf.h | 38 +---- 2 files changed, 297 insertions(+), 75 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 735464708..bedd92168 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -126,10 +126,39 @@ static uint8_t rf_flags; static int on(void); static int off(void); /*---------------------------------------------------------------------------*/ +/* TX Power dBm lookup table. Values from SmartRF Studio v1.16.0 */ +typedef struct output_config { + radio_value_t power; + uint8_t txpower_val; +} output_config_t; + +static const output_config_t output_power[] = { + { 7, 0xFF }, + { 5, 0xED }, + { 3, 0xD5 }, + { 1, 0xC5 }, + { 0, 0xB6 }, + { -1, 0xB0 }, + { -3, 0xA1 }, + { -5, 0x91 }, + { -7, 0x88 }, + { -9, 0x72 }, + {-11, 0x62 }, + {-13, 0x58 }, + {-15, 0x42 }, + {-24, 0x00 }, +}; + +#define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) +/*---------------------------------------------------------------------------*/ PROCESS(cc2538_rf_process, "cc2538 RF driver"); /*---------------------------------------------------------------------------*/ -uint8_t -cc2538_rf_channel_get() +/** + * \brief Get the current operating channel + * \return Returns a value in [11,26] representing the current channel + */ +static uint8_t +get_channel() { uint8_t chan = REG(RFCORE_XREG_FREQCTRL) & RFCORE_XREG_FREQCTRL_FREQ; @@ -137,13 +166,19 @@ cc2538_rf_channel_get() + CC2538_RF_CHANNEL_MIN); } /*---------------------------------------------------------------------------*/ -int8_t -cc2538_rf_channel_set(uint8_t channel) +/** + * \brief Set the current operating channel + * \param channel The desired channel as a value in [11,26] + * \return Returns a value in [11,26] representing the current channel + * or a negative value if \e channel was out of bounds + */ +static int8_t +set_channel(uint8_t channel) { PRINTF("RF: Set Channel\n"); if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) { - return -1; + return CC2538_RF_CHANNEL_SET_ERROR; } /* Changes to FREQCTRL take effect after the next recalibration */ @@ -155,41 +190,43 @@ cc2538_rf_channel_set(uint8_t channel) return (int8_t) channel; } /*---------------------------------------------------------------------------*/ -uint8_t -cc2538_rf_power_set(uint8_t new_power) +static radio_value_t +get_pan_id(void) { - PRINTF("RF: Set Power\n"); - - REG(RFCORE_XREG_TXPOWER) = new_power; - - return (REG(RFCORE_XREG_TXPOWER) & 0xFF); + return (radio_value_t)(REG(RFCORE_FFSM_PAN_ID1) << 8 | REG(RFCORE_FFSM_PAN_ID0)); } /*---------------------------------------------------------------------------*/ -/* ToDo: Check once we have info on the... infopage */ -void -cc2538_rf_set_addr(uint16_t pan) +static void +set_pan_id(uint16_t pan) { -#if LINKADDR_SIZE==8 - /* EXT_ADDR[7:0] is ignored when using short addresses */ - int i; - - for(i = (LINKADDR_SIZE - 1); i >= 0; --i) { - ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = - linkaddr_node_addr.u8[LINKADDR_SIZE - 1 - i]; - } -#endif - REG(RFCORE_FFSM_PAN_ID0) = pan & 0xFF; REG(RFCORE_FFSM_PAN_ID1) = pan >> 8; - - REG(RFCORE_FFSM_SHORT_ADDR0) = linkaddr_node_addr.u8[LINKADDR_SIZE - 1]; - REG(RFCORE_FFSM_SHORT_ADDR1) = linkaddr_node_addr.u8[LINKADDR_SIZE - 2]; } /*---------------------------------------------------------------------------*/ -int -cc2538_rf_read_rssi(void) +static radio_value_t +get_short_addr(void) { - int rssi; + return (radio_value_t)(REG(RFCORE_FFSM_SHORT_ADDR1) << 8 | REG(RFCORE_FFSM_SHORT_ADDR0)); +} +/*---------------------------------------------------------------------------*/ +static void +set_short_addr(uint16_t addr) +{ + REG(RFCORE_FFSM_SHORT_ADDR0) = addr & 0xFF; + REG(RFCORE_FFSM_SHORT_ADDR1) = addr >> 8; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Reads the current signal strength (RSSI) + * \return The current RSSI in dBm + * + * This function reads the current RSSI on the currently configured + * channel. + */ +static radio_value_t +get_rssi(void) +{ + int8_t rssi; /* If we are off, turn on first */ if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { @@ -200,7 +237,7 @@ cc2538_rf_read_rssi(void) /* Wait on RSSI_VALID */ while((REG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0); - rssi = ((int8_t)REG(RFCORE_XREG_RSSI)) - RSSI_OFFSET; + rssi = (int8_t)(REG(RFCORE_XREG_RSSI) & RFCORE_XREG_RSSI_RSSI_VAL) - RSSI_OFFSET; /* If we were off, turn back off */ if((rf_flags & WAS_OFF) == WAS_OFF) { @@ -211,6 +248,80 @@ cc2538_rf_read_rssi(void) return rssi; } /*---------------------------------------------------------------------------*/ +/* Returns the current CCA threshold in dBm */ +static radio_value_t +get_cca_threshold(void) +{ + return (int8_t)(REG(RFCORE_XREG_CCACTRL0) & RFCORE_XREG_CCACTRL0_CCA_THR) - RSSI_OFFSET; +} +/*---------------------------------------------------------------------------*/ +/* Sets the CCA threshold in dBm */ +static void +set_cca_threshold(radio_value_t value) +{ + REG(RFCORE_XREG_CCACTRL0) = (value & 0xFF) + RSSI_OFFSET; +} +/*---------------------------------------------------------------------------*/ +/* Returns the current TX power in dBm */ +static radio_value_t +get_tx_power(void) +{ + int i; + uint8_t reg_val = REG(RFCORE_XREG_TXPOWER) & 0xFF; + + /* + * Find the TXPOWER value in the lookup table + * If the value has been written with set_tx_power, we should be able to + * find the exact value. However, in case the register has been written in + * a different fashion, we return the immediately lower value of the lookup + */ + for(i = 0; i < OUTPUT_CONFIG_COUNT; i++) { + if(reg_val >= output_power[i].txpower_val) { + return output_power[i].power; + } + } + return CC2538_RF_TX_POWER_MIN; +} +/*---------------------------------------------------------------------------*/ +/* + * Set TX power to 'at least' power dBm + * This works with a lookup table. If the value of 'power' does not exist in + * the lookup table, TXPOWER will be set to the immediately higher available + * value + */ +static void +set_tx_power(radio_value_t power) +{ + int i; + + for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) { + if(power <= output_power[i].power) { + REG(RFCORE_XREG_TXPOWER) = output_power[i].txpower_val; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_frame_filtering(uint8_t enable) +{ + if(enable) { + REG(RFCORE_XREG_FRMFILT0) |= RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN; + } else { + REG(RFCORE_XREG_FRMFILT0) &= ~RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN; + } +} +/*---------------------------------------------------------------------------*/ +static void +set_auto_ack(uint8_t enable) +{ + if(enable) { + REG(RFCORE_XREG_FRMCTRL0) |= RFCORE_XREG_FRMCTRL0_AUTOACK; + } else { + REG(RFCORE_XREG_FRMCTRL0) &= ~RFCORE_XREG_FRMCTRL0_AUTOACK; + } +} +/*---------------------------------------------------------------------------*/ /* Netstack API radio driver functions */ /*---------------------------------------------------------------------------*/ static int @@ -327,8 +438,10 @@ init(void) /* MAX FIFOP threshold */ REG(RFCORE_XREG_FIFOPCTRL) = CC2538_RF_MAX_PACKET_LEN; - cc2538_rf_power_set(CC2538_RF_TX_POWER); - cc2538_rf_channel_set(CC2538_RF_CHANNEL); + /* Set TX Power */ + REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER; + + set_channel(CC2538_RF_CHANNEL); /* Acknowledge RF interrupts, FIFOP only */ REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; @@ -641,24 +754,150 @@ pending_packet(void) static radio_result_t get_value(radio_param_t param, radio_value_t *value) { - return RADIO_RESULT_NOT_SUPPORTED; + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch(param) { + case RADIO_PARAM_POWER_MODE: + *value = (REG(RFCORE_XREG_RXENABLE) && RFCORE_XREG_RXENABLE_RXENMASK) == 0 + ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = (radio_value_t)get_channel(); + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + *value = get_pan_id(); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + *value = get_short_addr(); + return RADIO_RESULT_OK; + case RADIO_PARAM_RX_MODE: + *value = 0; + if(REG(RFCORE_XREG_FRMFILT0) & RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN) { + *value |= RADIO_RX_MODE_ADDRESS_FILTER; + } + if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) { + *value |= RADIO_RX_MODE_AUTOACK; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + *value = get_tx_power(); + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + *value = get_cca_threshold(); + return RADIO_RESULT_OK; + case RADIO_PARAM_RSSI: + *value = get_rssi(); + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MIN: + *value = CC2538_RF_CHANNEL_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = CC2538_RF_CHANNEL_MAX; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MIN: + *value = CC2538_RF_TX_POWER_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = CC2538_RF_TX_POWER_MAX; + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } } /*---------------------------------------------------------------------------*/ static radio_result_t set_value(radio_param_t param, radio_value_t value) { - return RADIO_RESULT_NOT_SUPPORTED; + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + on(); + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < CC2538_RF_CHANNEL_MIN || + value > CC2538_RF_CHANNEL_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + if(set_channel(value) == CC2538_RF_CHANNEL_SET_ERROR) { + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + set_pan_id(value & 0xffff); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + set_short_addr(value & 0xffff); + return RADIO_RESULT_OK; + case RADIO_PARAM_RX_MODE: + if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | + RADIO_RX_MODE_AUTOACK)) { + return RADIO_RESULT_INVALID_VALUE; + } + + set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0); + set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0); + + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + if(value < CC2538_RF_TX_POWER_MIN || value > CC2538_RF_TX_POWER_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + + set_tx_power(value); + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + set_cca_threshold(value); + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } } /*---------------------------------------------------------------------------*/ static radio_result_t get_object(radio_param_t param, void *dest, size_t size) { + uint8_t *target; + int i; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size < 8 || !dest || LINKADDR_SIZE != 8) { + return RADIO_RESULT_INVALID_VALUE; + } + + target = dest; + for(i = 0; i < size; i++) { + target[size - 1 - i] = ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] & 0xFF; + } + + return RADIO_RESULT_OK; + } return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ static radio_result_t set_object(radio_param_t param, const void *src, size_t size) { + int i; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size < 8 || !src || LINKADDR_SIZE != 8) { + return RADIO_RESULT_INVALID_VALUE; + } + + for(i = 0; i < size; i++) { + ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = ((uint8_t *)src)[size - 1 - i]; + } + + return RADIO_RESULT_OK; + } return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ @@ -776,11 +1015,26 @@ cc2538_rf_err_isr(void) void cc2538_rf_set_promiscous_mode(char p) { - if(p) { - REG(RFCORE_XREG_FRMFILT0) &= ~RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN; - } else { - REG(RFCORE_XREG_FRMFILT0) |= RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN; + set_frame_filtering(p); +} +/*---------------------------------------------------------------------------*/ +void +cc2538_rf_set_addr(uint16_t pan) +{ +#if LINKADDR_SIZE == 8 + /* EXT_ADDR[7:0] is ignored when using short addresses */ + int i; + + for(i = (LINKADDR_SIZE - 1); i >= 0; --i) { + ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = + linkaddr_node_addr.u8[LINKADDR_SIZE - 1 - i]; } +#endif + + set_pan_id(pan); + + REG(RFCORE_FFSM_SHORT_ADDR0) = linkaddr_node_addr.u8[LINKADDR_SIZE - 1]; + REG(RFCORE_FFSM_SHORT_ADDR1) = linkaddr_node_addr.u8[LINKADDR_SIZE - 2]; } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/cpu/cc2538/dev/cc2538-rf.h b/cpu/cc2538/dev/cc2538-rf.h index 9d48929cf..3606ce78f 100644 --- a/cpu/cc2538/dev/cc2538-rf.h +++ b/cpu/cc2538/dev/cc2538-rf.h @@ -56,10 +56,13 @@ #define CC2538_RF_CHANNEL_MIN 11 #define CC2538_RF_CHANNEL_MAX 26 #define CC2538_RF_CHANNEL_SPACING 5 +#define CC2538_RF_CHANNEL_SET_ERROR -1 #define CC2538_RF_MAX_PACKET_LEN 127 #define CC2538_RF_MIN_PACKET_LEN 4 #define CC2538_RF_CCA_CLEAR 1 #define CC2538_RF_CCA_BUSY 0 +#define CC2538_RF_TX_POWER_MIN -24 +#define CC2538_RF_TX_POWER_MAX 7 /*---------------------------------------------------------------------------*/ #ifdef CC2538_RF_CONF_TX_POWER #define CC2538_RF_TX_POWER CC2538_RF_CONF_TX_POWER @@ -132,31 +135,6 @@ /** The NETSTACK data structure for the cc2538 RF driver */ extern const struct radio_driver cc2538_rf_driver; /*---------------------------------------------------------------------------*/ -/** - * \brief Set the current operating channel - * \param channel The desired channel as a value in [11,26] - * \return Returns a value in [11,26] representing the current channel - * or a negative value if \e channel was out of bounds - */ -int8_t cc2538_rf_channel_set(uint8_t channel); - -/** - * \brief Get the current operating channel - * \return Returns a value in [11,26] representing the current channel - */ -uint8_t cc2538_rf_channel_get(void); - -/** - * \brief Sets RF TX power - * \param new_power The desired power level - * \return The power level in use after the adjustment - * - * The value specified in \e new_power will be written directly to the - * RFCORE_XREG_TXPOWER register. See the datasheet for more details on - * possible values. - */ -uint8_t cc2538_rf_power_set(uint8_t new_power); - /** * \brief Sets addresses and PAN identifier to the relevant RF hardware * registers @@ -168,15 +146,6 @@ uint8_t cc2538_rf_power_set(uint8_t new_power); */ void cc2538_rf_set_addr(uint16_t pan); -/** - * \brief Reads the current signal strength (RSSI) - * \return The current RSSI - * - * This function reads the current RSSI on the currently configured - * channel. - */ -int cc2538_rf_read_rssi(void); - /** * \brief Turn promiscous mode on or off * \param p If promiscous mode should be on (1) or off (0) @@ -187,7 +156,6 @@ int cc2538_rf_read_rssi(void); * address as the receive address are returned from the RF core. */ void cc2538_rf_set_promiscous_mode(char p); - /*---------------------------------------------------------------------------*/ #endif /* CC2538_RF_H__ */ From 22800de94e9b134f5b549b786255266ee89234cd Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Sun, 13 Apr 2014 19:49:38 +0100 Subject: [PATCH 23/30] Add extended RF API example --- examples/extended-rf-api/Makefile | 11 + examples/extended-rf-api/extended-rf-api.c | 510 +++++++++++++++++++++ examples/extended-rf-api/project-conf.h | 37 ++ 3 files changed, 558 insertions(+) create mode 100644 examples/extended-rf-api/Makefile create mode 100644 examples/extended-rf-api/extended-rf-api.c create mode 100644 examples/extended-rf-api/project-conf.h diff --git a/examples/extended-rf-api/Makefile b/examples/extended-rf-api/Makefile new file mode 100644 index 000000000..e11687f9f --- /dev/null +++ b/examples/extended-rf-api/Makefile @@ -0,0 +1,11 @@ +UIP_CONF_IPV6=1 +UIP_CONF_RPL=1 + +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +CONTIKI_PROJECT = extended-rf-api + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/extended-rf-api/extended-rf-api.c b/examples/extended-rf-api/extended-rf-api.c new file mode 100644 index 000000000..894ba0928 --- /dev/null +++ b/examples/extended-rf-api/extended-rf-api.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2014, George Oikonomou (george@contiki-os.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * Example project demonstrating the extended RF API functionality + */ +#include "contiki.h" +#include "net/netstack.h" +#include "dev/radio.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +struct rf_consts { + radio_value_t channel_min; + radio_value_t channel_max; + radio_value_t txpower_min; + radio_value_t txpower_max; +}; + +static struct rf_consts consts; + +static radio_value_t value; +static uint8_t ext_addr[8]; +/*---------------------------------------------------------------------------*/ +PROCESS(extended_rf_api_process, "Extended RF API demo process"); +AUTOSTART_PROCESSES(&extended_rf_api_process); +/*---------------------------------------------------------------------------*/ +static void +print_64bit_addr(const uint8_t *addr) +{ + unsigned int i; + for(i = 0; i < 7; i++) { + printf("%02x:", addr[i]); + } + printf("%02x (network order)\n", addr[7]); +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + radio_result_t rv; + + rv = NETSTACK_RADIO.get_object(param, dest, size); + + switch(rv) { + case RADIO_RESULT_ERROR: + printf("Radio returned an error\n"); + break; + case RADIO_RESULT_INVALID_VALUE: + printf("Value is invalid\n"); + break; + case RADIO_RESULT_NOT_SUPPORTED: + printf("Param %u not supported\n", param); + break; + case RADIO_RESULT_OK: + break; + default: + printf("Unknown return value\n"); + break; + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, void *src, size_t size) +{ + radio_result_t rv; + + rv = NETSTACK_RADIO.set_object(param, src, size); + + switch(rv) { + case RADIO_RESULT_ERROR: + printf("Radio returned an error\n"); + break; + case RADIO_RESULT_INVALID_VALUE: + printf("Value is invalid\n"); + break; + case RADIO_RESULT_NOT_SUPPORTED: + printf("Param %u not supported\n", param); + break; + case RADIO_RESULT_OK: + break; + default: + printf("Unknown return value\n"); + break; + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_param(radio_param_t param, radio_value_t *value) +{ + radio_result_t rv; + + rv = NETSTACK_RADIO.get_value(param, value); + + switch(rv) { + case RADIO_RESULT_ERROR: + printf("Radio returned an error\n"); + break; + case RADIO_RESULT_INVALID_VALUE: + printf("Value %d is invalid\n", *value); + break; + case RADIO_RESULT_NOT_SUPPORTED: + printf("Param %u not supported\n", param); + break; + case RADIO_RESULT_OK: + break; + default: + printf("Unknown return value\n"); + break; + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_param(radio_param_t param, radio_value_t value) +{ + radio_result_t rv; + + rv = NETSTACK_RADIO.set_value(param, value); + + switch(rv) { + case RADIO_RESULT_ERROR: + printf("Radio returned an error\n"); + break; + case RADIO_RESULT_INVALID_VALUE: + printf("Value %d is invalid\n", value); + break; + case RADIO_RESULT_NOT_SUPPORTED: + printf("Param %u not supported\n", param); + break; + case RADIO_RESULT_OK: + break; + default: + printf("Unknown return value\n"); + break; + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static void +get_rf_consts(void) +{ + printf("====================================\n"); + printf("RF Constants\n"); + printf("Min Channel : "); + if(get_param(RADIO_CONST_CHANNEL_MIN, &consts.channel_min) == RADIO_RESULT_OK) { + printf("%3d\n", consts.channel_min); + } + + printf("Max Channel : "); + if(get_param(RADIO_CONST_CHANNEL_MAX, &consts.channel_max) == RADIO_RESULT_OK) { + printf("%3d\n", consts.channel_max); + } + + printf("Min TX Power: "); + if(get_param(RADIO_CONST_TXPOWER_MIN, &consts.txpower_min) == RADIO_RESULT_OK) { + printf("%3d dBm\n", consts.txpower_min); + } + + printf("Max TX Power: "); + if(get_param(RADIO_CONST_TXPOWER_MAX, &consts.txpower_max) == RADIO_RESULT_OK) { + printf("%3d dBm\n", consts.txpower_max); + } +} +/*---------------------------------------------------------------------------*/ +static void +test_off_on(void) +{ + printf("====================================\n"); + printf("Power mode Test: Off, then On\n"); + + printf("Power mode is : "); + if(get_param(RADIO_PARAM_POWER_MODE, &value) == RADIO_RESULT_OK) { + if(value == RADIO_POWER_MODE_ON) { + printf("On\n"); + } else if(value == RADIO_POWER_MODE_OFF) { + printf("Off\n"); + } + } + + printf("Turning Off : "); + value = RADIO_POWER_MODE_OFF; + set_param(RADIO_PARAM_POWER_MODE, value); + if(get_param(RADIO_PARAM_POWER_MODE, &value) == RADIO_RESULT_OK) { + if(value == RADIO_POWER_MODE_ON) { + printf("On\n"); + } else if(value == RADIO_POWER_MODE_OFF) { + printf("Off\n"); + } + } + + printf("Turning On : "); + value = RADIO_POWER_MODE_ON; + set_param(RADIO_PARAM_POWER_MODE, value); + if(get_param(RADIO_PARAM_POWER_MODE, &value) == RADIO_RESULT_OK) { + if(value == RADIO_POWER_MODE_ON) { + printf("On\n"); + } else if(value == RADIO_POWER_MODE_OFF) { + printf("Off\n"); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +test_channels(void) +{ + int i; + + printf("====================================\n"); + printf("Channel Test: [%u , %u]\n", consts.channel_min, consts.channel_max); + + for(i = consts.channel_min; i <= consts.channel_max; i++) { + value = i; + printf("Switch to: %d, Now: ", value); + set_param(RADIO_PARAM_CHANNEL, value); + if(get_param(RADIO_PARAM_CHANNEL, &value) == RADIO_RESULT_OK) { + printf("%d\n", value); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +test_rx_modes(void) +{ + int i; + + printf("====================================\n"); + printf("RX Modes Test: [0 , 3]\n"); + + for(i = 0; i <= 3; i++) { + value = i; + printf("Switch to: %d, Now: ", value); + set_param(RADIO_PARAM_RX_MODE, value); + if(get_param(RADIO_PARAM_RX_MODE, &value) == RADIO_RESULT_OK) { + printf("Address Filtering is "); + if(value & RADIO_RX_MODE_ADDRESS_FILTER) { + printf("On, "); + } else { + printf("Off, "); + } + printf("Auto ACK is "); + if(value & RADIO_RX_MODE_AUTOACK) { + printf("On, "); + } else { + printf("Off, "); + } + + printf("(value=%d)\n", value); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +test_tx_powers(void) +{ + int i; + + printf("====================================\n"); + printf("TX Power Test: [%d , %d]\n", consts.txpower_min, consts.txpower_max); + + for(i = consts.txpower_min; i <= consts.txpower_max; i += 5) { + value = i; + printf("Switch to: %3d dBm, Now: ", value); + set_param(RADIO_PARAM_TXPOWER, value); + if(get_param(RADIO_PARAM_TXPOWER, &value) == RADIO_RESULT_OK) { + printf("%3d dBm\n", value); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +test_cca_thresholds(void) +{ + printf("====================================\n"); + printf("CCA Thres. Test: -105, then -81\n"); + + value = -105; + printf("Switch to: %4d dBm, Now: ", value); + set_param(RADIO_PARAM_CCA_THRESHOLD, value); + if(get_param(RADIO_PARAM_CCA_THRESHOLD, &value) == RADIO_RESULT_OK) { + printf("%4d dBm [0x%04x]\n", value, (uint16_t)value); + } + + value = -81; + printf("Switch to: %4d dBm, Now: ", value); + set_param(RADIO_PARAM_CCA_THRESHOLD, value); + if(get_param(RADIO_PARAM_CCA_THRESHOLD, &value) == RADIO_RESULT_OK) { + printf("%4d dBm [0x%04x]\n", value, (uint16_t)value); + } +} +/*---------------------------------------------------------------------------*/ +static void +test_pan_id(void) +{ + radio_value_t new_val; + + printf("====================================\n"); + printf("PAN ID Test: Flip bytes and back\n"); + + printf("PAN ID is: "); + if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } + + new_val = value >> 8; + new_val |= (value & 0xFF) << 8; + printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + set_param(RADIO_PARAM_PAN_ID, new_val); + if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } + + new_val = value >> 8; + new_val |= (value & 0xFF) << 8; + printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + set_param(RADIO_PARAM_PAN_ID, new_val); + if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } +} +/*---------------------------------------------------------------------------*/ +static void +test_16bit_addr(void) +{ + radio_value_t new_val; + + printf("====================================\n"); + printf("16-bit Address Test: Flip bytes and back\n"); + + printf("16-bit Address is: "); + if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } + + new_val = value >> 8; + new_val |= (value & 0xFF) << 8; + printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + set_param(RADIO_PARAM_16BIT_ADDR, new_val); + if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } + + new_val = value >> 8; + new_val |= (value & 0xFF) << 8; + printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + set_param(RADIO_PARAM_16BIT_ADDR, new_val); + if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } +} +/*---------------------------------------------------------------------------*/ +static void +test_64bit_addr(void) +{ + int i; + uint8_t new_val[8]; + + printf("====================================\n"); + printf("64-bit Address Test: Invert byte order\n"); + + printf("64-bit Address is: "); + if(get_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8) == RADIO_RESULT_OK) { + print_64bit_addr(ext_addr); + } + + for(i = 0; i <= 7; i++) { + new_val[7 - i] = ext_addr[i]; + } + + printf("Setting to : "); + print_64bit_addr(new_val); + + printf("64-bit Address is: "); + set_object(RADIO_PARAM_64BIT_ADDR, new_val, 8); + if(get_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8) == RADIO_RESULT_OK) { + print_64bit_addr(ext_addr); + } +} +/*---------------------------------------------------------------------------*/ +static void +print_rf_values(void) +{ + printf("====================================\n"); + printf("RF Values\n"); + + printf("Power: "); + if(get_param(RADIO_PARAM_POWER_MODE, &value) == RADIO_RESULT_OK) { + if(value == RADIO_POWER_MODE_ON) { + printf("On\n"); + } else if(value == RADIO_POWER_MODE_OFF) { + printf("Off\n"); + } + } + + printf("Channel: "); + if(get_param(RADIO_PARAM_CHANNEL, &value) == RADIO_RESULT_OK) { + printf("%d\n", value); + } + + printf("PAN ID: "); + if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } + + printf("16-bit Address: "); + if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { + printf("0x%02x%02x\n", value >> 8, value & 0xFF); + } + + printf("64-bit Address: "); + if(get_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8) == RADIO_RESULT_OK) { + print_64bit_addr(ext_addr); + } + + printf("RX Mode: "); + if(get_param(RADIO_PARAM_RX_MODE, &value) == RADIO_RESULT_OK) { + printf("Address Filtering is "); + if(value & RADIO_RX_MODE_ADDRESS_FILTER) { + printf("On, "); + } else { + printf("Off, "); + } + printf("Auto ACK is "); + if(value & RADIO_RX_MODE_AUTOACK) { + printf("On, "); + } else { + printf("Off, "); + } + + printf("(value=%d)\n", value); + } + + printf("TX Mode: "); + if(get_param(RADIO_PARAM_TX_MODE, &value) == RADIO_RESULT_OK) { + printf("%d\n", value); + } + + printf("TX Power: "); + if(get_param(RADIO_PARAM_TXPOWER, &value) == RADIO_RESULT_OK) { + printf("%d dBm [0x%04x]\n", value, (uint16_t)value); + } + + printf("CCA Threshold: "); + if(get_param(RADIO_PARAM_CCA_THRESHOLD, &value) == RADIO_RESULT_OK) { + printf("%d dBm [0x%04x]\n", value, (uint16_t)value); + } + + printf("RSSI: "); + if(get_param(RADIO_PARAM_RSSI, &value) == RADIO_RESULT_OK) { + printf("%d dBm [0x%04x]\n", value, (uint16_t)value); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(extended_rf_api_process, ev, data) +{ + + PROCESS_BEGIN(); + + get_rf_consts(); + print_rf_values(); + + test_off_on(); + test_channels(); + test_rx_modes(); + test_tx_powers(); + test_cca_thresholds(); + test_pan_id(); + test_16bit_addr(); + test_64bit_addr(); + + printf("Done\n"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/extended-rf-api/project-conf.h b/examples/extended-rf-api/project-conf.h new file mode 100644 index 000000000..2fc561e46 --- /dev/null +++ b/examples/extended-rf-api/project-conf.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, George Oikonomou (george@contiki-os.org) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver + +#endif /* PROJECT_CONF_H_ */ From 0327623ae1e54d3bdfe3f42b94f68eda050b1de4 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 15 Apr 2014 16:20:41 +0200 Subject: [PATCH 24/30] Minor update to improve output in extended RF API example. On 16 bit platforms, PAN id and short address might be negative when used as 16 bit signed integers. --- examples/extended-rf-api/extended-rf-api.c | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/extended-rf-api/extended-rf-api.c b/examples/extended-rf-api/extended-rf-api.c index 894ba0928..d02fe5546 100644 --- a/examples/extended-rf-api/extended-rf-api.c +++ b/examples/extended-rf-api/extended-rf-api.c @@ -334,23 +334,23 @@ test_pan_id(void) printf("PAN ID is: "); if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } - new_val = value >> 8; + new_val = (value >> 8) & 0xFF; new_val |= (value & 0xFF) << 8; - printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + printf("Switch to: 0x%02x%02x, Now: ", (new_val >> 8) & 0xFF, new_val & 0xFF); set_param(RADIO_PARAM_PAN_ID, new_val); if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } - new_val = value >> 8; + new_val = (value >> 8) & 0xFF; new_val |= (value & 0xFF) << 8; - printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + printf("Switch to: 0x%02x%02x, Now: ", (new_val >> 8) & 0xFF, new_val & 0xFF); set_param(RADIO_PARAM_PAN_ID, new_val); if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } } /*---------------------------------------------------------------------------*/ @@ -364,23 +364,23 @@ test_16bit_addr(void) printf("16-bit Address is: "); if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } - new_val = value >> 8; + new_val = (value >> 8) & 0xFF; new_val |= (value & 0xFF) << 8; - printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + printf("Switch to: 0x%02x%02x, Now: ", (new_val >> 8) & 0xFF, new_val & 0xFF); set_param(RADIO_PARAM_16BIT_ADDR, new_val); if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } - new_val = value >> 8; + new_val = (value >> 8) & 0xFF; new_val |= (value & 0xFF) << 8; - printf("Switch to: 0x%02x%02x, Now: ", new_val >> 8, new_val & 0xFF); + printf("Switch to: 0x%02x%02x, Now: ", (new_val >> 8) & 0xFF, new_val & 0xFF); set_param(RADIO_PARAM_16BIT_ADDR, new_val); if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } } /*---------------------------------------------------------------------------*/ @@ -434,12 +434,12 @@ print_rf_values(void) printf("PAN ID: "); if(get_param(RADIO_PARAM_PAN_ID, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } printf("16-bit Address: "); if(get_param(RADIO_PARAM_16BIT_ADDR, &value) == RADIO_RESULT_OK) { - printf("0x%02x%02x\n", value >> 8, value & 0xFF); + printf("0x%02x%02x\n", (value >> 8) & 0xFF, value & 0xFF); } printf("64-bit Address: "); From ceb868d934462a7038a8c5636f5b10c5b82edda7 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Tue, 15 Apr 2014 22:59:20 +0200 Subject: [PATCH 25/30] Modified project setup for er-rest-example and rest-example to use nullrdc and nullmac to reduce the code size. This allows the examples to compile on Tmote Sky again. --- examples/er-rest-example/project-conf.h | 8 ++++++-- examples/rest-example/project-conf.h | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/examples/er-rest-example/project-conf.h b/examples/er-rest-example/project-conf.h index 128ccd0b2..edaf10b71 100644 --- a/examples/er-rest-example/project-conf.h +++ b/examples/er-rest-example/project-conf.h @@ -35,11 +35,15 @@ /* Some platforms have weird includes. */ #undef IEEE802154_CONF_PANID -/* Disabling RDC for demo purposes. Core updates often require more memory. */ -/* For projects, optimize memory and enable RDC again. */ +/* Disabling RDC and CSMA for demo purposes. Core updates often + require more memory. */ +/* For projects, optimize memory and enable RDC and CSMA again. */ #undef NETSTACK_CONF_RDC #define NETSTACK_CONF_RDC nullrdc_driver +#undef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC nullmac_driver + /* Increase rpl-border-router IP-buffer when using more than 64. */ #undef REST_MAX_CHUNK_SIZE #define REST_MAX_CHUNK_SIZE 64 diff --git a/examples/rest-example/project-conf.h b/examples/rest-example/project-conf.h index ca93a92ec..7019c021a 100644 --- a/examples/rest-example/project-conf.h +++ b/examples/rest-example/project-conf.h @@ -32,6 +32,15 @@ #ifndef PROJECT_RPL_WEB_CONF_H_ #define PROJECT_RPL_WEB_CONF_H_ +/* Disabling RDC and CSMA for demo purposes. Core updates often + require more memory. */ +/* For projects, optimize memory and enable RDC and CSMA again. */ +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver + +#undef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC nullmac_driver + #ifndef QUEUEBUF_CONF_NUM #define QUEUEBUF_CONF_NUM 6 #endif From df81cbaed9c73785b543b0295090951452775060 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 18 Apr 2014 15:46:16 +0100 Subject: [PATCH 26/30] Simplify the extended RF API example --- examples/extended-rf-api/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/extended-rf-api/Makefile b/examples/extended-rf-api/Makefile index e11687f9f..53ef73cea 100644 --- a/examples/extended-rf-api/Makefile +++ b/examples/extended-rf-api/Makefile @@ -1,6 +1,3 @@ -UIP_CONF_IPV6=1 -UIP_CONF_RPL=1 - DEFINES+=PROJECT_CONF_H=\"project-conf.h\" CONTIKI_PROJECT = extended-rf-api From 3183805ba440de8b18d1d2ee42ae8f27576009ff Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 18 Apr 2014 14:41:45 +0100 Subject: [PATCH 27/30] Implement extended RF API for the CC2530 RF --- cpu/cc253x/dev/cc2530-rf.c | 346 ++++++++++++++++++++++++++++--- cpu/cc253x/dev/cc2530-rf.h | 3 - cpu/cc253x/sfr-bits.h | 3 + platform/cc2530dk/contiki-main.c | 27 ++- 4 files changed, 344 insertions(+), 35 deletions(-) diff --git a/cpu/cc253x/dev/cc2530-rf.c b/cpu/cc253x/dev/cc2530-rf.c index fe52d79c3..3bd769142 100644 --- a/cpu/cc253x/dev/cc2530-rf.c +++ b/cpu/cc253x/dev/cc2530-rf.c @@ -96,6 +96,10 @@ /* 192 ms, radio off -> on interval */ #define ONOFF_TIME RTIMER_ARCH_SECOND / 3125 +#define CC2530_RF_CHANNEL_SET_ERROR -1 + +#define CC2530_RF_TX_POWER_TXCTRL_MIN_VAL 0x09 /* Value for min TX Power */ +#define CC2530_RF_TX_POWER_TXCTRL_DEF_VAL 0x69 /* Reset Value */ /*---------------------------------------------------------------------------*/ #if CC2530_RF_CONF_HEXDUMP #include "dev/io-arch.h" @@ -114,50 +118,215 @@ static int on(void); /* prepare() needs our prototype */ static int off(void); /* transmit() needs our prototype */ static int channel_clear(void); /* transmit() needs our prototype */ /*---------------------------------------------------------------------------*/ -int8_t -cc2530_rf_channel_set(uint8_t channel) +/* TX Power dBm lookup table. Values from SmartRF Studio v1.16.0 */ +typedef struct output_config { + radio_value_t power; + uint8_t txpower_val; +} output_config_t; + +static const output_config_t output_power[] = { + { 5, 0xF5 }, /* 4.5 */ + { 3, 0xE5 }, /* 2.5 */ + { 1, 0xD5 }, + { 0, 0xC5 }, /* -0.5 */ + { -1, 0xB5 }, /* -1.5 */ + { -3, 0xA5 }, + { -4, 0x95 }, + { -6, 0x85 }, + { -8, 0x75 }, + {-10, 0x65 }, + {-12, 0x55 }, + {-14, 0x45 }, + {-16, 0x35 }, + {-18, 0x25 }, + {-20, 0x15 }, + {-22, 0x05 }, + {-28, 0x05 }, /* TXCTRL must be set to 0x09 */ +}; + +#define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) + +/* Max and Min Output Power in dBm */ +#define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].power) +#define OUTPUT_POWER_MAX (output_power[0].power) +/*---------------------------------------------------------------------------*/ +/** + * \brief Get the current operating channel + * \return Returns a value in [11,26] representing the current channel + */ +static uint8_t +get_channel() +{ + return (uint8_t)((FREQCTRL + 44) / 5); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the current operating channel + * \param channel The desired channel as a value in [11,26] + * \return Returns a value in [11,26] representing the current channel + * or a negative value if \e channel was out of bounds + */ +static int8_t +set_channel(uint8_t channel) { PUTSTRING("RF: Set Chan\n"); if((channel < CC2530_RF_CHANNEL_MIN) || (channel > CC2530_RF_CHANNEL_MAX)) { - return -1; + return CC2530_RF_CHANNEL_SET_ERROR; } + /* Changes to FREQCTRL take effect after the next recalibration */ /* Changes to FREQCTRL take effect after the next recalibration */ off(); FREQCTRL = (CC2530_RF_CHANNEL_MIN + (channel - CC2530_RF_CHANNEL_MIN) * CC2530_RF_CHANNEL_SPACING); on(); - return (int8_t) channel; + return (int8_t)channel; } /*---------------------------------------------------------------------------*/ -uint8_t -cc2530_rf_power_set(uint8_t new_power) +static radio_value_t +get_pan_id(void) { - PUTSTRING("RF: Set Power\n"); - /* off() */ - TXPOWER = new_power; - /* on() */ - - return TXPOWER; + return (radio_value_t)(PAN_ID1 << 8 | PAN_ID0); } /*---------------------------------------------------------------------------*/ -void -cc2530_rf_set_addr(uint16_t pan) +static void +set_pan_id(uint16_t pan) { -#if LINKADDR_SIZE==8 /* EXT_ADDR[7:0] is ignored when using short addresses */ - int i; - for(i = (LINKADDR_SIZE - 1); i >= 0; --i) { - ((uint8_t *)&EXT_ADDR0)[i] = linkaddr_node_addr.u8[LINKADDR_SIZE - 1 - i]; - } -#endif - PAN_ID0 = pan & 0xFF; PAN_ID1 = pan >> 8; +} +/*---------------------------------------------------------------------------*/ +static radio_value_t +get_short_addr(void) +{ + return (radio_value_t)(SHORT_ADDR1 << 8 | SHORT_ADDR0); +} +/*---------------------------------------------------------------------------*/ +static void +set_short_addr(uint16_t addr) +{ + SHORT_ADDR0 = addr & 0xFF; + SHORT_ADDR1 = addr >> 8; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Reads the current signal strength (RSSI) + * \return The current RSSI in dBm + * + * This function reads the current RSSI on the currently configured + * channel. + */ +static radio_value_t +get_rssi(void) +{ + int8_t rssi; - SHORT_ADDR0 = linkaddr_node_addr.u8[LINKADDR_SIZE - 1]; - SHORT_ADDR1 = linkaddr_node_addr.u8[LINKADDR_SIZE - 2]; + /* If we are off, turn on first */ + if(RXENABLE == 0) { + rf_flags |= WAS_OFF; + on(); + } + + /* Wait on RSSI_VALID */ + while((RSSISTAT & RSSISTAT_RSSI_VALID) == 0); + + rssi = (radio_value_t)RSSI - RSSI_OFFSET; + + /* If we were off, turn back off */ + if((rf_flags & WAS_OFF) == WAS_OFF) { + rf_flags &= ~WAS_OFF; + off(); + } + + return rssi; +} +/*---------------------------------------------------------------------------*/ +/* Returns the current CCA threshold in dBm */ +static radio_value_t +get_cca_threshold(void) +{ + return (int8_t)CCACTRL0 - RSSI_OFFSET; +} +/*---------------------------------------------------------------------------*/ +/* Sets the CCA threshold in dBm */ +static void +set_cca_threshold(radio_value_t value) +{ + CCACTRL0 = (value + RSSI_OFFSET) & 0xFF; +} +/*---------------------------------------------------------------------------*/ +/* Returns the current TX power in dBm */ +static radio_value_t +get_tx_power(void) +{ + int i; + uint8_t reg_val = TXPOWER; + + if(TXCTRL == CC2530_RF_TX_POWER_TXCTRL_MIN_VAL) { + return OUTPUT_POWER_MIN; + } + + /* + * Find the TXPOWER value in the lookup table + * If the value has been written with set_tx_power, we should be able to + * find the exact value. However, in case the register has been written in + * a different fashion, we return the immediately lower value of the lookup + */ + for(i = 0; i < OUTPUT_CONFIG_COUNT; i++) { + if(reg_val >= output_power[i].txpower_val) { + return output_power[i].power; + } + } + return OUTPUT_POWER_MIN; +} +/*---------------------------------------------------------------------------*/ +/* + * Set TX power to 'at least' power dBm + * This works with a lookup table. If the value of 'power' does not exist in + * the lookup table, TXPOWER will be set to the immediately higher available + * value + */ +static void +set_tx_power(radio_value_t power) +{ + int i; + + if(power <= output_power[OUTPUT_CONFIG_COUNT - 1].power) { + TXCTRL = CC2530_RF_TX_POWER_TXCTRL_MIN_VAL; + TXPOWER = output_power[OUTPUT_CONFIG_COUNT - 1].txpower_val; + return; + } + + for(i = OUTPUT_CONFIG_COUNT - 2; i >= 0; --i) { + if(power <= output_power[i].power) { + /* Perhaps an earlier call set TXCTRL to 0x09. Restore */ + TXCTRL = CC2530_RF_TX_POWER_TXCTRL_DEF_VAL; + TXPOWER = output_power[i].txpower_val; + return; + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_frame_filtering(uint8_t enable) +{ + if(enable) { + FRMFILT0 |= FRMFILT0_FRAME_FILTER_EN; + } else { + FRMFILT0 &= ~FRMFILT0_FRAME_FILTER_EN; + } +} +/*---------------------------------------------------------------------------*/ +static void +set_auto_ack(uint8_t enable) +{ + if(enable) { + FRMCTRL0 |= FRMCTRL0_AUTOACK; + } else { + FRMCTRL0 &= ~FRMCTRL0_AUTOACK; + } } /*---------------------------------------------------------------------------*/ /* Netstack API radio driver functions */ @@ -204,8 +373,7 @@ init(void) /* MAX FIFOP threshold */ FIFOPCTRL = CC2530_RF_MAX_PACKET_LEN; - cc2530_rf_power_set(CC2530_RF_TX_POWER); - cc2530_rf_channel_set(CC2530_RF_CHANNEL); + TXPOWER = CC2530_RF_TX_POWER; RF_TX_LED_OFF(); RF_RX_LED_OFF(); @@ -486,24 +654,148 @@ off(void) static radio_result_t get_value(radio_param_t param, radio_value_t *value) { - return RADIO_RESULT_NOT_SUPPORTED; + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch(param) { + case RADIO_PARAM_POWER_MODE: + *value = RXENABLE == 0 ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = (radio_value_t)get_channel(); + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + *value = get_pan_id(); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + *value = get_short_addr(); + return RADIO_RESULT_OK; + case RADIO_PARAM_RX_MODE: + *value = 0; + if(FRMFILT0 & FRMFILT0_FRAME_FILTER_EN) { + *value |= RADIO_RX_MODE_ADDRESS_FILTER; + } + if(FRMCTRL0 & FRMCTRL0_AUTOACK) { + *value |= RADIO_RX_MODE_AUTOACK; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + *value = get_tx_power(); + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + *value = get_cca_threshold(); + return RADIO_RESULT_OK; + case RADIO_PARAM_RSSI: + *value = get_rssi(); + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MIN: + *value = CC2530_RF_CHANNEL_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = CC2530_RF_CHANNEL_MAX; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MIN: + *value = OUTPUT_POWER_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = OUTPUT_POWER_MAX; + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } } /*---------------------------------------------------------------------------*/ static radio_result_t set_value(radio_param_t param, radio_value_t value) { - return RADIO_RESULT_NOT_SUPPORTED; + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + on(); + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < CC2530_RF_CHANNEL_MIN || value > CC2530_RF_CHANNEL_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + if(set_channel(value) == CC2530_RF_CHANNEL_SET_ERROR) { + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + set_pan_id(value & 0xffff); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + set_short_addr(value & 0xffff); + return RADIO_RESULT_OK; + case RADIO_PARAM_RX_MODE: + if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | + RADIO_RX_MODE_AUTOACK)) { + return RADIO_RESULT_INVALID_VALUE; + } + + set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0); + set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0); + + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + + set_tx_power(value); + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + set_cca_threshold(value); + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } } /*---------------------------------------------------------------------------*/ static radio_result_t get_object(radio_param_t param, void *dest, size_t size) { + uint8_t *target; + int i; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size != 8 || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + + target = dest; + for(i = 0; i < 8; i++) { + target[i] = ((uint8_t *)&EXT_ADDR0)[7 - i] & 0xFF; + } + + return RADIO_RESULT_OK; + } return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ static radio_result_t set_object(radio_param_t param, const void *src, size_t size) { + int i; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size != 8 || !src) { + return RADIO_RESULT_INVALID_VALUE; + } + + for(i = 0; i < 8; i++) { + ((uint8_t *)&EXT_ADDR0)[i] = ((uint8_t *)src)[7 - i]; + } + + return RADIO_RESULT_OK; + } return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc253x/dev/cc2530-rf.h b/cpu/cc253x/dev/cc2530-rf.h index f5722db5f..4e092ca7a 100644 --- a/cpu/cc253x/dev/cc2530-rf.h +++ b/cpu/cc253x/dev/cc2530-rf.h @@ -120,9 +120,6 @@ /*---------------------------------------------------------------------------*/ extern const struct radio_driver cc2530_rf_driver; /*---------------------------------------------------------------------------*/ -int8_t cc2530_rf_channel_set(uint8_t channel); -#define cc2530_rf_channel_get() ((uint8_t)((FREQCTRL + 44) / 5)) -uint8_t cc2530_rf_power_set(uint8_t new_power); void cc2530_rf_set_addr(uint16_t pan); /*---------------------------------------------------------------------------*/ #endif /* CC2530_RF_H_ */ diff --git a/cpu/cc253x/sfr-bits.h b/cpu/cc253x/sfr-bits.h index 7a4d72cac..09173cf18 100644 --- a/cpu/cc253x/sfr-bits.h +++ b/cpu/cc253x/sfr-bits.h @@ -184,6 +184,9 @@ /*--------------------------------------------------------------------------- * Radio Register Bits *---------------------------------------------------------------------------*/ +/* FRMFILT0 */ +#define FRMFILT0_FRAME_FILTER_EN 0x01 + /* FRMCTRL0 */ #define FRMCTRL0_APPEND_DATA_MODE 0x80 #define FRMCTRL0_AUTOCRC 0x40 diff --git a/platform/cc2530dk/contiki-main.c b/platform/cc2530dk/contiki-main.c index 7e63650f9..22f458da8 100644 --- a/platform/cc2530dk/contiki-main.c +++ b/platform/cc2530dk/contiki-main.c @@ -9,6 +9,7 @@ #include "dev/io-arch.h" #include "dev/dma.h" #include "dev/cc2530-rf.h" +#include "dev/radio.h" #include "dev/watchdog.h" #include "dev/clock-isr.h" #include "dev/port2.h" @@ -79,9 +80,11 @@ fade(int l) CC_NON_BANKED } /*---------------------------------------------------------------------------*/ static void -set_rime_addr(void) CC_NON_BANKED +set_rf_params(void) CC_NON_BANKED { char i; + uint16_t short_addr; + uint8_t ext_addr[8]; #if CC2530_CONF_MAC_FROM_PRIMARY __xdata unsigned char *macp = &X_IEEE_ADDR; @@ -114,8 +117,12 @@ set_rime_addr(void) CC_NON_BANKED FMAP = CC2530_LAST_FLASH_BANK; #endif - for(i = (LINKADDR_SIZE - 1); i >= 0; --i) { - linkaddr_node_addr.u8[i] = *macp; + /* + * Read IEEE address from flash, store in ext_addr. + * Invert endianness (from little to big endian) + */ + for(i = 7; i >= 0; --i) { + ext_addr[i] = *macp; macp++; } @@ -125,6 +132,12 @@ set_rime_addr(void) CC_NON_BANKED ENABLE_INTERRUPTS(); #endif + short_addr = ext_addr[7]; + short_addr |= ext_addr[6] << 8; + + /* Populate linkaddr_node_addr. Maintain endianness */ + memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); + /* Now the address is stored MSB first */ #if STARTUP_CONF_VERBOSE PUTSTRING("Rime configured with address "); @@ -136,7 +149,11 @@ set_rime_addr(void) CC_NON_BANKED PUTCHAR('\n'); #endif - cc2530_rf_set_addr(IEEE802154_PANID); + /* Write params to RF registers */ + NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); + NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); + NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2530_RF_CHANNEL); + NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); return; } /*---------------------------------------------------------------------------*/ @@ -235,7 +252,7 @@ main(void) CC_NON_BANKED /* initialize the netstack */ netstack_init(); - set_rime_addr(); + set_rf_params(); #if BUTTON_SENSOR_ON || ADC_SENSOR_ON process_start(&sensors_process, NULL); From 6028c0765fc305b6652f6c1295236618d4c12c5b Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Fri, 18 Apr 2014 18:00:11 +0100 Subject: [PATCH 28/30] Don't hardcode min and max TX power values --- cpu/cc2538/dev/cc2538-rf.c | 12 ++++++++---- cpu/cc2538/dev/cc2538-rf.h | 2 -- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index bedd92168..88a740a8c 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -150,6 +150,10 @@ static const output_config_t output_power[] = { }; #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) + +/* Max and Min Output Power in dBm */ +#define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].power) +#define OUTPUT_POWER_MAX (output_power[0].power) /*---------------------------------------------------------------------------*/ PROCESS(cc2538_rf_process, "cc2538 RF driver"); /*---------------------------------------------------------------------------*/ @@ -280,7 +284,7 @@ get_tx_power(void) return output_power[i].power; } } - return CC2538_RF_TX_POWER_MIN; + return OUTPUT_POWER_MIN; } /*---------------------------------------------------------------------------*/ /* @@ -797,10 +801,10 @@ get_value(radio_param_t param, radio_value_t *value) *value = CC2538_RF_CHANNEL_MAX; return RADIO_RESULT_OK; case RADIO_CONST_TXPOWER_MIN: - *value = CC2538_RF_TX_POWER_MIN; + *value = OUTPUT_POWER_MIN; return RADIO_RESULT_OK; case RADIO_CONST_TXPOWER_MAX: - *value = CC2538_RF_TX_POWER_MAX; + *value = OUTPUT_POWER_MAX; return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; @@ -847,7 +851,7 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: - if(value < CC2538_RF_TX_POWER_MIN || value > CC2538_RF_TX_POWER_MAX) { + if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { return RADIO_RESULT_INVALID_VALUE; } diff --git a/cpu/cc2538/dev/cc2538-rf.h b/cpu/cc2538/dev/cc2538-rf.h index 3606ce78f..5edb478ba 100644 --- a/cpu/cc2538/dev/cc2538-rf.h +++ b/cpu/cc2538/dev/cc2538-rf.h @@ -61,8 +61,6 @@ #define CC2538_RF_MIN_PACKET_LEN 4 #define CC2538_RF_CCA_CLEAR 1 #define CC2538_RF_CCA_BUSY 0 -#define CC2538_RF_TX_POWER_MIN -24 -#define CC2538_RF_TX_POWER_MAX 7 /*---------------------------------------------------------------------------*/ #ifdef CC2538_RF_CONF_TX_POWER #define CC2538_RF_TX_POWER CC2538_RF_CONF_TX_POWER From 49b6ad2af5018c6003ae961714ad981bf52e5a48 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Tue, 22 Apr 2014 18:21:43 +0100 Subject: [PATCH 29/30] Use the extended RF API for the cc2530 border router example --- examples/cc2530dk/border-router/border-router.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/cc2530dk/border-router/border-router.c b/examples/cc2530dk/border-router/border-router.c index bc3bb1ba4..0df514474 100644 --- a/examples/cc2530dk/border-router/border-router.c +++ b/examples/cc2530dk/border-router/border-router.c @@ -39,7 +39,7 @@ #include "dev/watchdog.h" #include "dev/slip.h" #include "dev/leds.h" -#include "dev/cc2530-rf.h" +#include "dev/radio.h" #include "debug.h" static uint8_t prefix_set; @@ -114,6 +114,16 @@ set_prefix_64(uip_ipaddr_t *prefix_64) } } /*---------------------------------------------------------------------------*/ +static uint8_t +get_rf_channel(void) +{ + radio_value_t chan; + + NETSTACK_RADIO.get_value(RADIO_PARAM_CHANNEL, &chan); + + return (uint8_t)chan; +} +/*---------------------------------------------------------------------------*/ PROCESS_THREAD(border_router_process, ev, data) { static struct etimer et; @@ -135,7 +145,7 @@ PROCESS_THREAD(border_router_process, ev, data) } /* We have created a new DODAG when we reach here */ PUTSTRING("On Channel "); - PUTDEC(cc2530_rf_channel_get()); + PUTDEC(get_rf_channel()); PUTCHAR('\n'); print_local_addresses(); From 08c884afa07a7d07ff0b59b63f242953d52c0c73 Mon Sep 17 00:00:00 2001 From: George Oikonomou Date: Tue, 22 Apr 2014 19:28:38 +0100 Subject: [PATCH 30/30] Improve the CC2538 extended RF API implementation * Decouple 64-bit address from LINKADDR_SIZE * get and set object from/to the start/end of the src/dest buffer * We expect size == 8 (rather than size < 8) for both get_ and set_object. Error otherwise * The RF no longer sets parameters by itself. We let the platform do this, using the extended API. --- cpu/cc2538/dev/cc2538-rf.c | 31 ++++++------------------------- platform/cc2538dk/contiki-main.c | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 88a740a8c..a43a5b0c2 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -872,13 +872,13 @@ get_object(radio_param_t param, void *dest, size_t size) int i; if(param == RADIO_PARAM_64BIT_ADDR) { - if(size < 8 || !dest || LINKADDR_SIZE != 8) { + if(size != 8 || !dest) { return RADIO_RESULT_INVALID_VALUE; } target = dest; - for(i = 0; i < size; i++) { - target[size - 1 - i] = ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] & 0xFF; + for(i = 0; i < 8; i++) { + target[i] = ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[7 - i] & 0xFF; } return RADIO_RESULT_OK; @@ -892,12 +892,12 @@ set_object(radio_param_t param, const void *src, size_t size) int i; if(param == RADIO_PARAM_64BIT_ADDR) { - if(size < 8 || !src || LINKADDR_SIZE != 8) { + if(size != 8 || !src) { return RADIO_RESULT_INVALID_VALUE; } - for(i = 0; i < size; i++) { - ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = ((uint8_t *)src)[size - 1 - i]; + for(i = 0; i < 8; i++) { + ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = ((uint8_t *)src)[7 - i]; } return RADIO_RESULT_OK; @@ -1022,23 +1022,4 @@ cc2538_rf_set_promiscous_mode(char p) set_frame_filtering(p); } /*---------------------------------------------------------------------------*/ -void -cc2538_rf_set_addr(uint16_t pan) -{ -#if LINKADDR_SIZE == 8 - /* EXT_ADDR[7:0] is ignored when using short addresses */ - int i; - - for(i = (LINKADDR_SIZE - 1); i >= 0; --i) { - ((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = - linkaddr_node_addr.u8[LINKADDR_SIZE - 1 - i]; - } -#endif - - set_pan_id(pan); - - REG(RFCORE_FFSM_SHORT_ADDR0) = linkaddr_node_addr.u8[LINKADDR_SIZE - 1]; - REG(RFCORE_FFSM_SHORT_ADDR1) = linkaddr_node_addr.u8[LINKADDR_SIZE - 2]; -} -/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/cc2538dk/contiki-main.c b/platform/cc2538dk/contiki-main.c index 9409fb460..e3fe5e342 100644 --- a/platform/cc2538dk/contiki-main.c +++ b/platform/cc2538dk/contiki-main.c @@ -103,9 +103,18 @@ fade(unsigned char l) } /*---------------------------------------------------------------------------*/ static void -set_rime_addr() +set_rf_params(void) { - ieee_addr_cpy_to(&linkaddr_node_addr.u8[0], LINKADDR_SIZE); + uint16_t short_addr; + uint8_t ext_addr[8]; + + ieee_addr_cpy_to(ext_addr, 8); + + short_addr = ext_addr[7]; + short_addr |= ext_addr[6] << 8; + + /* Populate linkaddr_node_addr. Maintain endianness */ + memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); #if STARTUP_CONF_VERBOSE { @@ -118,6 +127,10 @@ set_rime_addr() } #endif + NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); + NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); + NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2538_RF_CHANNEL); + NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); } /*---------------------------------------------------------------------------*/ /** @@ -185,9 +198,8 @@ main(void) process_start(&etimer_process, NULL); ctimer_init(); - set_rime_addr(); + set_rf_params(); netstack_init(); - cc2538_rf_set_addr(IEEE802154_PANID); #if UIP_CONF_IPV6 memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));