enhanced BLE support for cc26xx-cc13xx
This commit is contained in:
parent
01048c8f66
commit
b415d57a99
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -71,7 +72,7 @@
|
||||
#define BLE_ADV_TYPE_DEVINFO 0x01
|
||||
#define BLE_ADV_TYPE_NAME 0x09
|
||||
#define BLE_ADV_TYPE_MANUFACTURER 0xFF
|
||||
#define BLE_ADV_NAME_BUF_LEN 32
|
||||
#define BLE_ADV_NAME_BUF_LEN BLE_ADV_MAX_SIZE
|
||||
#define BLE_ADV_PAYLOAD_BUF_LEN 64
|
||||
#define BLE_UUID_SIZE 16
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -82,8 +83,6 @@ static uint8_t payload[BLE_ADV_PAYLOAD_BUF_LEN];
|
||||
static int p = 0;
|
||||
static int i;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint16_t tx_power = 0x9330;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* BLE beacond config */
|
||||
static struct ble_beacond_config {
|
||||
clock_time_t interval;
|
||||
@ -108,6 +107,38 @@ static uint32_t ble_overrides[] = {
|
||||
0xFFFFFFFF, /* End of override list */
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* TX Power dBm lookup table - values from SmartRF Studio */
|
||||
typedef struct output_config {
|
||||
radio_value_t dbm;
|
||||
uint16_t tx_power; /* Value for the CMD_RADIO_SETUP.txPower field */
|
||||
} output_config_t;
|
||||
|
||||
static const output_config_t output_power[] = {
|
||||
{ 5, 0x9330 },
|
||||
{ 4, 0x9324 },
|
||||
{ 3, 0x5a1c },
|
||||
{ 2, 0x4e18 },
|
||||
{ 1, 0x4214 },
|
||||
{ 0, 0x3161 },
|
||||
{ -3, 0x2558 },
|
||||
{ -6, 0x1d52 },
|
||||
{ -9, 0x194e },
|
||||
{ -12, 0x144b },
|
||||
{ -15, 0x0ccb },
|
||||
{ -18, 0x0cc9 },
|
||||
{ -21, 0x0cc7 },
|
||||
};
|
||||
|
||||
#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].dbm)
|
||||
#define OUTPUT_POWER_MAX (output_power[0].dbm)
|
||||
#define OUTPUT_POWER_UNKNOWN 0xFFFF
|
||||
|
||||
/* Default TX Power - position in output_power[] */
|
||||
static const output_config_t *tx_power_current = &output_power[0];
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(rf_ble_beacon_process, "CC13xx / CC26xx RF BLE Beacon Process");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
@ -132,7 +163,7 @@ send_ble_adv_nc(int channel, uint8_t *adv_payload, int adv_payload_len)
|
||||
cmd.channel = channel;
|
||||
|
||||
/* Set up BLE Advertisement parameters */
|
||||
params->pDeviceAddress = (uint16_t *)&linkaddr_node_addr.u8[LINKADDR_SIZE - 2];
|
||||
params->pDeviceAddress = (uint16_t *)BLE_ADDRESS_PTR;
|
||||
params->endTrigger.triggerType = TRIG_NEVER;
|
||||
params->endTime = TRIG_NEVER;
|
||||
|
||||
@ -157,6 +188,33 @@ send_ble_adv_nc(int channel, uint8_t *adv_payload, int adv_payload_len)
|
||||
return RF_CORE_CMD_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Returns the current TX power in dBm */
|
||||
radio_value_t
|
||||
rf_ble_get_tx_power(void)
|
||||
{
|
||||
return tx_power_current->dbm;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
void
|
||||
rf_ble_set_tx_power(radio_value_t power)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* First, find the correct setting and save it */
|
||||
for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
|
||||
if(power <= output_power[i].dbm) {
|
||||
tx_power_current = &output_power[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rf_ble_beacond_config(clock_time_t interval, const char *name)
|
||||
{
|
||||
@ -211,7 +269,6 @@ rf_ble_beacond_stop()
|
||||
{
|
||||
process_exit(&rf_ble_beacon_process);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint8_t
|
||||
rf_radio_setup()
|
||||
{
|
||||
@ -223,7 +280,7 @@ rf_radio_setup()
|
||||
/* Create radio setup command */
|
||||
rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP);
|
||||
|
||||
cmd.txPower = tx_power;
|
||||
cmd.txPower = tx_power_current->tx_power;
|
||||
cmd.pRegOverride = ble_overrides;
|
||||
cmd.config.frontEndMode = RF_CORE_RADIO_SETUP_FRONT_END_MODE;
|
||||
cmd.config.biasMode = RF_CORE_RADIO_SETUP_BIAS_MODE;
|
||||
@ -246,13 +303,114 @@ rf_radio_setup()
|
||||
return RF_CORE_CMD_OK;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(rf_ble_beacon_process, ev, data)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rf_ble_beacon_single(uint8_t channel, uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t was_on;
|
||||
int j;
|
||||
uint32_t cmd_status;
|
||||
bool interrupts_disabled;
|
||||
uint8_t j, channel_selected;
|
||||
uint8_t was_on;
|
||||
|
||||
/* Adhere to the maximum BLE advertisement payload size */
|
||||
if(len > BLE_ADV_NAME_BUF_LEN) {
|
||||
len = BLE_ADV_NAME_BUF_LEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Under ContikiMAC, some IEEE-related operations will be called from an
|
||||
* interrupt context. We need those to see that we are in BLE mode.
|
||||
*/
|
||||
interrupts_disabled = ti_lib_int_master_disable();
|
||||
ble_mode_on = RF_BLE_ACTIVE;
|
||||
if(!interrupts_disabled) {
|
||||
ti_lib_int_master_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* First, determine our state:
|
||||
*
|
||||
* If we are running CSMA, we are likely in IEEE RX mode. We need to
|
||||
* abort the IEEE BG Op before entering BLE mode.
|
||||
* If we are ContikiMAC, we are likely off, in which case we need to
|
||||
* boot the CPE before entering BLE mode
|
||||
*/
|
||||
was_on = rf_core_is_accessible();
|
||||
|
||||
if(was_on) {
|
||||
/*
|
||||
* We were on: If we are in the process of receiving a frame, abort the
|
||||
* BLE beacon burst. Otherwise, terminate the primary radio Op so we
|
||||
* can switch to BLE mode
|
||||
*/
|
||||
if(NETSTACK_RADIO.receiving_packet()) {
|
||||
PRINTF("rf_ble_beacon_single: We were receiving\n");
|
||||
|
||||
/* Abort this pass */
|
||||
return;
|
||||
}
|
||||
|
||||
rf_core_primary_mode_abort();
|
||||
} else {
|
||||
|
||||
oscillators_request_hf_xosc();
|
||||
|
||||
/* We were off: Boot the CPE */
|
||||
if(rf_core_boot() != RF_CORE_CMD_OK) {
|
||||
/* Abort this pass */
|
||||
PRINTF("rf_ble_beacon_single: rf_core_boot() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
oscillators_switch_to_hf_xosc();
|
||||
|
||||
/* Enter BLE mode */
|
||||
if(rf_radio_setup() != RF_CORE_CMD_OK) {
|
||||
/* Continue so we can at least try to restore our previous state */
|
||||
PRINTF("rf_ble_beacon_single: Error entering BLE mode\n");
|
||||
} else {
|
||||
|
||||
for(j = 0; j < 3; j++) {
|
||||
channel_selected = (channel >> j) & 0x01;
|
||||
if(channel_selected == 1) {
|
||||
if(send_ble_adv_nc(37 + j, data, len) != RF_CORE_CMD_OK) {
|
||||
/* Continue... */
|
||||
PRINTF("rf_ble_beacon_single: Channel=%d, "
|
||||
"Error advertising\n", 37 + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a CMD_STOP command to RF Core */
|
||||
if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_STOP), &cmd_status) != RF_CORE_CMD_OK) {
|
||||
/* Continue... */
|
||||
PRINTF("rf_ble_beacon_single: status=0x%08lx\n", cmd_status);
|
||||
}
|
||||
|
||||
if(was_on) {
|
||||
/* We were on, go back to previous primary mode */
|
||||
rf_core_primary_mode_restore();
|
||||
} else {
|
||||
/* We were off. Shut back off */
|
||||
rf_core_power_down();
|
||||
|
||||
/* Switch HF clock source to the RCOSC to preserve power */
|
||||
oscillators_switch_to_hf_rc();
|
||||
}
|
||||
|
||||
interrupts_disabled = ti_lib_int_master_disable();
|
||||
|
||||
ble_mode_on = RF_BLE_IDLE;
|
||||
|
||||
if(!interrupts_disabled) {
|
||||
ti_lib_int_master_enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(rf_ble_beacon_process, ev, data)
|
||||
{
|
||||
PROCESS_BEGIN();
|
||||
|
||||
while(1) {
|
||||
@ -278,115 +436,21 @@ PROCESS_THREAD(rf_ble_beacon_process, ev, data)
|
||||
strlen(beacond_config.adv_name));
|
||||
p += strlen(beacond_config.adv_name);
|
||||
|
||||
/*
|
||||
* Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three
|
||||
* channels, with a BLE_ADV_DUTY_CYCLE interval between bursts
|
||||
*/
|
||||
for(i = 0; i < BLE_ADV_MESSAGES; i++) {
|
||||
/*
|
||||
* Under ContikiMAC, some IEEE-related operations will be called from an
|
||||
* interrupt context. We need those to see that we are in BLE mode.
|
||||
*/
|
||||
interrupts_disabled = ti_lib_int_master_disable();
|
||||
ble_mode_on = RF_BLE_ACTIVE;
|
||||
if(!interrupts_disabled) {
|
||||
ti_lib_int_master_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three
|
||||
* channels, with a BLE_ADV_DUTY_CYCLE interval between bursts
|
||||
*
|
||||
* First, determine our state:
|
||||
*
|
||||
* If we are running CSMA, we are likely in IEEE RX mode. We need to
|
||||
* abort the IEEE BG Op before entering BLE mode.
|
||||
* If we are ContikiMAC, we are likely off, in which case we need to
|
||||
* boot the CPE before entering BLE mode
|
||||
*/
|
||||
was_on = rf_core_is_accessible();
|
||||
rf_ble_beacon_single(BLE_ADV_CHANNEL_ALL, payload, p);
|
||||
|
||||
if(was_on) {
|
||||
/*
|
||||
* We were on: If we are in the process of receiving a frame, abort the
|
||||
* BLE beacon burst. Otherwise, terminate the primary radio Op so we
|
||||
* can switch to BLE mode
|
||||
*/
|
||||
if(NETSTACK_RADIO.receiving_packet()) {
|
||||
PRINTF("rf_ble_beacon_process: We were receiving\n");
|
||||
|
||||
/* Abort this pass */
|
||||
break;
|
||||
}
|
||||
|
||||
rf_core_primary_mode_abort();
|
||||
} else {
|
||||
/* Request the HF XOSC to source the HF clock. */
|
||||
oscillators_request_hf_xosc();
|
||||
|
||||
/* We were off: Boot the CPE */
|
||||
if(rf_core_boot() != RF_CORE_CMD_OK) {
|
||||
PRINTF("rf_ble_beacon_process: rf_core_boot() failed\n");
|
||||
|
||||
/* Abort this pass */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Trigger a switch to the XOSC, so that we can use the FS */
|
||||
oscillators_switch_to_hf_xosc();
|
||||
}
|
||||
|
||||
/* Enter BLE mode */
|
||||
if(rf_radio_setup() != RF_CORE_CMD_OK) {
|
||||
PRINTF("cc26xx_rf_ble_beacon_process: Error entering BLE mode\n");
|
||||
/* Continue so we can at least try to restore our previous state */
|
||||
} else {
|
||||
/* Send advertising packets on all 3 advertising channels */
|
||||
for(j = 37; j <= 39; j++) {
|
||||
if(send_ble_adv_nc(j, payload, p) != RF_CORE_CMD_OK) {
|
||||
PRINTF("cc26xx_rf_ble_beacon_process: Channel=%d, "
|
||||
"Error advertising\n", j);
|
||||
/* Break the loop, but don't return just yet */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send a CMD_STOP command to RF Core */
|
||||
if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_STOP), &cmd_status) != RF_CORE_CMD_OK) {
|
||||
PRINTF("cc26xx_rf_ble_beacon_process: status=0x%08lx\n", cmd_status);
|
||||
/* Continue... */
|
||||
}
|
||||
|
||||
if(was_on) {
|
||||
/* We were on, go back to previous primary mode */
|
||||
rf_core_primary_mode_restore();
|
||||
} else {
|
||||
/* We were off. Shut back off */
|
||||
rf_core_power_down();
|
||||
|
||||
/* Switch HF clock source to the RCOSC to preserve power */
|
||||
oscillators_switch_to_hf_rc();
|
||||
}
|
||||
etimer_set(&ble_adv_et, BLE_ADV_DUTY_CYCLE);
|
||||
|
||||
interrupts_disabled = ti_lib_int_master_disable();
|
||||
|
||||
ble_mode_on = RF_BLE_IDLE;
|
||||
|
||||
if(!interrupts_disabled) {
|
||||
ti_lib_int_master_enable();
|
||||
}
|
||||
|
||||
/* Wait unless this is the last burst */
|
||||
if(i < BLE_ADV_MESSAGES - 1) {
|
||||
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ble_adv_et));
|
||||
}
|
||||
}
|
||||
|
||||
interrupts_disabled = ti_lib_int_master_disable();
|
||||
|
||||
ble_mode_on = RF_BLE_IDLE;
|
||||
|
||||
if(!interrupts_disabled) {
|
||||
ti_lib_int_master_enable();
|
||||
}
|
||||
}
|
||||
PROCESS_END();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Copyright (c) 2017, University of Bristol - http://www.bristol.ac.uk/
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -45,6 +46,7 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#include "contiki.h"
|
||||
#include "rf-core/rf-core.h"
|
||||
#include "radio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -57,6 +59,23 @@
|
||||
#define RF_BLE_IDLE 0
|
||||
#define RF_BLE_ACTIVE 1
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Memory address of BLE MAC address. Can be overwritten by the user by defining BLE_ADDRESS_PTR. */
|
||||
#ifndef BLE_ADDRESS_PTR
|
||||
#define BLE_ADDRESS_PTR (0x500012E8)
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* BLE Advertisement channels. Not to be changed by the user. */
|
||||
#define BLE_ADV_CHANNEL_MASK 0x07
|
||||
|
||||
#define BLE_ADV_CHANNEL_37 0x01
|
||||
#define BLE_ADV_CHANNEL_38 0x02
|
||||
#define BLE_ADV_CHANNEL_39 0x04
|
||||
|
||||
#define BLE_ADV_CHANNEL_ALL (BLE_ADV_CHANNEL_37 | BLE_ADV_CHANNEL_38 | BLE_ADV_CHANNEL_39)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Maximum BLE advertisement size. Not to be changed by the user. */
|
||||
#define BLE_ADV_MAX_SIZE 31
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set the device name to use with the BLE advertisement/beacon daemon
|
||||
* \param interval The interval (ticks) between two consecutive beacon bursts
|
||||
@ -89,6 +108,37 @@ void rf_ble_beacond_stop(void);
|
||||
* \retval 0 The BLE daemon is not active, or disabled
|
||||
*/
|
||||
uint8_t rf_ble_is_active(void);
|
||||
|
||||
/**
|
||||
* \brief Set TX power for BLE advertisements
|
||||
* \param power The 'at least' TX power in dBm, values avove 5 dBm will be ignored
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
void rf_ble_set_tx_power(radio_value_t power);
|
||||
|
||||
/**
|
||||
* \brief Get TX power for BLE advertisements
|
||||
* \return The TX power for BLE advertisements
|
||||
*/
|
||||
radio_value_t rf_ble_get_tx_power(void);
|
||||
|
||||
/**
|
||||
* \brief Transmit a single BLE advertisement in one or more advertisement channels
|
||||
* \param channel Bitmask of advertisement channels to be used: use
|
||||
* BLE_ADV_CHANNEL_37 for channel 37, BLE_ADV_CHANNEL_38 for channel 38,
|
||||
* BLE_ADV_CHANNEL_39 for channel 39, or any 'or' combination of those
|
||||
* \param data A pointer to the advertisement data buffer
|
||||
* \param len The length of the advertisement data. If more than BLE_ADV_MAX_SIZE,
|
||||
* the first BLE_ADV_MAX_SIZE bytes will be used.
|
||||
*
|
||||
* Transmits a given advertisement payload once in one or any arbitrary combination
|
||||
* of advertisement channels.
|
||||
*/
|
||||
void rf_ble_beacon_single(uint8_t channel, uint8_t *data, uint8_t len);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* RF_BLE_H_ */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
Loading…
Reference in New Issue
Block a user