Merge pull request #617 from nfi/extended-radio-api

Extended radio API with support for setting channel, pan id, addressing modes, etc
This commit is contained in:
Adam Dunkels 2014-06-03 21:32:53 +02:00
commit 64f65b4e45
24 changed files with 2055 additions and 177 deletions

View file

@ -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
};
/*---------------------------------------------------------------------------*/

View file

@ -49,18 +49,183 @@
* Header file for the radio API
* \author
* Adam Dunkels <adam@sics.se>
* Joakim Eriksson <joakime@sics.se>
* Niclas Finne <nfi@sics.se>
* Nicolas Tsiftes <nvt@sics.se>
*/
#ifndef RADIO_H_
#define RADIO_H_
#include <stddef.h>
/**
* 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,
/*
* 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
* 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,
/*
* 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,
/*
* 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) */
/* 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
};
/* Radio power modes */
enum {
RADIO_POWER_MODE_OFF,
RADIO_POWER_MODE_ON
};
/**
* 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.
*
* To enable both address filter and transmissions of automatic
* acknowledgments:
*
* NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE,
* RADIO_RX_MODE_ADDRESS_FILTER | RADIO_RX_MODE_AUTOACK);
*/
#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 {
RADIO_RESULT_OK,
RADIO_RESULT_NOT_SUPPORTED,
RADIO_RESULT_INVALID_VALUE,
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.
*/
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,18 +253,30 @@ struct radio_driver {
/** Turn the radio off. */
int (* off)(void);
};
/* Generic radio return values. */
enum {
RADIO_TX_OK,
RADIO_TX_ERR,
RADIO_TX_COLLISION,
RADIO_TX_NOACK,
/** Get a radio parameter value. */
radio_result_t (* get_value)(radio_param_t param, radio_value_t *value);
/** Set a radio parameter value. */
radio_result_t (* set_value)(radio_param_t param, radio_value_t value);
/**
* 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 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);
};
#endif /* RADIO_H_ */
/** @} */
/** @} */

View file

@ -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;

View file

@ -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

View file

@ -126,10 +126,43 @@ 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))
/* 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");
/*---------------------------------------------------------------------------*/
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 +170,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 +194,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 +241,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 +252,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 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;
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 +442,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;
@ -638,6 +755,156 @@ 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)
{
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 = 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)
{
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 < 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] = ((uint32_t *)RFCORE_FFSM_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++) {
((uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = ((uint8_t *)src)[7 - i];
}
return RADIO_RESULT_OK;
}
return RADIO_RESULT_NOT_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
const struct radio_driver cc2538_rf_driver = {
init,
prepare,
@ -649,6 +916,10 @@ const struct radio_driver cc2538_rf_driver = {
pending_packet,
on,
off,
get_value,
set_value,
get_object,
set_object
};
/*---------------------------------------------------------------------------*/
/**
@ -748,11 +1019,7 @@ 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);
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -56,6 +56,7 @@
#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
@ -132,31 +133,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 +144,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 +154,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__ */

View file

@ -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();
@ -483,6 +651,154 @@ off(void)
return 1;
}
/*---------------------------------------------------------------------------*/
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 = 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)
{
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;
}
/*---------------------------------------------------------------------------*/
const struct radio_driver cc2530_rf_driver = {
init,
prepare,
@ -494,5 +810,9 @@ const struct radio_driver cc2530_rf_driver = {
pending_packet,
on,
off,
get_value,
set_value,
get_object,
set_object
};
/*---------------------------------------------------------------------------*/

View file

@ -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_ */

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -264,6 +264,147 @@ 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_RX_MODE:
*value = 0;
if(ST_RadioAddressFilteringEnabled()) {
*value |= RADIO_RX_MODE_ADDRESS_FILTER;
}
if(ST_RadioAutoAckEnabled()) {
*value |= RADIO_RX_MODE_AUTOACK;
}
return RADIO_RESULT_OK;
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;
case RADIO_CONST_CHANNEL_MIN:
*value = ST_MIN_802_15_4_CHANNEL_NUMBER;
return RADIO_RESULT_OK;
case RADIO_CONST_CHANNEL_MAX:
*value = ST_MAX_802_15_4_CHANNEL_NUMBER;
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 < 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) {
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_RX_MODE:
if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
RADIO_RX_MODE_AUTOACK)) {
return RADIO_RESULT_INVALID_VALUE;
}
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 > MAX_RADIO_POWER) {
return RADIO_RESULT_INVALID_VALUE;
}
if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) {
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;
}
}
/*--------------------------------------------------------------------------*/
static radio_result_t
get_object(radio_param_t param, void *dest, size_t size)
{
const uint8_t *eui64;
uint8_t *target;
int i;
if(param == RADIO_PARAM_64BIT_ADDR) {
if(size < 8 || !dest) {
return RADIO_RESULT_INVALID_VALUE;
}
eui64 = ST_RadioGetEui64();
if(!eui64) {
return RADIO_RESULT_ERROR;
}
target = dest;
for(i = 0; i < 8; i++) {
target[i] = eui64[7 - i];
}
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 +417,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

View file

@ -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 <stdio.h>
@ -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 */
@ -112,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 { \
@ -148,6 +173,107 @@ 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)
{
int i, v;
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_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;
}
}
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) {
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;
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) {
break;
}
}
cc2420_set_txpower(output_power[i - 1].config);
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 +288,18 @@ 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
strobe(enum cc2420_register regname)
{
CC2420_STROBE(regname);
}
/*---------------------------------------------------------------------------*/
static void
@ -185,15 +317,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
@ -204,6 +333,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
@ -212,7 +353,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;
@ -224,7 +365,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);
@ -265,6 +406,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;
@ -351,7 +498,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 */
@ -366,8 +512,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.
@ -383,7 +527,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);
@ -396,7 +540,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);
}
}
@ -413,7 +557,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());
@ -560,10 +704,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);
@ -590,22 +734,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();
}
@ -620,7 +764,7 @@ cc2420_interrupt(void)
process_poll(&cc2420_process);
last_packet_timestamp = cc2420_sfd_start_time;
pending++;
/* pending++; */
cc2420_packets_seen++;
return 1;
}
@ -665,7 +809,7 @@ cc2420_read(void *buf, unsigned short bufsize)
return 0;
}*/
pending = 0;
/* pending = 0; */
GET_LOCK();
@ -781,7 +925,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));
@ -800,19 +944,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)
{
@ -842,7 +973,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;

View file

@ -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

View file

@ -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();

View file

@ -54,8 +54,9 @@
#define UIP_CONF_BUFFER_SIZE 256
*/
/* 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
@ -63,6 +64,9 @@
#undef UIP_CONF_TCP
#define UIP_CONF_TCP 0
#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 48

View file

@ -0,0 +1,8 @@
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
CONTIKI_PROJECT = extended-rf-api
all: $(CONTIKI_PROJECT)
CONTIKI = ../..
include $(CONTIKI)/Makefile.include

View file

@ -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 <stdio.h>
#include <stdint.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
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) & 0xFF, value & 0xFF);
}
new_val = (value >> 8) & 0xFF;
new_val |= (value & 0xFF) << 8;
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) & 0xFF, value & 0xFF);
}
new_val = (value >> 8) & 0xFF;
new_val |= (value & 0xFF) << 8;
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) & 0xFF, 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) & 0xFF, value & 0xFF);
}
new_val = (value >> 8) & 0xFF;
new_val |= (value & 0xFF) << 8;
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) & 0xFF, value & 0xFF);
}
new_val = (value >> 8) & 0xFF;
new_val |= (value & 0xFF) << 8;
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) & 0xFF, 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) & 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) & 0xFF, 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();
}
/*---------------------------------------------------------------------------*/

View file

@ -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_ */

View file

@ -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

View file

@ -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);

View file

@ -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);
}
/*---------------------------------------------------------------------------*/
/**
@ -186,9 +199,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));

View file

@ -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,

View file

@ -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
};
/*---------------------------------------------------------------------------*/