Working prop-mode

This commit is contained in:
Edvard Pettersen 2018-06-15 16:37:51 +02:00
parent f9fcbd6a77
commit f6b016c5d4
13 changed files with 593 additions and 543 deletions

View File

@ -56,12 +56,10 @@
#define CC2650_FAST_RADIO_STARTUP (MAC_CONF_WITH_TSCH)
#endif
#ifdef RF_CHANNEL
#define RF_CORE_CONF_CHANNEL RF_CHANNEL
#endif
#ifndef RF_CORE_CONF_CHANNEL
#define RF_CORE_CONF_CHANNEL 25
#ifdef RF_CORE_CONF_CHANNEL
#define RF_CHANNEL RF_CORE_CONF_CHANNEL
#else
#define RF_CHANNEL 25
#endif
/* Number of Prop Mode RX buffers */
@ -70,11 +68,13 @@
#endif
/* Configure Radio mode, i.e. prop or ieee */
/*----- CC13xx Device Line --------------------------------------------------*/
/* CC13xx supports both IEEE and Prop mode, depending on which device */
/* CC26xx only supports IEEE mode */
#if defined(DEVICE_LINE_CC13XX)
/* Default mode should be prop for prop-only devices (CC1310, CC1312);
/* Default mode should be prop for prop-only devices (CC1310, CC1312R);
* Else, IEEE mode is default. */
# ifndef CC13XX_CONF_PROP_MODE
# if (SUPPORTS_IEEE_MODE == 0)
@ -84,14 +84,12 @@
# endif
# endif
# if (CC13XX_CONF_PROP_MODE == 1) && (SUPPORTS_PROP_MODE == 1)
/*----- CC13xx Prop Mode ----------------------------------------------------*/
# define NETSTACK_CONF_RADIO prop_mode_driver
# define CSMA_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 400)
# define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME \
(RTIMER_SECOND / 1000)
# define CSMA_CONF_ACK_WAIT_TIME (RTIMER_SECOND / 300)
# define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME (RTIMER_SECOND / 1000)
# define CSMA_CONF_SEND_SOFT_ACK 1
# elif (CC13XX_CONF_PROP_MODE == 0) && (SUPPORTS_IEEE_MODE == 1)
@ -101,9 +99,12 @@
# define CSMA_CONF_SEND_SOFT_ACK 0
# else
/*----- CC13xx Non-supported Mode -------------------------------------------*/
# error "Invalid radio mode configuration of CC13xx device"
# endif /* (CC13XX_CONF_PROP_MODE == 1) && (SUPPORTS_PROP_MODE == 1) */
/*----- CC26xx Device Line --------------------------------------------------*/
/* CC26xx only supports IEEE mode */
#elif defined(DEVICE_LINE_CC26XX)
# if (SUPPORTS_IEEE_MODE == 1)
@ -113,9 +114,11 @@
# define CSMA_CONF_SEND_SOFT_ACK 0
# else
/*----- CC26xx Non-supported Mode -------------------------------------------*/
# error "IEEE mode only supported by CC26xx devices"
# endif /* (SUPPORTS_IEEE_MODE == 1) */
/*----- Unsupported device line ---------------------------------------------*/
#else
# error "Unsupported Device Line defined"
#endif /* defined(DEVICE_LINE_CC13xx) */

View File

@ -39,25 +39,18 @@
#include <contiki.h>
#include <dev/watchdog.h>
#include <sys/process.h>
#include <sys/energest.h>
#include <net/netstack.h>
#include <net/packetbuf.h>
#include <net/mac/mac.h>
/*---------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
/*---------------------------------------------------------------------------*/
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RF"
#define LOG_LEVEL LOG_LEVEL_DBG
/*---------------------------------------------------------------------------*/
PROCESS(RF_coreProcess, "SimpleLink RF process");
PROCESS(rf_process, "SimpleLink RF Process");
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(RF_coreProcess, ev, data)
PROCESS_THREAD(rf_process, ev, data)
{
int len;

View File

@ -43,34 +43,12 @@
#ifndef RF_COMMON_H_
#define RF_COMMON_H_
/*---------------------------------------------------------------------------*/
/* Contiki API */
#include <sys/rtimer.h>
#include <dev/radio.h>
/*---------------------------------------------------------------------------*/
/* Standard library */
#include <stdint.h>
/*---------------------------------------------------------------------------*/
#ifdef RF_CORE_CONF_CHANNEL
# define RF_CORE_CHANNEL RF_CORE_CONF_CHANNEL
#else
# define RF_CORE_CHANNEL 25
#endif
/*---------------------------------------------------------------------------*/
typedef enum {
CMD_RESULT_ERROR = 0,
CMD_RESULT_OK = 1,
} CmdResult;
} cmd_result_t;
/*---------------------------------------------------------------------------*/
typedef struct {
radio_value_t dbm;
uint16_t power; ///< Value for the .txPower field
} RF_TxPower;
#define TX_POWER_UNKNOWN 0xFFFF
/*---------------------------------------------------------------------------*/
#define RSSI_UNKNOWN -128
/*---------------------------------------------------------------------------*/
PROCESS_NAME(RF_coreProcess);
PROCESS_NAME(rf_process);
/*---------------------------------------------------------------------------*/
#endif /* RF_COMMON_H_ */
/*---------------------------------------------------------------------------*/

View File

@ -121,7 +121,7 @@
#ifdef IEEE_MODE_CONF_CHANNEL
# define IEEE_MODE_CHANNEL IEEE_MODE_CONF_CHANNEL
#else
# define IEEE_MODE_CHANNEL RF_CORE_CHANNEL
# define IEEE_MODE_CHANNEL RF_CHANNEL
#endif
/* Configuration for TX power table */
@ -301,10 +301,7 @@ static void
rx_cb(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
if (e & RF_EventRxOk) {
process_poll(&RF_coreProcess);
}
if (e & RF_EventRxBufFull) {
process_poll(&rf_process);
}
}
/*---------------------------------------------------------------------------*/
@ -343,7 +340,7 @@ init_data_queue(void)
static void
init_rf_params(void)
{
cmd_rx.channel = RF_CORE_CHANNEL;
cmd_rx.channel = IEEE_MODE_CHANNEL;
cmd_rx.pRxQ = &g_rxDataQueue;
cmd_rx.pOutput = &g_rxStats;
@ -555,7 +552,7 @@ init(void)
ctimer_set(&g_ratOverflowTimer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
rat_overflow_cb, NULL);
process_start(&RF_coreProcess, NULL);
process_start(&rf_process, NULL);
return CMD_RESULT_OK;
}
@ -812,23 +809,25 @@ pending_packet(void)
const rfc_dataEntry_t *const pStartEntry = (rfc_dataEntry_t *)g_rxDataQueue.pCurrEntry;
volatile const rfc_dataEntry_t *pCurrEntry = pStartEntry;
int rv = 0;
// Check all RX buffers and check their statuses, stopping when looping the circular buffer
int bIsPending = 0;
do {
const uint8_t status = pCurrEntry->status;
if ((status == DATA_ENTRY_FINISHED) ||
(status == DATA_ENTRY_BUSY)) {
bIsPending = 1;
if (!g_bPollMode) {
process_poll(&RF_coreProcess);
}
rv += 1;
}
pCurrEntry = (rfc_dataEntry_t *)pCurrEntry->pNextEntry;
} while (pCurrEntry != pStartEntry);
if ((rv > 0) && !g_bPollMode) {
process_poll(&rf_process);
}
// If we didn't find an entry at status finished or busy, no frames are pending
return bIsPending;
return rv;
}
/*---------------------------------------------------------------------------*/
static int
@ -909,7 +908,7 @@ get_value(radio_param_t param, radio_value_t *value)
case RADIO_PARAM_TXPOWER:
*value = get_tx_power();
return (*value == TX_POWER_UNKNOWN)
return (*value == RF_TxPowerTable_INVALID_DBM)
? RADIO_RESULT_ERROR
: RADIO_RESULT_OK;

View File

@ -80,6 +80,13 @@
# define PRINTF(...) printf(__VA_ARGS__)
#endif
/*---------------------------------------------------------------------------*/
/* Configuration for default Prop channel */
#ifdef PROP_MODE_CONF_CHANNEL
# define PROP_MODE_CHANNEL PROP_MODE_CONF_CHANNEL
#else
# define PROP_MODE_CHANNEL RF_CHANNEL
#endif
/*---------------------------------------------------------------------------*/
/* Data whitener. 1: Whitener, 0: No whitener */
#ifdef PROP_MODE_CONF_DW
# define PROP_MODE_DW PROP_MODE_CONF_DW
@ -93,19 +100,6 @@
# define PROP_MODE_USE_CRC16 0
#endif
/*---------------------------------------------------------------------------*/
/**
* \brief Returns the current status of a running Radio Op command
* \param a A pointer with the buffer used to initiate the command
* \return The value of the Radio Op buffer's status field
*
* This macro can be used to e.g. return the status of a previously
* initiated background operation, or of an immediate command
*/
#define RF_RADIO_OP_GET_STATUS(a) GET_FIELD_V(a, radioOp, status)
/*---------------------------------------------------------------------------*/
/* Special value returned by CMD_IEEE_CCA_REQ when an RSSI is not available */
#define RF_CMD_CCA_REQ_RSSI_UNKNOWN -128
/* Used for the return value of channel_clear */
#define RF_CCA_CLEAR 1
#define RF_CCA_BUSY 0
@ -122,17 +116,10 @@
#define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 10 */
#ifdef PROP_MODE_CONF_RSSI_THRESHOLD
#define PROP_MODE_RSSI_THRESHOLD PROP_MODE_CONF_RSSI_THRESHOLD
# define PROP_MODE_RSSI_THRESHOLD PROP_MODE_CONF_RSSI_THRESHOLD
#else
#define PROP_MODE_RSSI_THRESHOLD 0xA6
# define PROP_MODE_RSSI_THRESHOLD 0xA6
#endif
static int8_t rssi_threshold = PROP_MODE_RSSI_THRESHOLD;
/*---------------------------------------------------------------------------*/
static int rf_switch_on(void);
static int rf_switch_off(void);
static rfc_propRxOutput_t rx_stats;
/*---------------------------------------------------------------------------*/
/* Defines and variables related to the .15.4g PHY HDR */
#define DOT_4G_MAX_FRAME_LEN 2047
@ -144,23 +131,20 @@ static rfc_propRxOutput_t rx_stats;
#if PROP_MODE_USE_CRC16
/* CRC16 */
#define DOT_4G_PHR_CRC_BIT DOT_4G_PHR_CRC16
#define CRC_LEN 2
# define DOT_4G_PHR_CRC_BIT DOT_4G_PHR_CRC16
# define CRC_LEN 2
#else
/* CRC32 */
#define DOT_4G_PHR_CRC_BIT 0
#define CRC_LEN 4
#endif
# define DOT_4G_PHR_CRC_BIT 0
# define CRC_LEN 4
#endif /* PROP_MODE_USE_CRC16 */
#if PROP_MODE_DW
#define DOT_4G_PHR_DW_BIT DOT_4G_PHR_DW
# define DOT_4G_PHR_DW_BIT DOT_4G_PHR_DW
#else
#define DOT_4G_PHR_DW_BIT 0
#define DOT_4G_PHR_DW_BIT 0
#endif
/*---------------------------------------------------------------------------*/
/* How long to wait for an ongoing ACK TX to finish before starting frame TX */
#define TX_WAIT_TIMEOUT (RTIMER_SECOND >> 11)
/* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */
#define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10)
/*---------------------------------------------------------------------------*/
@ -179,106 +163,118 @@ static rfc_propRxOutput_t rx_stats;
#define TX_POWER_IN_RANGE(dbm) (((dbm) >= TX_POWER_MIN) && ((dbm) <= TX_POWER_MAX))
/*---------------------------------------------------------------------------*/
/* TX buf configuration */
#define TX_BUF_HDR_LEN 2
#define TX_BUF_PAYLOAD_LEN 180
#define TX_BUF_SIZE (TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN)
/* RX buf configuration */
#ifdef PROP_MODE_CONF_RX_BUF_CNT
#define PROP_MODE_RX_BUF_CNT PROP_MODE_CONF_RX_BUF_CNT
# define RX_BUF_CNT PROP_MODE_CONF_RX_BUF_CNT
#else
#define PROP_MODE_RX_BUF_CNT 4
# define RX_BUF_CNT 4
#endif
#define RX_BUF_SIZE 140
/*---------------------------------------------------------------------------*/
#define DATA_ENTRY_LENSZ_NONE 0
#define DATA_ENTRY_LENSZ_BYTE 1
#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
/*
* RX buffers.
* PROP_MODE_RX_BUF_CNT buffers of RX_BUF_SIZE bytes each. The start of each
* buffer must be 4-byte aligned, therefore RX_BUF_SIZE must divide by 4
*/
#define RX_BUF_SIZE 140
static uint8_t rx_buf[PROP_MODE_RX_BUF_CNT][RX_BUF_SIZE] CC_ALIGN(4);
/* The RX Data Queue */
static dataQueue_t rx_data_queue = { 0 };
/* Receive entry pointer to keep track of read items */
volatile static uint8_t *rx_read_entry;
/*---------------------------------------------------------------------------*/
/* The outgoing frame buffer */
#define TX_BUF_PAYLOAD_LEN 180
#define TX_BUF_HDR_LEN 2
#define MAC_RADIO_RECEIVER_SENSITIVITY_DBM -110
#define MAC_RADIO_RECEIVER_SATURATION_DBM 10
#define MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY 10
#define MAC_SPEC_ED_MAX 0xFF
static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
#define ED_RF_POWER_MIN_DBM (MAC_RADIO_RECEIVER_SENSITIVITY_DBM + MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY)
#define ED_RF_POWER_MAX_DBM MAC_RADIO_RECEIVER_SATURATION_DBM
/*---------------------------------------------------------------------------*/
#define cmd_radio_setup ((volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t *)&rf_cmd_prop_radio_div_setup)
#define cmd_fs ((volatile rfc_CMD_FS_t *) &rf_cmd_prop_fs)
#define cmd_tx ((volatile rfc_CMD_PROP_TX_ADV_t *) &rf_cmd_prop_tx_adv)
#define cmd_rx ((volatile rfc_CMD_PROP_RX_ADV_t *) &rf_cmd_prop_rx_adv)
typedef struct {
/* Outgoing frame buffer */
uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
/* Incoming frame buffer */
uint8_t rx_buf[RX_BUF_CNT][RX_BUF_SIZE] CC_ALIGN(4);
/* RX Data Queue */
dataQueue_t rx_data_queue;
/* RX Statistics struct */
rfc_propRxOutput_t rx_stats;
/* Receive entry pointer to keep track of read items */
volatile uint8_t* rx_read_entry;
/* RSSI Threshold */
int8_t rssi_threshold;
/* Indicates RF is supposed to be on or off */
uint8_t rf_is_on;
/* RF driver */
RF_Object rf_object;
RF_Handle rf_handle;
} prop_radio_t;
static prop_radio_t prop_radio;
/*---------------------------------------------------------------------------*/
/* RF driver */
static RF_Object rfObject;
static RF_Handle rfHandle;
#define cmd_radio_setup (*(volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t *)&rf_cmd_prop_radio_div_setup)
#define cmd_fs (*(volatile rfc_CMD_FS_t *) &rf_cmd_prop_fs)
#define cmd_tx (*(volatile rfc_CMD_PROP_TX_ADV_t *) &rf_cmd_prop_tx_adv)
#define cmd_rx (*(volatile rfc_CMD_PROP_RX_ADV_t *) &rf_cmd_prop_rx_adv)
/*---------------------------------------------------------------------------*/
static CC_INLINE bool rf_is_transmitting(void) { return cmd_tx->status == ACTIVE; }
static CC_INLINE bool rf_is_receiving(void) { return cmd_rx->status == ACTIVE; }
static CC_INLINE bool rf_is_on(void) { return rf_is_transmitting() || rf_is_receiving(); }
static CC_INLINE bool tx_active(void) { return cmd_tx.status == ACTIVE; }
static CC_INLINE bool rx_active(void) { return cmd_rx.status == ACTIVE; }
/*---------------------------------------------------------------------------*/
static int on(void);
static int off(void);
/*---------------------------------------------------------------------------*/
static void
rf_rx_callback(RF_Handle client, RF_CmdHandle command, RF_EventMask events)
cmd_rx_cb(RF_Handle client, RF_CmdHandle command, RF_EventMask events)
{
/* Unused arguments */
(void)client;
(void)command;
if (events & RF_EventRxEntryDone) {
process_poll(&RF_coreProcess);
process_poll(&rf_process);
}
}
/*---------------------------------------------------------------------------*/
static CmdResult
rf_start_rx()
static cmd_result_t
start_rx(void)
{
cmd_rx->status = IDLE;
/*
* Set the max Packet length. This is for the payload only, therefore
* 2047 - length offset
*/
cmd_rx->maxPktLen = DOT_4G_MAX_FRAME_LEN - cmd_rx->lenOffset;
RF_CmdHandle rxCmdHandle = RF_postCmd(rfHandle, (RF_Op*)cmd_rx, RF_PriorityNormal,
&rf_rx_callback, RF_EventRxEntryDone);
if (rxCmdHandle == RF_ALLOC_ERROR) {
cmd_rx.status = IDLE;
RF_CmdHandle rx_handle = RF_postCmd(prop_radio.rf_handle, (RF_Op*)&cmd_rx, RF_PriorityNormal,
&cmd_rx_cb, RF_EventRxEntryDone);
if (rx_handle == RF_ALLOC_ERROR) {
PRINTF("start_rx: RF_ALLOC_ERROR for cmd_rx\n");
return CMD_RESULT_ERROR;
}
/* Wait to enter RX */
const rtimer_clock_t t0 = RTIMER_NOW();
while (!rf_is_receiving() &&
while (!rx_active() &&
(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT)));
if (!rf_is_receiving()) {
PRINTF("RF_cmdPropRxAdv: handle=0x%08lx, status=0x%04x\n",
(unsigned long)rxCmdHandle, cmd_rx->status);
rf_switch_off();
if (!rx_active()) {
PRINTF("cmd_rx: status=0x%04x\n", cmd_rx.status);
return CMD_RESULT_ERROR;
}
return CMD_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
static CmdResult
rf_stop_rx(void)
static cmd_result_t
stop_rx(void)
{
/* If we are off, do nothing */
if (!rf_is_receiving()) {
return CMD_RESULT_OK;
}
/* Abort any ongoing operation. Don't care about the result. */
RF_cancelCmd(rfHandle, RF_CMDHANDLE_FLUSH_ALL, 1);
RF_cancelCmd(prop_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, 1);
/* Todo: maybe do a RF_pendCmd() to synchronize with command execution. */
if(cmd_rx->status != PROP_DONE_STOPPED &&
cmd_rx->status != PROP_DONE_ABORT) {
if(cmd_rx.status != PROP_DONE_STOPPED &&
cmd_rx.status != PROP_DONE_ABORT) {
PRINTF("RF_cmdPropRxAdv cancel: status=0x%04x\n",
cmd_rx->status);
cmd_rx.status);
return CMD_RESULT_ERROR;
}
@ -287,11 +283,11 @@ rf_stop_rx(void)
return CMD_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
static CmdResult
static cmd_result_t
rf_run_setup()
{
RF_runCmd(rfHandle, (RF_Op*)cmd_radio_setup, RF_PriorityNormal, NULL, 0);
if (cmd_radio_setup->status != PROP_DONE_OK) {
RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_radio_setup, RF_PriorityNormal, NULL, 0);
if (cmd_radio_setup.status != PROP_DONE_OK) {
return CMD_RESULT_ERROR;
}
@ -301,24 +297,24 @@ rf_run_setup()
static radio_value_t
get_rssi(void)
{
if (rf_is_transmitting()) {
if (tx_active()) {
PRINTF("get_rssi: called while in TX\n");
return RF_GET_RSSI_ERROR_VAL;
}
const bool was_off = !rf_is_receiving();
if (was_off && rf_start_rx() == CMD_RESULT_ERROR) {
const bool was_off = !rx_active();
if (was_off && start_rx() == CMD_RESULT_ERROR) {
PRINTF("get_rssi: unable to start RX\n");
return RF_GET_RSSI_ERROR_VAL;
}
int8_t rssi = RF_GET_RSSI_ERROR_VAL;
while(rssi == RF_GET_RSSI_ERROR_VAL || rssi == 0) {
rssi = RF_getRssi(rfHandle);
rssi = RF_getRssi(prop_radio.rf_handle);
}
if(was_off) {
rf_switch_off();
if (was_off) {
stop_rx();
}
return rssi;
@ -327,9 +323,7 @@ get_rssi(void)
static uint8_t
get_channel(void)
{
uint32_t freq_khz;
freq_khz = cmd_fs->frequency * 1000;
uint32_t freq_khz = cmd_fs.frequency * 1000;
/*
* For some channels, fractFreq * 1000 / 65536 will return 324.99xx.
@ -337,12 +331,12 @@ get_channel(void)
* function returning channel - 1 instead of channel. Thus, we do a quick
* positive integer round up.
*/
freq_khz += (((cmd_fs->fractFreq * 1000) + 65535) / 65536);
freq_khz += (((cmd_fs.fractFreq * 1000) + 65535) / 65536);
return (freq_khz - DOT_15_4G_CHAN0_FREQUENCY) / DOT_15_4G_CHANNEL_SPACING;
}
/*---------------------------------------------------------------------------*/
static void
static cmd_result_t
set_channel(uint8_t channel)
{
uint32_t new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING);
@ -353,24 +347,32 @@ set_channel(uint8_t channel)
PRINTF("set_channel: %u = 0x%04x.0x%04x (%lu)\n",
channel, freq, frac, new_freq);
cmd_radio_setup->centerFreq = freq;
cmd_fs->frequency = freq;
cmd_fs->fractFreq = frac;
// Todo: Need to re-run setup command when deviation from previous frequency
// is too large
// rf_run_setup();
cmd_radio_setup.centerFreq = freq;
cmd_fs.frequency = freq;
cmd_fs.fractFreq = frac;
// We don't care whether the FS command is successful because subsequent
// TX and RX commands will tell us indirectly.
RF_postCmd(rfHandle, (RF_Op*)cmd_fs, RF_PriorityNormal, NULL, 0);
RF_EventMask rf_events = RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_fs,
RF_PriorityNormal, NULL, 0);
if ((rf_events & (RF_EventCmdDone | RF_EventLastCmdDone)) == 0) {
PRINTF("set_channel: RF_runCmd failed, events=0x%llx\n", rf_events);
return CMD_RESULT_ERROR;
}
if (cmd_fs.status != DONE_OK) {
PRINTF("set_channel: cmd_fs failed, status=0x%04x\n", cmd_fs.status);
return CMD_RESULT_ERROR;
}
return CMD_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
/* Returns the current TX power in dBm */
static radio_value_t
get_tx_power(void)
{
const RF_TxPowerTable_Value value = RF_getTxPower(rfHandle);
const RF_TxPowerTable_Value value = RF_getTxPower(prop_radio.rf_handle);
return (radio_value_t)RF_TxPowerTable_findPowerLevel(TX_POWER_TABLE, value);
}
/*---------------------------------------------------------------------------*/
@ -385,29 +387,46 @@ set_tx_power(const radio_value_t power)
return RADIO_RESULT_INVALID_VALUE;
}
const RF_TxPowerTable_Value value = RF_TxPowerTable_findValue(TX_POWER_TABLE, power);
RF_Stat stat = RF_setTxPower(rfHandle, value);
RF_Stat stat = RF_setTxPower(prop_radio.rf_handle, value);
return (stat == RF_StatSuccess)
? RADIO_RESULT_OK
: RADIO_RESULT_ERROR;
}
/*---------------------------------------------------------------------------*/
static uint8_t
calculate_lqi(int8_t rssi)
{
/* Note : Currently the LQI value is simply the energy detect measurement.
* A more accurate value could be derived by using the correlation
* value along with the RSSI value. */
rssi = CLAMP(rssi, ED_RF_POWER_MIN_DBM, ED_RF_POWER_MAX_DBM);
/* Create energy detect measurement by normalizing and scaling RF power level.
* Note : The division operation below is designed for maximum accuracy and
* best granularity. This is done by grouping the math operations to
* compute the entire numerator before doing any division. */
return (MAC_SPEC_ED_MAX * (rssi - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);
}
/*---------------------------------------------------------------------------*/
static void
init_rx_buffers(void)
{
rfc_dataEntry_t *entry;
int i;
for(i = 0; i < PROP_MODE_RX_BUF_CNT; i++) {
entry = (rfc_dataEntry_t *)rx_buf[i];
entry->status = DATA_ENTRY_PENDING;
entry->config.type = DATA_ENTRY_TYPE_GEN;
entry->config.lenSz = DATA_ENTRY_LENSZ_WORD;
entry->length = RX_BUF_SIZE - 8;
entry->pNextEntry = rx_buf[i + 1];
size_t i = 0;
for (i = 0; i < RX_BUF_CNT; i++) {
const rfc_dataEntry_t data_entry = {
.status = DATA_ENTRY_PENDING,
.config.type = DATA_ENTRY_TYPE_GEN,
.config.lenSz = DATA_ENTRY_LENSZ_WORD,
.length = RX_BUF_SIZE - sizeof(rfc_dataEntry_t), /* TODO is this sizeof sound? */
/* Point to fist entry if this is last entry, else point to next entry */
.pNextEntry = (i == (RX_BUF_CNT - 1))
? prop_radio.rx_buf[0]
: prop_radio.rx_buf[i]
};
/* Write back data entry struct */
*(rfc_dataEntry_t *)prop_radio.rx_buf[i] = data_entry;
}
((rfc_dataEntry_t *)rx_buf[PROP_MODE_RX_BUF_CNT - 1])->pNextEntry = rx_buf[0];
}
/*---------------------------------------------------------------------------*/
static int
@ -415,7 +434,7 @@ prepare(const void *payload, unsigned short payload_len)
{
int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN);
memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len);
memcpy(prop_radio.tx_buf + TX_BUF_HDR_LEN, payload, len);
return 0;
}
/*---------------------------------------------------------------------------*/
@ -425,11 +444,11 @@ transmit(unsigned short transmit_len)
int ret;
uint8_t was_off = 0;
if (rf_is_transmitting()) {
if (tx_active()) {
PRINTF("transmit: not allowed while transmitting\n");
return RADIO_TX_ERR;
} else if (rf_is_receiving()) {
rf_stop_rx();
} else if (rx_active()) {
stop_rx();
} else {
was_off = 1;
}
@ -447,18 +466,18 @@ transmit(unsigned short transmit_len)
*/
total_length = transmit_len + CRC_LEN;
tx_buf[0] = total_length & 0xFF;
tx_buf[1] = (total_length >> 8) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT;
prop_radio.tx_buf[0] = total_length & 0xFF;
prop_radio.tx_buf[1] = (total_length >> 8) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT;
/*
* pktLen: Total number of bytes in the TX buffer, including the header if
* one exists, but not including the CRC (which is not present in the buffer)
*/
cmd_tx->pktLen = transmit_len + DOT_4G_PHR_LEN;
cmd_tx->pPkt = tx_buf;
cmd_tx.pktLen = transmit_len + DOT_4G_PHR_LEN;
cmd_tx.pPkt = prop_radio.tx_buf;
// TODO: Register callback
RF_runCmd(rfHandle, (RF_Op*)cmd_tx, RF_PriorityNormal, NULL, 0);
RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_tx, RF_PriorityNormal, NULL, 0);
// if (txHandle == RF_ALLOC_ERROR)
// {
// /* Failure sending the CMD_PROP_TX command */
@ -472,27 +491,27 @@ transmit(unsigned short transmit_len)
// // watchdog_periodic();
//
// /* Idle away while the command is running */
// RF_pendCmd(rfHandle, txHandle, RF_EventLastCmdDone);
// RF_pendCmd(rf_handle, txHandle, RF_EventLastCmdDone);
if(cmd_tx->status == PROP_DONE_OK) {
if(cmd_tx.status == PROP_DONE_OK) {
/* Sent OK */
ret = RADIO_TX_OK;
} else {
/* Operation completed, but frame was not sent */
PRINTF("transmit: Not Sent OK status=0x%04x\n",
cmd_tx->status);
cmd_tx.status);
ret = RADIO_TX_ERR;
}
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
/* Workaround. Set status to IDLE */
cmd_tx->status = IDLE;
cmd_tx.status = IDLE;
if (was_off) {
RF_yield(rfHandle);
RF_yield(prop_radio.rf_handle);
} else {
rf_start_rx();
start_rx();
}
return ret;
@ -506,71 +525,66 @@ send(const void *payload, unsigned short payload_len)
}
/*---------------------------------------------------------------------------*/
static int
read_frame(void *buf, unsigned short buf_len)
read(void *buf, unsigned short buf_len)
{
rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)prop_radio.rx_read_entry;
uint8_t *data_ptr = &entry->data;
int len = 0;
uint16_t len = 0;
if(entry->status == DATA_ENTRY_FINISHED) {
if (entry->status != DATA_ENTRY_FINISHED) {
return 0;
}
/*
* First 2 bytes in the data entry are the length.
/* First 2 bytes in the data entry are the length.
* Our data entry consists of: Payload + RSSI (1 byte) + Status (1 byte)
* This length includes all of those.
*/
len = (*(uint16_t *)data_ptr);
* This length includes all of those. */
len = *(uint16_t *)data_ptr;
data_ptr += 2;
len -= 2;
if(len > 0) {
if(len <= buf_len) {
const bool len_ok = (0 < len) && (len <= (uint16_t)buf_len);
if (len_ok) {
memcpy(buf, data_ptr, len);
}
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (int8_t)data_ptr[len]);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, 0x7F);
int8_t rssi = (int8_t)data_ptr[len];
uint8_t lqi = calculate_lqi(rssi);
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)rssi);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)lqi);
}
/* Move read entry pointer to next entry */
rx_read_entry = entry->pNextEntry;
prop_radio.rx_read_entry = entry->pNextEntry;
entry->status = DATA_ENTRY_PENDING;
}
return len;
return (len_ok)
? (int)len
: 0;
}
/*---------------------------------------------------------------------------*/
static int
channel_clear(void)
{
uint8_t was_off = 0;
int8_t rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN;
// /*
// * If we are in the middle of a BLE operation, we got called by ContikiMAC
// * from within an interrupt context. Indicate a clear channel
// */
// if(rf_ble_is_active() == RF_BLE_ACTIVE) {
// return RF_CCA_CLEAR;
// }
if (rf_is_transmitting()) {
if (tx_active()) {
PRINTF("channel_clear: called while in TX\n");
return RF_CCA_CLEAR;
} else if (!rf_is_receiving()) {
was_off = 1;
rf_start_rx();
}
while(rssi == RF_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) {
rssi = RF_getRssi(rfHandle);
const bool rx_was_off = !rx_active();
if (rx_was_off) {
start_rx();
}
if(was_off) {
rf_switch_off();
int8_t rssi = RF_GET_RSSI_ERROR_VAL;
while (rssi == RF_GET_RSSI_ERROR_VAL || rssi == 0) {
rssi = RF_getRssi(prop_radio.rf_handle);
}
if(rssi >= rssi_threshold) {
if (rx_was_off) {
stop_rx();
}
if(rssi >= prop_radio.rssi_threshold) {
return RF_CCA_BUSY;
}
@ -580,11 +594,11 @@ channel_clear(void)
static int
receiving_packet(void)
{
if(!rf_is_receiving()) {
if (!rx_active()) {
return 0;
}
if(channel_clear() == RF_CCA_CLEAR) {
if (channel_clear() == RF_CCA_CLEAR) {
return 0;
}
@ -594,50 +608,76 @@ receiving_packet(void)
static int
pending_packet(void)
{
int rv = 0;
volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
const rfc_dataEntry_t *const first_entry = (rfc_dataEntry_t *)prop_radio.rx_data_queue.pCurrEntry;
volatile const rfc_dataEntry_t *entry = first_entry;
/* Go through all RX buffers and check their status */
int rv = 0;
/* Go through RX Circular buffer and check their status */
do {
if(entry->status == DATA_ENTRY_FINISHED) {
const uint8_t status = entry->status;
if ((status == DATA_ENTRY_FINISHED) ||
(status == DATA_ENTRY_BUSY)) {
rv += 1;
process_poll(&RF_coreProcess);
}
entry = (rfc_dataEntry_t *)entry->pNextEntry;
} while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
} while (entry != first_entry);
if (rv > 0) {
process_poll(&rf_process);
}
/* If we didn't find an entry at status finished, no frames are pending */
return rv;
}
/*---------------------------------------------------------------------------*/
static int
rf_switch_on(void)
on(void)
{
if (prop_radio.rf_is_on) {
PRINTF("RF on: Radio already in RX\n");
return CMD_RESULT_OK;
}
/* Reset all RF command statuses */
cmd_radio_setup.status = IDLE;
cmd_fs.status = IDLE;
cmd_tx.status = IDLE;
cmd_rx.status = IDLE;
init_rx_buffers();
return rf_start_rx();
const int rx_ok = start_rx();
if (!rx_ok) {
off();
return CMD_RESULT_ERROR;
}
prop_radio.rf_is_on = true;
return CMD_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
static int
rf_switch_off(void)
off(void)
{
// /*
// * If we are in the middle of a BLE operation, we got called by ContikiMAC
// * from within an interrupt context. Abort, but pretend everything is OK.
// */
// if(rf_ble_is_active() == RF_BLE_ACTIVE) {
// return CMD_RESULT_OK;
// }
if (!prop_radio.rf_is_on) {
return CMD_RESULT_OK;
}
// Force abort of any ongoing RF operation.
RF_cancelCmd(rfHandle, RF_CMDHANDLE_FLUSH_ALL, 0);
RF_flushCmd(prop_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
// Trigger a manual power-down
RF_yield(rfHandle);
RF_yield(prop_radio.rf_handle);
/* We pulled the plug, so we need to restore the status manually */
cmd_rx->status = IDLE;
cmd_radio_setup.status = IDLE;
cmd_fs.status = IDLE;
cmd_tx.status = IDLE;
cmd_rx.status = IDLE;
prop_radio.rf_is_on = false;
return CMD_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
@ -651,7 +691,10 @@ get_value(radio_param_t param, radio_value_t *value)
switch (param) {
case RADIO_PARAM_POWER_MODE:
/* On / off */
*value = rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
*value = (prop_radio.rf_is_on)
? RADIO_POWER_MODE_ON
: RADIO_POWER_MODE_OFF;
return RADIO_RESULT_OK;
case RADIO_PARAM_CHANNEL:
@ -663,12 +706,12 @@ get_value(radio_param_t param, radio_value_t *value)
return RADIO_RESULT_OK;
case RADIO_PARAM_CCA_THRESHOLD:
*value = rssi_threshold;
*value = prop_radio.rssi_threshold;
return RADIO_RESULT_OK;
case RADIO_PARAM_RSSI:
*value = get_rssi();
return (*value == RF_CMD_CCA_REQ_RSSI_UNKNOWN)
return (*value == RF_GET_RSSI_ERROR_VAL)
? RADIO_RESULT_ERROR
: RADIO_RESULT_OK;
@ -703,7 +746,7 @@ set_value(radio_param_t param, radio_value_t value)
return RADIO_RESULT_OK;
}
if(value == RADIO_POWER_MODE_OFF) {
rf_switch_off();
off();
return RADIO_RESULT_OK;
}
return RADIO_RESULT_INVALID_VALUE;
@ -730,7 +773,7 @@ set_value(radio_param_t param, radio_value_t value)
return RADIO_RESULT_OK;
case RADIO_PARAM_CCA_THRESHOLD:
rssi_threshold = (int8_t)value;
prop_radio.rssi_threshold = (int8_t)value;
return RADIO_RESULT_OK;
default:
@ -738,13 +781,13 @@ set_value(radio_param_t param, radio_value_t value)
}
/* If we reach here we had no errors. Apply new settings */
if (rf_is_receiving()) {
rf_stop_rx();
if (rx_active()) {
stop_rx();
if (rf_run_setup() != CMD_RESULT_OK) {
return RADIO_RESULT_ERROR;
}
rf_start_rx();
} else if (rf_is_transmitting()) {
start_rx();
} else if (tx_active()) {
// Should not happen. TX is always synchronous and blocking.
// Todo: maybe remove completely here.
PRINTF("set_value: cannot apply new value while transmitting. \n");
@ -770,49 +813,63 @@ set_object(radio_param_t param, const void *src, size_t size)
}
/*---------------------------------------------------------------------------*/
static int
rf_init(void)
init(void)
{
RF_Params params;
RF_Params_init(&params);
// Disable automatic power-down just to not interfere with stack timing
params.nInactivityTimeout = 0;
/* Zero initalize TX and RX buffers */
memset(prop_radio.tx_buf, 0x0, sizeof(prop_radio.tx_buf));
memset(prop_radio.rx_buf, 0x0, sizeof(prop_radio.rx_buf));
rfHandle = RF_open(&rfObject, &rf_prop_mode, (RF_RadioSetup*)cmd_radio_setup, &params);
assert(rfHandle != NULL);
/* Initialise RX buffers */
memset(rx_buf, 0, sizeof(rx_buf));
/* Set of RF Core data queue. Circular buffer, no last entry */
rx_data_queue.pCurrEntry = rx_buf[0];
rx_data_queue.pLastEntry = NULL;
/* Circular buffer, no last entry */
prop_radio.rx_data_queue.pCurrEntry = prop_radio.rx_buf[0];
prop_radio.rx_data_queue.pLastEntry = NULL;
/* Initialize current read pointer to first element (used in ISR) */
rx_read_entry = rx_buf[0];
prop_radio.rx_read_entry = prop_radio.rx_buf[0];
cmd_rx->pQueue = &rx_data_queue;
cmd_rx->pOutput = (uint8_t *)&rx_stats;
/* Set configured RSSI threshold */
prop_radio.rssi_threshold = PROP_MODE_RSSI_THRESHOLD;
set_channel(RF_CORE_CHANNEL);
/* RX is off */
prop_radio.rf_is_on = false;
/* Configure RX command */
cmd_rx.maxPktLen = DOT_4G_MAX_FRAME_LEN - cmd_rx.lenOffset;
cmd_rx.pQueue = &prop_radio.rx_data_queue;
cmd_rx.pOutput = (uint8_t *)&prop_radio.rx_stats;
/* Init RF params and specify non-default params */
RF_Params rf_params;
RF_Params_init(&rf_params);
rf_params.nInactivityTimeout = 2000; /* 2 ms */
/* Open RF Driver */
prop_radio.rf_handle = RF_open(&prop_radio.rf_object, &rf_prop_mode,
(RF_RadioSetup*)&cmd_radio_setup, &rf_params);
if (prop_radio.rf_handle == NULL) {
return CMD_RESULT_ERROR;
}
set_channel(PROP_MODE_CHANNEL);
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
process_start(&RF_coreProcess, NULL);
/* Start RF process */
process_start(&rf_process, NULL);
return CMD_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
const struct radio_driver prop_mode_driver = {
rf_init,
init,
prepare,
transmit,
send,
read_frame,
read,
channel_clear,
receiving_packet,
pending_packet,
rf_switch_on,
rf_switch_off,
on,
off,
get_value,
set_value,
get_object,

View File

@ -97,7 +97,7 @@ RF_TxPowerTable_Entry rf_prop_tx_power_table[RF_PROP_TX_POWER_TABLE_SIZE+1] =
};
/*---------------------------------------------------------------------------*/
// Overrides for CMD_PROP_RADIO_DIV_SETUP
uint32_t p_prop_overrides[] CC_ALIGN(4) =
uint32_t rf_prop_overrides[] CC_ALIGN(4) =
{
// override_use_patch_prop_genfsk.xml
MCE_RFE_OVERRIDE(0,4,0,1,0,0), // PHY: Use MCE ROM bank 4, RFE RAM patch
@ -137,15 +137,15 @@ uint32_t p_prop_overrides[] CC_ALIGN(4) =
// Proprietary Mode Radio Setup Command for All Frequency Bands
rfc_CMD_PROP_RADIO_DIV_SETUP_t rf_cmd_prop_radio_div_setup =
{
.commandNo = 0x3807,
.status = 0x0000,
.commandNo = CMD_PROP_RADIO_DIV_SETUP,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x0,
.condition.rule = 0x1,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.modulation.modType = 0x1,
.modulation.deviation = 0x64,
@ -164,7 +164,7 @@ rfc_CMD_PROP_RADIO_DIV_SETUP_t rf_cmd_prop_radio_div_setup =
.config.analogCfgMode = 0x0,
.config.bNoFsPowerUp = 0x0,
.txPower = 0xAB3F,
.pRegOverride = pPropOverrides,
.pRegOverride = rf_prop_overrides,
.centerFreq = 0x0364,
.intFreq = 0x8000,
.loDivider = 0x05,
@ -174,15 +174,15 @@ rfc_CMD_PROP_RADIO_DIV_SETUP_t rf_cmd_prop_radio_div_setup =
// Frequency Synthesizer Programming Command
rfc_CMD_FS_t rf_cmd_prop_fs =
{
.commandNo = 0x0803,
.status = 0x0000,
.commandNo = CMD_FS,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x0,
.condition.rule = 0x1,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.frequency = 0x0364,
.fractFreq = 0x0000,
@ -199,14 +199,14 @@ rfc_CMD_FS_t rf_cmd_prop_fs =
rfc_CMD_PROP_TX_ADV_t rf_cmd_prop_tx_adv =
{
.commandNo = CMD_PROP_TX_ADV,
.status = 0x0000,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x2,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x1,
.condition.rule = 0x1,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.pktConf.bFsOff = 0x0,
.pktConf.bUseCrc = 0x1,

View File

@ -52,7 +52,7 @@ extern rfc_CMD_PROP_TX_ADV_t rf_cmd_prop_tx_adv;
extern rfc_CMD_PROP_RX_ADV_t rf_cmd_prop_rx_adv;
/*---------------------------------------------------------------------------*/
// RF Core API Overrides
extern uint32_t p_prop_overrides[];
extern uint32_t rf_prop_overrides[];
/*---------------------------------------------------------------------------*/
#endif /* PROP_SETTINGS_H_ */
/*---------------------------------------------------------------------------*/

View File

@ -109,7 +109,7 @@ uint32_t rf_ieee_overrides[] CC_ALIGN(4) =
rfc_CMD_RADIO_SETUP_t rf_cmd_ieee_radio_setup =
{
.commandNo = CMD_RADIO_SETUP,
.status = 0x0000,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = TRIG_NOW,
@ -133,7 +133,7 @@ rfc_CMD_RADIO_SETUP_t rf_cmd_ieee_radio_setup =
rfc_CMD_FS_t rf_cmd_ieee_fs =
{
.commandNo = CMD_FS,
.status = 0x0000,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = TRIG_NOW,
@ -142,8 +142,8 @@ rfc_CMD_FS_t rf_cmd_ieee_fs =
.startTrigger.pastTrig = 0x0,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.frequency = 0x0965,
.fractFreq = 0x0000,
.frequency = 0x0965, /* set by driver */
.fractFreq = 0x0000, /* set by driver */
.synthConf.bTxMode = 0x1,
.synthConf.refFreq = 0x0,
.__dummy0 = 0x00,
@ -156,8 +156,8 @@ rfc_CMD_FS_t rf_cmd_ieee_fs =
// IEEE 802.15.4 Transmit Command
rfc_CMD_IEEE_TX_t rf_cmd_ieee_tx =
{
.commandNo = CMD_IEEE_RX,
.status = 0x0000,
.commandNo = CMD_IEEE_TX,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = TRIG_NOW,
@ -178,25 +178,25 @@ rfc_CMD_IEEE_TX_t rf_cmd_ieee_tx =
// IEEE 802.15.4 Receive Command
rfc_CMD_IEEE_RX_t rf_cmd_ieee_rx =
{
.commandNo = 0x2801,
.status = 0x0000,
.commandNo = CMD_IEEE_RX,
.status = IDLE,
.pNextOp = 0,
.startTime = 0x00000000,
.startTrigger.triggerType = 0x0,
.startTrigger.triggerType = TRIG_NOW,
.startTrigger.bEnaCmd = 0x0,
.startTrigger.triggerNo = 0x0,
.startTrigger.pastTrig = 0x0,
.condition.rule = 0x1,
.condition.rule = COND_NEVER,
.condition.nSkip = 0x0,
.channel = 0x00,
.rxConfig.bAutoFlushCrc = 0x0,
.channel = 0x00, /* set by driver */
.rxConfig.bAutoFlushCrc = 0x1,
.rxConfig.bAutoFlushIgn = 0x0,
.rxConfig.bIncludePhyHdr = 0x0,
.rxConfig.bIncludeCrc = 0x0,
.rxConfig.bIncludeCrc = 0x1,
.rxConfig.bAppendRssi = 0x1,
.rxConfig.bAppendCorrCrc = 0x1,
.rxConfig.bAppendSrcInd = 0x0,
.rxConfig.bAppendTimestamp = 0x0,
.rxConfig.bAppendTimestamp = 0x1,
.pRxQ = 0, /* set by driver */
.pOutput = 0, /* set by driver */
.frameFiltOpt.frameFiltEn = 0x0, /* set by driver */

View File

@ -34,8 +34,8 @@
#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
#include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
#include DeviceFamily_constructPath(driverlib/rf_ieee_cmd.h
#include DeviceFamily_constructPath(driverlib/rf_ieee_mailbox.h))
#include DeviceFamily_constructPath(driverlib/rf_ieee_cmd.h)
#include DeviceFamily_constructPath(driverlib/rf_ieee_mailbox.h)
#include <ti/drivers/rf/RF.h>
/*---------------------------------------------------------------------------*/

View File

@ -59,8 +59,8 @@
* Override button symbols from dev/button-sensor.h, for the examples that
* include it
*/
#define btn1_sensor button_left_sensor
#define btn2_sensor button_right_sensor
#define button_left_sensor btn1_sensor
#define button_right_sensor btn2_sensor
/** @} */
/*---------------------------------------------------------------------------*/
/* Platform-specific define to signify sensor reading failure */

View File

@ -41,23 +41,24 @@
#include <lib/sensors.h>
/*---------------------------------------------------------------------------*/
#include <Board.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/Power.h>
/*---------------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
/*---------------------------------------------------------------------------*/
#include "button-sensor.h"
#include "button-sensor-arch.h"
/*---------------------------------------------------------------------------*/
/* LaunchPad has 2 buttons: BTN1 and BTN2 */
/* Map the GPIO defines from the Board file */
#define BTN1_GPIO Board_GPIO_BTN1
#define BTN2_GPIO Board_GPIO_BTN2
#define BTN1_PIN Board_PIN_BTN1
#define BTN2_PIN Board_PIN_BTN2
/*---------------------------------------------------------------------------*/
#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN
# define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN
#else
# define BUTTON_SENSOR_ENABLE_SHUTDOWN 1
# define BUTTON_SENSOR_ENABLE_SHUTDOWN 0
#endif
/*---------------------------------------------------------------------------*/
#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5)
@ -68,56 +69,92 @@ typedef struct {
clock_time_t duration;
} BtnTimer;
/*---------------------------------------------------------------------------*/
static BtnTimer g_btn1Timer;
static BtnTimer g_btn2Timer;
static BtnTimer btn1_timer;
static BtnTimer btn2_timer;
/*---------------------------------------------------------------------------*/
static const PIN_Config btn_pin_table[] = {
BTN1_PIN | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS, /* Button is active low */
BTN2_PIN | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS, /* Button is active low */
PIN_TERMINATE
};
static PIN_State pin_state;
static PIN_Handle pin_handle;
/*---------------------------------------------------------------------------*/
static void
button_press_cb(uint8_t index, BtnTimer *btnTimer, const struct sensors_sensor *btnSensor)
button_press_cb(PIN_Handle handle, PIN_Id pin_id)
{
if (!timer_expired(&btnTimer->debounce)) {
#ifdef BUTTON_SENSOR_ENABLE_SHUTDOWN
if (pin_id == BTN2_PIN) {
Power_shutdown(Power_ENTERING_SHUTDOWN, 0);
return;
}
#endif
BtnTimer *btn_timer = NULL;
const struct sensors_sensor *btn_sensor = NULL;
switch (pin_id) {
case BTN1_PIN: btn_timer = &btn1_timer;
btn_sensor = &btn1_sensor; break;
case BTN2_PIN: btn_timer = &btn2_timer;
btn_sensor = &btn2_sensor; break;
default: return; /* No matching PIN */
}
if (!timer_expired(&btn_timer->debounce)) {
return;
}
timer_set(&btnTimer->debounce, DEBOUNCE_DURATION);
timer_set(&btn_timer->debounce, DEBOUNCE_DURATION);
// Start press duration counter on press (falling), notify on release (rising)
if (GPIO_read(index) == 0) {
btnTimer->start = clock_time();
btnTimer->duration = 0;
if (PIN_getInputValue(pin_id) == 0) {
btn_timer->start = clock_time();
btn_timer->duration = 0;
} else {
btnTimer->duration = clock_time() - btnTimer->start;
sensors_changed(btnSensor);
btn_timer->duration = clock_time() - btn_timer->start;
sensors_changed(btn_sensor);
}
}
/*---------------------------------------------------------------------------*/
static int
button_value(int type, uint8_t index, BtnTimer *btnTimer)
button_value(int type, uint8_t pin, BtnTimer *btn_timer)
{
if (type == BUTTON_SENSOR_VALUE_STATE) {
return (GPIO_read(index) == 0)
return (PIN_getInputValue(pin) == 0)
? BUTTON_SENSOR_VALUE_PRESSED
: BUTTON_SENSOR_VALUE_RELEASED;
} else if (type == BUTTON_SENSOR_VALUE_DURATION) {
return (int)btnTimer->duration;
return (int)btn_timer->duration;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int
button_config(int type, int value, uint8_t index, GPIO_CallbackFxn callback)
button_config(int type, int value, uint8_t pin)
{
switch (type) {
case SENSORS_HW_INIT:
GPIO_clearInt(index);
GPIO_setCallback(index, callback);
// Open PIN handle
if (pin_handle) {
return 1;
}
pin_handle = PIN_open(&pin_state, btn_pin_table);
if (!pin_handle) {
return 0;
}
// Register button callback function
PIN_registerIntCb(pin_handle, button_press_cb);
break;
case SENSORS_ACTIVE:
if (value) {
GPIO_clearInt(index);
GPIO_enableInt(index);
// Enable interrupts on both edges
PIN_setInterrupt(pin_handle, pin | PIN_IRQ_BOTHEDGES);
} else {
GPIO_disableInt(index);
// Disable pin interrupts
PIN_setInterrupt(pin_handle, pin | PIN_IRQ_DIS);
}
break;
}
@ -126,70 +163,53 @@ button_config(int type, int value, uint8_t index, GPIO_CallbackFxn callback)
}
/*---------------------------------------------------------------------------*/
static int
button_status(int type, uint8_t index)
button_status(int type, uint8_t pin)
{
switch(type) {
case SENSORS_ACTIVE: /* fallthrough */
case SENSORS_READY: {
GPIO_PinConfig pinCfg = 0;
GPIO_getConfig(index, &pinCfg);
return (pinCfg & GPIO_CFG_IN_INT_NONE) == 0;
PIN_Config pin_cfg = PIN_getConfig(pin);
return (pin_cfg & PIN_BM_IRQ) == PIN_IRQ_DIS;
}
default: break;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static void
btn1_press_cb(unsigned char unusued)
{
button_press_cb(BTN1_GPIO, &g_btn1Timer, &btn1_sensor);
}
/*---------------------------------------------------------------------------*/
static int
btn1_value(int type)
{
return button_value(type, BTN1_GPIO, &g_btn1Timer);
return button_value(type, BTN1_PIN, &btn1_timer);
}
/*---------------------------------------------------------------------------*/
static int
btn1_config(int type, int value)
{
return button_config(type, value, BTN1_GPIO, btn1_press_cb);
return button_config(type, value, BTN1_PIN);
}
/*---------------------------------------------------------------------------*/
static int
btn1_status(int type)
{
return button_status(type, BTN1_GPIO);
}
/*---------------------------------------------------------------------------*/
static void
btn2_press_cb(unsigned char unusued)
{
if (BUTTON_SENSOR_ENABLE_SHUTDOWN) {
Power_shutdown(Power_ENTERING_SHUTDOWN, 0);
return;
}
button_press_cb(BTN2_GPIO, &g_btn2Timer, &btn2_sensor);
return button_status(type, BTN1_PIN);
}
/*---------------------------------------------------------------------------*/
static int
btn2_value(int type)
{
return button_value(type, BTN2_GPIO, &g_btn2Timer);
return button_value(type, BTN2_PIN, &btn2_timer);
}
/*---------------------------------------------------------------------------*/
static int
btn2_config(int type, int value)
{
return button_config(type, value, BTN2_GPIO, btn2_press_cb);
return button_config(type, value, BTN2_PIN);
}
/*---------------------------------------------------------------------------*/
static int
btn2_status(int type)
{
return button_status(type, BTN1_GPIO);
return button_status(type, BTN2_PIN);
}
/*---------------------------------------------------------------------------*/
SENSORS_SENSOR(btn1_sensor, BUTTON_SENSOR, btn1_value, btn1_config, btn1_status);

View File

@ -43,12 +43,8 @@
/*---------------------------------------------------------------------------*/
/* Exports a global symbol to be used by the sensor API */
SENSORS(
#ifdef BUTTON_SENSOR_ARCH_BTN1
&button_sensor,
#endif
#ifdef BUTTON_SENSOR_ARCH_BTN2
&button_sensor2,
#endif
&btn1_sensor,
&btn2_sensor,
NULL
);
/*---------------------------------------------------------------------------*/

View File

@ -145,6 +145,10 @@
#define ABS(n) (((n) < 0) ? -(n) : (n))
#endif
#ifndef CLAMP
#define CLAMP(v, vmin, vmax) (MAX(MIN(v, vmax), vmin))
#endif
#define CC_CONCAT2(s1, s2) s1##s2
/**