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:
commit
64f65b4e45
|
@ -28,7 +28,7 @@ send(const void *payload, unsigned short payload_len)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
read(void *buf, unsigned short buf_len)
|
radio_read(void *buf, unsigned short buf_len)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -63,17 +63,45 @@ off(void)
|
||||||
return 0;
|
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 =
|
const struct radio_driver nullradio_driver =
|
||||||
{
|
{
|
||||||
init,
|
init,
|
||||||
prepare,
|
prepare,
|
||||||
transmit,
|
transmit,
|
||||||
send,
|
send,
|
||||||
read,
|
radio_read,
|
||||||
channel_clear,
|
channel_clear,
|
||||||
receiving_packet,
|
receiving_packet,
|
||||||
pending_packet,
|
pending_packet,
|
||||||
on,
|
on,
|
||||||
off,
|
off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
193
core/dev/radio.h
193
core/dev/radio.h
|
@ -49,11 +49,176 @@
|
||||||
* Header file for the radio API
|
* Header file for the radio API
|
||||||
* \author
|
* \author
|
||||||
* Adam Dunkels <adam@sics.se>
|
* Adam Dunkels <adam@sics.se>
|
||||||
|
* Joakim Eriksson <joakime@sics.se>
|
||||||
|
* Niclas Finne <nfi@sics.se>
|
||||||
|
* Nicolas Tsiftes <nvt@sics.se>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RADIO_H_
|
#ifndef RADIO_H_
|
||||||
#define 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.
|
* The structure of a device driver for a radio in Contiki.
|
||||||
*/
|
*/
|
||||||
|
@ -88,18 +253,30 @@ struct radio_driver {
|
||||||
|
|
||||||
/** Turn the radio off. */
|
/** Turn the radio off. */
|
||||||
int (* off)(void);
|
int (* off)(void);
|
||||||
};
|
|
||||||
|
|
||||||
/* Generic radio return values. */
|
/** Get a radio parameter value. */
|
||||||
enum {
|
radio_result_t (* get_value)(radio_param_t param, radio_value_t *value);
|
||||||
RADIO_TX_OK,
|
|
||||||
RADIO_TX_ERR,
|
/** Set a radio parameter value. */
|
||||||
RADIO_TX_COLLISION,
|
radio_result_t (* set_value)(radio_param_t param, radio_value_t value);
|
||||||
RADIO_TX_NOACK,
|
|
||||||
|
/**
|
||||||
|
* 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_ */
|
#endif /* RADIO_H_ */
|
||||||
|
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -252,6 +252,31 @@ static int rf230_cca(void);
|
||||||
|
|
||||||
uint8_t rf230_last_correlation,rf230_last_rssi,rf230_smallest_rssi;
|
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 =
|
const struct radio_driver rf230_driver =
|
||||||
{
|
{
|
||||||
rf230_init,
|
rf230_init,
|
||||||
|
@ -263,7 +288,11 @@ const struct radio_driver rf230_driver =
|
||||||
rf230_receiving_packet,
|
rf230_receiving_packet,
|
||||||
rf230_pending_packet,
|
rf230_pending_packet,
|
||||||
rf230_on,
|
rf230_on,
|
||||||
rf230_off
|
rf230_off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t RF230_receive_on;
|
uint8_t RF230_receive_on;
|
||||||
|
|
|
@ -686,6 +686,30 @@ off(void)
|
||||||
return 1;
|
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 = {
|
const struct radio_driver cc2430_rf_driver = {
|
||||||
init,
|
init,
|
||||||
prepare,
|
prepare,
|
||||||
|
@ -697,6 +721,10 @@ const struct radio_driver cc2430_rf_driver = {
|
||||||
pending_packet,
|
pending_packet,
|
||||||
on,
|
on,
|
||||||
off,
|
off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if !NETSTACK_CONF_SHORTCUTS
|
#if !NETSTACK_CONF_SHORTCUTS
|
||||||
|
|
|
@ -126,10 +126,43 @@ static uint8_t rf_flags;
|
||||||
static int on(void);
|
static int on(void);
|
||||||
static int off(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");
|
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;
|
uint8_t chan = REG(RFCORE_XREG_FREQCTRL) & RFCORE_XREG_FREQCTRL_FREQ;
|
||||||
|
|
||||||
|
@ -137,13 +170,19 @@ cc2538_rf_channel_get()
|
||||||
+ CC2538_RF_CHANNEL_MIN);
|
+ 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");
|
PRINTF("RF: Set Channel\n");
|
||||||
|
|
||||||
if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) {
|
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 */
|
/* Changes to FREQCTRL take effect after the next recalibration */
|
||||||
|
@ -155,41 +194,43 @@ cc2538_rf_channel_set(uint8_t channel)
|
||||||
return (int8_t) channel;
|
return (int8_t) channel;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
uint8_t
|
static radio_value_t
|
||||||
cc2538_rf_power_set(uint8_t new_power)
|
get_pan_id(void)
|
||||||
{
|
{
|
||||||
PRINTF("RF: Set Power\n");
|
return (radio_value_t)(REG(RFCORE_FFSM_PAN_ID1) << 8 | REG(RFCORE_FFSM_PAN_ID0));
|
||||||
|
|
||||||
REG(RFCORE_XREG_TXPOWER) = new_power;
|
|
||||||
|
|
||||||
return (REG(RFCORE_XREG_TXPOWER) & 0xFF);
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* ToDo: Check once we have info on the... infopage */
|
static void
|
||||||
void
|
set_pan_id(uint16_t pan)
|
||||||
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
|
|
||||||
|
|
||||||
REG(RFCORE_FFSM_PAN_ID0) = pan & 0xFF;
|
REG(RFCORE_FFSM_PAN_ID0) = pan & 0xFF;
|
||||||
REG(RFCORE_FFSM_PAN_ID1) = pan >> 8;
|
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
|
static radio_value_t
|
||||||
cc2538_rf_read_rssi(void)
|
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 we are off, turn on first */
|
||||||
if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) {
|
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 */
|
/* Wait on RSSI_VALID */
|
||||||
while((REG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0);
|
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 we were off, turn back off */
|
||||||
if((rf_flags & WAS_OFF) == WAS_OFF) {
|
if((rf_flags & WAS_OFF) == WAS_OFF) {
|
||||||
|
@ -211,6 +252,80 @@ cc2538_rf_read_rssi(void)
|
||||||
return rssi;
|
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 */
|
/* Netstack API radio driver functions */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
|
@ -327,8 +442,10 @@ init(void)
|
||||||
/* MAX FIFOP threshold */
|
/* MAX FIFOP threshold */
|
||||||
REG(RFCORE_XREG_FIFOPCTRL) = CC2538_RF_MAX_PACKET_LEN;
|
REG(RFCORE_XREG_FIFOPCTRL) = CC2538_RF_MAX_PACKET_LEN;
|
||||||
|
|
||||||
cc2538_rf_power_set(CC2538_RF_TX_POWER);
|
/* Set TX Power */
|
||||||
cc2538_rf_channel_set(CC2538_RF_CHANNEL);
|
REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER;
|
||||||
|
|
||||||
|
set_channel(CC2538_RF_CHANNEL);
|
||||||
|
|
||||||
/* Acknowledge RF interrupts, FIFOP only */
|
/* Acknowledge RF interrupts, FIFOP only */
|
||||||
REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP;
|
REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP;
|
||||||
|
@ -638,6 +755,156 @@ pending_packet(void)
|
||||||
return (REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP);
|
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 = {
|
const struct radio_driver cc2538_rf_driver = {
|
||||||
init,
|
init,
|
||||||
prepare,
|
prepare,
|
||||||
|
@ -649,6 +916,10 @@ const struct radio_driver cc2538_rf_driver = {
|
||||||
pending_packet,
|
pending_packet,
|
||||||
on,
|
on,
|
||||||
off,
|
off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
|
@ -748,11 +1019,7 @@ cc2538_rf_err_isr(void)
|
||||||
void
|
void
|
||||||
cc2538_rf_set_promiscous_mode(char p)
|
cc2538_rf_set_promiscous_mode(char p)
|
||||||
{
|
{
|
||||||
if(p) {
|
set_frame_filtering(p);
|
||||||
REG(RFCORE_XREG_FRMFILT0) &= ~RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN;
|
|
||||||
} else {
|
|
||||||
REG(RFCORE_XREG_FRMFILT0) |= RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#define CC2538_RF_CHANNEL_MIN 11
|
#define CC2538_RF_CHANNEL_MIN 11
|
||||||
#define CC2538_RF_CHANNEL_MAX 26
|
#define CC2538_RF_CHANNEL_MAX 26
|
||||||
#define CC2538_RF_CHANNEL_SPACING 5
|
#define CC2538_RF_CHANNEL_SPACING 5
|
||||||
|
#define CC2538_RF_CHANNEL_SET_ERROR -1
|
||||||
#define CC2538_RF_MAX_PACKET_LEN 127
|
#define CC2538_RF_MAX_PACKET_LEN 127
|
||||||
#define CC2538_RF_MIN_PACKET_LEN 4
|
#define CC2538_RF_MIN_PACKET_LEN 4
|
||||||
#define CC2538_RF_CCA_CLEAR 1
|
#define CC2538_RF_CCA_CLEAR 1
|
||||||
|
@ -132,31 +133,6 @@
|
||||||
/** The NETSTACK data structure for the cc2538 RF driver */
|
/** The NETSTACK data structure for the cc2538 RF driver */
|
||||||
extern const struct radio_driver 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
|
* \brief Sets addresses and PAN identifier to the relevant RF hardware
|
||||||
* registers
|
* registers
|
||||||
|
@ -168,15 +144,6 @@ uint8_t cc2538_rf_power_set(uint8_t new_power);
|
||||||
*/
|
*/
|
||||||
void cc2538_rf_set_addr(uint16_t pan);
|
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
|
* \brief Turn promiscous mode on or off
|
||||||
* \param p If promiscous mode should be on (1) or off (0)
|
* \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.
|
* address as the receive address are returned from the RF core.
|
||||||
*/
|
*/
|
||||||
void cc2538_rf_set_promiscous_mode(char p);
|
void cc2538_rf_set_promiscous_mode(char p);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#endif /* CC2538_RF_H__ */
|
#endif /* CC2538_RF_H__ */
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,10 @@
|
||||||
/* 192 ms, radio off -> on interval */
|
/* 192 ms, radio off -> on interval */
|
||||||
#define ONOFF_TIME RTIMER_ARCH_SECOND / 3125
|
#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
|
#if CC2530_RF_CONF_HEXDUMP
|
||||||
#include "dev/io-arch.h"
|
#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 off(void); /* transmit() needs our prototype */
|
||||||
static int channel_clear(void); /* transmit() needs our prototype */
|
static int channel_clear(void); /* transmit() needs our prototype */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int8_t
|
/* TX Power dBm lookup table. Values from SmartRF Studio v1.16.0 */
|
||||||
cc2530_rf_channel_set(uint8_t channel)
|
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");
|
PUTSTRING("RF: Set Chan\n");
|
||||||
|
|
||||||
if((channel < CC2530_RF_CHANNEL_MIN) || (channel > CC2530_RF_CHANNEL_MAX)) {
|
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 */
|
/* Changes to FREQCTRL take effect after the next recalibration */
|
||||||
off();
|
off();
|
||||||
FREQCTRL = (CC2530_RF_CHANNEL_MIN
|
FREQCTRL = (CC2530_RF_CHANNEL_MIN
|
||||||
+ (channel - CC2530_RF_CHANNEL_MIN) * CC2530_RF_CHANNEL_SPACING);
|
+ (channel - CC2530_RF_CHANNEL_MIN) * CC2530_RF_CHANNEL_SPACING);
|
||||||
on();
|
on();
|
||||||
|
|
||||||
return (int8_t) channel;
|
return (int8_t)channel;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
uint8_t
|
static radio_value_t
|
||||||
cc2530_rf_power_set(uint8_t new_power)
|
get_pan_id(void)
|
||||||
{
|
{
|
||||||
PUTSTRING("RF: Set Power\n");
|
return (radio_value_t)(PAN_ID1 << 8 | PAN_ID0);
|
||||||
/* off() */
|
|
||||||
TXPOWER = new_power;
|
|
||||||
/* on() */
|
|
||||||
|
|
||||||
return TXPOWER;
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
static void
|
||||||
cc2530_rf_set_addr(uint16_t pan)
|
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_ID0 = pan & 0xFF;
|
||||||
PAN_ID1 = pan >> 8;
|
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];
|
/* If we are off, turn on first */
|
||||||
SHORT_ADDR1 = linkaddr_node_addr.u8[LINKADDR_SIZE - 2];
|
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 */
|
/* Netstack API radio driver functions */
|
||||||
|
@ -204,8 +373,7 @@ init(void)
|
||||||
/* MAX FIFOP threshold */
|
/* MAX FIFOP threshold */
|
||||||
FIFOPCTRL = CC2530_RF_MAX_PACKET_LEN;
|
FIFOPCTRL = CC2530_RF_MAX_PACKET_LEN;
|
||||||
|
|
||||||
cc2530_rf_power_set(CC2530_RF_TX_POWER);
|
TXPOWER = CC2530_RF_TX_POWER;
|
||||||
cc2530_rf_channel_set(CC2530_RF_CHANNEL);
|
|
||||||
|
|
||||||
RF_TX_LED_OFF();
|
RF_TX_LED_OFF();
|
||||||
RF_RX_LED_OFF();
|
RF_RX_LED_OFF();
|
||||||
|
@ -483,6 +651,154 @@ off(void)
|
||||||
return 1;
|
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 = {
|
const struct radio_driver cc2530_rf_driver = {
|
||||||
init,
|
init,
|
||||||
prepare,
|
prepare,
|
||||||
|
@ -494,5 +810,9 @@ const struct radio_driver cc2530_rf_driver = {
|
||||||
pending_packet,
|
pending_packet,
|
||||||
on,
|
on,
|
||||||
off,
|
off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -120,9 +120,6 @@
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
extern const struct radio_driver cc2530_rf_driver;
|
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);
|
void cc2530_rf_set_addr(uint16_t pan);
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#endif /* CC2530_RF_H_ */
|
#endif /* CC2530_RF_H_ */
|
||||||
|
|
|
@ -184,6 +184,9 @@
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
* Radio Register Bits
|
* Radio Register Bits
|
||||||
*---------------------------------------------------------------------------*/
|
*---------------------------------------------------------------------------*/
|
||||||
|
/* FRMFILT0 */
|
||||||
|
#define FRMFILT0_FRAME_FILTER_EN 0x01
|
||||||
|
|
||||||
/* FRMCTRL0 */
|
/* FRMCTRL0 */
|
||||||
#define FRMCTRL0_APPEND_DATA_MODE 0x80
|
#define FRMCTRL0_APPEND_DATA_MODE 0x80
|
||||||
#define FRMCTRL0_AUTOCRC 0x40
|
#define FRMCTRL0_AUTOCRC 0x40
|
||||||
|
|
|
@ -79,6 +79,31 @@ int contiki_maca_channel_clear(void);
|
||||||
int contiki_maca_receiving_packet(void);
|
int contiki_maca_receiving_packet(void);
|
||||||
int contiki_maca_pending_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 =
|
const struct radio_driver contiki_maca_driver =
|
||||||
{
|
{
|
||||||
.init = contiki_maca_init,
|
.init = contiki_maca_init,
|
||||||
|
@ -91,6 +116,10 @@ const struct radio_driver contiki_maca_driver =
|
||||||
.channel_clear = contiki_maca_channel_clear,
|
.channel_clear = contiki_maca_channel_clear,
|
||||||
.on = contiki_maca_on_request,
|
.on = contiki_maca_on_request,
|
||||||
.off = contiki_maca_off_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;
|
static volatile uint8_t contiki_maca_request_on = 0;
|
||||||
|
|
|
@ -45,6 +45,31 @@
|
||||||
static unsigned char tx_buf[ADF7023_MAX_PACKET_SIZE];
|
static unsigned char tx_buf[ADF7023_MAX_PACKET_SIZE];
|
||||||
static unsigned char rx_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 = {
|
const struct radio_driver adf7023_driver = {
|
||||||
|
|
||||||
.init = adf7023_init,
|
.init = adf7023_init,
|
||||||
|
@ -76,6 +101,11 @@ const struct radio_driver adf7023_driver = {
|
||||||
|
|
||||||
/** Turn the radio off. */
|
/** Turn the radio off. */
|
||||||
.off = adf7023_off,
|
.off = adf7023_off,
|
||||||
|
|
||||||
|
.get_value = get_value,
|
||||||
|
.set_value = set_value,
|
||||||
|
.get_object = get_object,
|
||||||
|
.set_object = set_object
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -264,6 +264,147 @@ static int stm32w_radio_off(void);
|
||||||
static int add_to_rxbuf(uint8_t * src);
|
static int add_to_rxbuf(uint8_t * src);
|
||||||
|
|
||||||
static int read_from_rxbuf(void *dest, unsigned short len);
|
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 = {
|
const struct radio_driver stm32w_radio_driver = {
|
||||||
stm32w_radio_init,
|
stm32w_radio_init,
|
||||||
|
@ -276,6 +417,10 @@ const struct radio_driver stm32w_radio_driver = {
|
||||||
stm32w_radio_pending_packet,
|
stm32w_radio_pending_packet,
|
||||||
stm32w_radio_on,
|
stm32w_radio_on,
|
||||||
stm32w_radio_off,
|
stm32w_radio_off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -84,6 +84,9 @@
|
||||||
#define FOOTER1_CRC_OK 0x80
|
#define FOOTER1_CRC_OK 0x80
|
||||||
#define FOOTER1_CORRELATION 0x7f
|
#define FOOTER1_CORRELATION 0x7f
|
||||||
|
|
||||||
|
/* The RSSI_OFFSET is approximate -45 (see CC2420 specification) */
|
||||||
|
#define RSSI_OFFSET -45
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -103,6 +106,28 @@
|
||||||
#define LEDS_OFF(x)
|
#define LEDS_OFF(x)
|
||||||
#endif
|
#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);
|
void cc2420_arch_init(void);
|
||||||
|
|
||||||
/* XXX hack: these will be made as Chameleon packet attributes */
|
/* 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;
|
int cc2420_packets_seen, cc2420_packets_read;
|
||||||
|
|
||||||
static uint8_t volatile pending;
|
/* static uint8_t volatile pending; */
|
||||||
|
|
||||||
#define BUSYWAIT_UNTIL(cond, max_time) \
|
#define BUSYWAIT_UNTIL(cond, max_time) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -148,6 +173,107 @@ static int cc2420_cca(void);
|
||||||
signed char cc2420_last_rssi;
|
signed char cc2420_last_rssi;
|
||||||
uint8_t cc2420_last_correlation;
|
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 =
|
const struct radio_driver cc2420_driver =
|
||||||
{
|
{
|
||||||
cc2420_init,
|
cc2420_init,
|
||||||
|
@ -162,12 +288,18 @@ const struct radio_driver cc2420_driver =
|
||||||
pending_packet,
|
pending_packet,
|
||||||
cc2420_on,
|
cc2420_on,
|
||||||
cc2420_off,
|
cc2420_off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t receive_on;
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
static int channel;
|
strobe(enum cc2420_register regname)
|
||||||
|
{
|
||||||
|
CC2420_STROBE(regname);
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -185,15 +317,12 @@ flushrx(void)
|
||||||
{
|
{
|
||||||
uint8_t dummy;
|
uint8_t dummy;
|
||||||
|
|
||||||
CC2420_READ_FIFO_BYTE(dummy);
|
getrxbyte(&dummy);
|
||||||
CC2420_STROBE(CC2420_SFLUSHRX);
|
strobe(CC2420_SFLUSHRX);
|
||||||
CC2420_STROBE(CC2420_SFLUSHRX);
|
strobe(CC2420_SFLUSHRX);
|
||||||
}
|
if(dummy) {
|
||||||
/*---------------------------------------------------------------------------*/
|
/* avoid unused variable compiler warning */
|
||||||
static void
|
}
|
||||||
strobe(enum cc2420_register regname)
|
|
||||||
{
|
|
||||||
CC2420_STROBE(regname);
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static unsigned int
|
static unsigned int
|
||||||
|
@ -204,6 +333,18 @@ status(void)
|
||||||
return status;
|
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 uint8_t locked, lock_on, lock_off;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -212,7 +353,7 @@ on(void)
|
||||||
CC2420_ENABLE_FIFOP_INT();
|
CC2420_ENABLE_FIFOP_INT();
|
||||||
strobe(CC2420_SRXON);
|
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);
|
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
||||||
receive_on = 1;
|
receive_on = 1;
|
||||||
|
@ -224,7 +365,7 @@ off(void)
|
||||||
receive_on = 0;
|
receive_on = 0;
|
||||||
|
|
||||||
/* Wait for transmission to end before turning radio off. */
|
/* 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);
|
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||||
strobe(CC2420_SRFOFF);
|
strobe(CC2420_SRFOFF);
|
||||||
|
@ -265,6 +406,12 @@ setreg(enum cc2420_register regname, unsigned value)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
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)
|
set_txpower(uint8_t power)
|
||||||
{
|
{
|
||||||
uint16_t reg;
|
uint16_t reg;
|
||||||
|
@ -351,7 +498,6 @@ static int
|
||||||
cc2420_transmit(unsigned short payload_len)
|
cc2420_transmit(unsigned short payload_len)
|
||||||
{
|
{
|
||||||
int i, txpower;
|
int i, txpower;
|
||||||
uint8_t total_len;
|
|
||||||
#if CC2420_CONF_CHECKSUM
|
#if CC2420_CONF_CHECKSUM
|
||||||
uint16_t checksum;
|
uint16_t checksum;
|
||||||
#endif /* CC2420_CONF_CHECKSUM */
|
#endif /* CC2420_CONF_CHECKSUM */
|
||||||
|
@ -366,8 +512,6 @@ cc2420_transmit(unsigned short payload_len)
|
||||||
set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
|
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
|
/* The TX FIFO can only hold one packet. Make sure to not overrun
|
||||||
* FIFO by waiting for transmission to start here and synchronizing
|
* FIFO by waiting for transmission to start here and synchronizing
|
||||||
* with the CC2420_TX_ACTIVE check in cc2420_send.
|
* with the CC2420_TX_ACTIVE check in cc2420_send.
|
||||||
|
@ -383,7 +527,7 @@ cc2420_transmit(unsigned short payload_len)
|
||||||
|
|
||||||
#if WITH_SEND_CCA
|
#if WITH_SEND_CCA
|
||||||
strobe(CC2420_SRXON);
|
strobe(CC2420_SRXON);
|
||||||
BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10);
|
wait_for_status(BV(CC2420_RSSI_VALID));
|
||||||
strobe(CC2420_STXONCCA);
|
strobe(CC2420_STXONCCA);
|
||||||
#else /* WITH_SEND_CCA */
|
#else /* WITH_SEND_CCA */
|
||||||
strobe(CC2420_STXON);
|
strobe(CC2420_STXON);
|
||||||
|
@ -396,7 +540,7 @@ cc2420_transmit(unsigned short payload_len)
|
||||||
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
||||||
PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
|
PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
|
||||||
/* Write timestamp to last two bytes of packet in TXFIFO. */
|
/* 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);
|
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
|
||||||
/* We wait until transmission has ended so that we get an
|
/* We wait until transmission has ended so that we get an
|
||||||
accurate measurement of the transmission time.*/
|
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
|
#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
|
||||||
ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
|
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.
|
* 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. */
|
/* 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);
|
setreg(CC2420_FSCTRL, f);
|
||||||
|
|
||||||
|
@ -590,22 +734,22 @@ cc2420_set_pan_addr(unsigned pan,
|
||||||
/*
|
/*
|
||||||
* Writing RAM requires crystal oscillator to be stable.
|
* 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[0] = pan & 0xff;
|
||||||
tmp[1] = pan >> 8;
|
tmp[1] = pan >> 8;
|
||||||
CC2420_WRITE_RAM(&tmp, CC2420RAM_PANID, 2);
|
write_ram(&tmp, CC2420RAM_PANID, 2);
|
||||||
|
|
||||||
tmp[0] = addr & 0xff;
|
tmp[0] = addr & 0xff;
|
||||||
tmp[1] = addr >> 8;
|
tmp[1] = addr >> 8;
|
||||||
CC2420_WRITE_RAM(&tmp, CC2420RAM_SHORTADDR, 2);
|
write_ram(&tmp, CC2420RAM_SHORTADDR, 2);
|
||||||
if(ieee_addr != NULL) {
|
if(ieee_addr != NULL) {
|
||||||
uint8_t tmp_addr[8];
|
uint8_t tmp_addr[8];
|
||||||
/* LSB first, MSB last for 802.15.4 addresses in CC2420 */
|
/* LSB first, MSB last for 802.15.4 addresses in CC2420 */
|
||||||
for (f = 0; f < 8; f++) {
|
for (f = 0; f < 8; f++) {
|
||||||
tmp_addr[7 - f] = ieee_addr[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();
|
RELEASE_LOCK();
|
||||||
}
|
}
|
||||||
|
@ -620,7 +764,7 @@ cc2420_interrupt(void)
|
||||||
process_poll(&cc2420_process);
|
process_poll(&cc2420_process);
|
||||||
|
|
||||||
last_packet_timestamp = cc2420_sfd_start_time;
|
last_packet_timestamp = cc2420_sfd_start_time;
|
||||||
pending++;
|
/* pending++; */
|
||||||
cc2420_packets_seen++;
|
cc2420_packets_seen++;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -665,7 +809,7 @@ cc2420_read(void *buf, unsigned short bufsize)
|
||||||
return 0;
|
return 0;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
pending = 0;
|
/* pending = 0; */
|
||||||
|
|
||||||
GET_LOCK();
|
GET_LOCK();
|
||||||
|
|
||||||
|
@ -781,7 +925,7 @@ cc2420_rssi(void)
|
||||||
radio_was_off = 1;
|
radio_was_off = 1;
|
||||||
cc2420_on();
|
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));
|
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
|
static int
|
||||||
cc2420_cca(void)
|
cc2420_cca(void)
|
||||||
{
|
{
|
||||||
|
@ -842,7 +973,7 @@ cc2420_cca(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
|
wait_for_status(BV(CC2420_RSSI_VALID));
|
||||||
|
|
||||||
cca = CC2420_CCA_IS_1;
|
cca = CC2420_CCA_IS_1;
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,70 @@ static int cc2520_cca(void);
|
||||||
signed char cc2520_last_rssi;
|
signed char cc2520_last_rssi;
|
||||||
uint8_t cc2520_last_correlation;
|
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 =
|
const struct radio_driver cc2520_driver =
|
||||||
{
|
{
|
||||||
cc2520_init,
|
cc2520_init,
|
||||||
|
@ -129,12 +193,12 @@ const struct radio_driver cc2520_driver =
|
||||||
pending_packet,
|
pending_packet,
|
||||||
cc2520_on,
|
cc2520_on,
|
||||||
cc2520_off,
|
cc2520_off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t receive_on;
|
|
||||||
|
|
||||||
static int channel;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#include "dev/watchdog.h"
|
#include "dev/watchdog.h"
|
||||||
#include "dev/slip.h"
|
#include "dev/slip.h"
|
||||||
#include "dev/leds.h"
|
#include "dev/leds.h"
|
||||||
#include "dev/cc2530-rf.h"
|
#include "dev/radio.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
static uint8_t prefix_set;
|
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)
|
PROCESS_THREAD(border_router_process, ev, data)
|
||||||
{
|
{
|
||||||
static struct etimer et;
|
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 */
|
/* We have created a new DODAG when we reach here */
|
||||||
PUTSTRING("On Channel ");
|
PUTSTRING("On Channel ");
|
||||||
PUTDEC(cc2530_rf_channel_get());
|
PUTDEC(get_rf_channel());
|
||||||
PUTCHAR('\n');
|
PUTCHAR('\n');
|
||||||
|
|
||||||
print_local_addresses();
|
print_local_addresses();
|
||||||
|
|
|
@ -54,8 +54,9 @@
|
||||||
#define UIP_CONF_BUFFER_SIZE 256
|
#define UIP_CONF_BUFFER_SIZE 256
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Disabling RDC for demo purposes. Core updates often require more memory. */
|
/* Disabling RDC and CSMA for demo purposes. Core updates often
|
||||||
/* For projects, optimize memory and enable RDC again. */
|
require more memory. */
|
||||||
|
/* For projects, optimize memory and enable RDC and CSMA again. */
|
||||||
#undef NETSTACK_CONF_RDC
|
#undef NETSTACK_CONF_RDC
|
||||||
#define NETSTACK_CONF_RDC nullrdc_driver
|
#define NETSTACK_CONF_RDC nullrdc_driver
|
||||||
|
|
||||||
|
@ -63,6 +64,9 @@
|
||||||
#undef UIP_CONF_TCP
|
#undef UIP_CONF_TCP
|
||||||
#define UIP_CONF_TCP 0
|
#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. */
|
/* Increase rpl-border-router IP-buffer when using more than 64. */
|
||||||
#undef REST_MAX_CHUNK_SIZE
|
#undef REST_MAX_CHUNK_SIZE
|
||||||
#define REST_MAX_CHUNK_SIZE 48
|
#define REST_MAX_CHUNK_SIZE 48
|
||||||
|
|
8
examples/extended-rf-api/Makefile
Normal file
8
examples/extended-rf-api/Makefile
Normal 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
|
510
examples/extended-rf-api/extended-rf-api.c
Normal file
510
examples/extended-rf-api/extended-rf-api.c
Normal 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();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
37
examples/extended-rf-api/project-conf.h
Normal file
37
examples/extended-rf-api/project-conf.h
Normal 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_ */
|
|
@ -32,6 +32,15 @@
|
||||||
#ifndef PROJECT_RPL_WEB_CONF_H_
|
#ifndef PROJECT_RPL_WEB_CONF_H_
|
||||||
#define 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
|
#ifndef QUEUEBUF_CONF_NUM
|
||||||
#define QUEUEBUF_CONF_NUM 6
|
#define QUEUEBUF_CONF_NUM 6
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "dev/io-arch.h"
|
#include "dev/io-arch.h"
|
||||||
#include "dev/dma.h"
|
#include "dev/dma.h"
|
||||||
#include "dev/cc2530-rf.h"
|
#include "dev/cc2530-rf.h"
|
||||||
|
#include "dev/radio.h"
|
||||||
#include "dev/watchdog.h"
|
#include "dev/watchdog.h"
|
||||||
#include "dev/clock-isr.h"
|
#include "dev/clock-isr.h"
|
||||||
#include "dev/port2.h"
|
#include "dev/port2.h"
|
||||||
|
@ -79,9 +80,11 @@ fade(int l) CC_NON_BANKED
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
set_rime_addr(void) CC_NON_BANKED
|
set_rf_params(void) CC_NON_BANKED
|
||||||
{
|
{
|
||||||
char i;
|
char i;
|
||||||
|
uint16_t short_addr;
|
||||||
|
uint8_t ext_addr[8];
|
||||||
|
|
||||||
#if CC2530_CONF_MAC_FROM_PRIMARY
|
#if CC2530_CONF_MAC_FROM_PRIMARY
|
||||||
__xdata unsigned char *macp = &X_IEEE_ADDR;
|
__xdata unsigned char *macp = &X_IEEE_ADDR;
|
||||||
|
@ -114,8 +117,12 @@ set_rime_addr(void) CC_NON_BANKED
|
||||||
FMAP = CC2530_LAST_FLASH_BANK;
|
FMAP = CC2530_LAST_FLASH_BANK;
|
||||||
#endif
|
#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++;
|
macp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +132,12 @@ set_rime_addr(void) CC_NON_BANKED
|
||||||
ENABLE_INTERRUPTS();
|
ENABLE_INTERRUPTS();
|
||||||
#endif
|
#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 */
|
/* Now the address is stored MSB first */
|
||||||
#if STARTUP_CONF_VERBOSE
|
#if STARTUP_CONF_VERBOSE
|
||||||
PUTSTRING("Rime configured with address ");
|
PUTSTRING("Rime configured with address ");
|
||||||
|
@ -136,7 +149,11 @@ set_rime_addr(void) CC_NON_BANKED
|
||||||
PUTCHAR('\n');
|
PUTCHAR('\n');
|
||||||
#endif
|
#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;
|
return;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -235,7 +252,7 @@ main(void) CC_NON_BANKED
|
||||||
|
|
||||||
/* initialize the netstack */
|
/* initialize the netstack */
|
||||||
netstack_init();
|
netstack_init();
|
||||||
set_rime_addr();
|
set_rf_params();
|
||||||
|
|
||||||
#if BUTTON_SENSOR_ON || ADC_SENSOR_ON
|
#if BUTTON_SENSOR_ON || ADC_SENSOR_ON
|
||||||
process_start(&sensors_process, NULL);
|
process_start(&sensors_process, NULL);
|
||||||
|
|
|
@ -103,9 +103,18 @@ fade(unsigned char l)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
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
|
#if STARTUP_CONF_VERBOSE
|
||||||
{
|
{
|
||||||
|
@ -118,6 +127,10 @@ set_rime_addr()
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
process_start(&etimer_process, NULL);
|
||||||
ctimer_init();
|
ctimer_init();
|
||||||
|
|
||||||
set_rime_addr();
|
set_rf_params();
|
||||||
netstack_init();
|
netstack_init();
|
||||||
cc2538_rf_set_addr(IEEE802154_PANID);
|
|
||||||
|
|
||||||
#if UIP_CONF_IPV6
|
#if UIP_CONF_IPV6
|
||||||
memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));
|
memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));
|
||||||
|
|
|
@ -272,6 +272,30 @@ init(void)
|
||||||
return 1;
|
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 =
|
const struct radio_driver cooja_radio_driver =
|
||||||
{
|
{
|
||||||
init,
|
init,
|
||||||
|
@ -284,6 +308,10 @@ const struct radio_driver cooja_radio_driver =
|
||||||
pending_packet,
|
pending_packet,
|
||||||
radio_on,
|
radio_on,
|
||||||
radio_off,
|
radio_off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
SIM_INTERFACE(radio_interface,
|
SIM_INTERFACE(radio_interface,
|
||||||
|
|
|
@ -927,6 +927,31 @@ PROCESS_THREAD(mrf24j40_process, ev, data)
|
||||||
PROCESS_END();
|
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 = {
|
const struct radio_driver mrf24j40_driver = {
|
||||||
mrf24j40_init,
|
mrf24j40_init,
|
||||||
|
@ -938,7 +963,11 @@ const struct radio_driver mrf24j40_driver = {
|
||||||
mrf24j40_receiving_packet,
|
mrf24j40_receiving_packet,
|
||||||
mrf24j40_pending_packet,
|
mrf24j40_pending_packet,
|
||||||
mrf24j40_on,
|
mrf24j40_on,
|
||||||
mrf24j40_off
|
mrf24j40_off,
|
||||||
|
get_value,
|
||||||
|
set_value,
|
||||||
|
get_object,
|
||||||
|
set_object
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue