mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-28 08:37:22 +00:00
stm32-sx1280: advertise only every advertising interval max
This commit is contained in:
parent
c682a3bf6e
commit
44c20b8a7b
@ -21,9 +21,9 @@ The Makefile project compiles gatt_counter, gatt_streamer_server, hog_mouse and
|
||||
## Limitation
|
||||
|
||||
### Advertising State:
|
||||
- Advertises as fast as possible, back to back
|
||||
- Only Connectable Advertising supported
|
||||
- Only fixed public BD_ADDR of 33:33:33:33:33:33 is used
|
||||
- Scan response not supported
|
||||
|
||||
### Connection State:
|
||||
- Only a single packet is sent in each Connection Interval
|
||||
@ -49,12 +49,13 @@ For the FMLR-80-P-STL4E module, just run make. You can upload the .elf file crea
|
||||
## TODO
|
||||
|
||||
### General
|
||||
- only advertise with advertising interval
|
||||
- support other adv types
|
||||
- indicate random address in adertising pdus
|
||||
- allow to set random BD_ADDR via HCI command
|
||||
- handle Connection Param Update
|
||||
- handle disconnect for gatt streamer demo
|
||||
- multiple packets per connection interval
|
||||
- handle Connection Param Update
|
||||
- indicate random address in advertising pdus
|
||||
- allow to set random BD_ADDR via HCI command
|
||||
- support other adv types
|
||||
- support scan requests
|
||||
- handle Encryption
|
||||
|
||||
## Low Power
|
||||
|
@ -65,7 +65,7 @@ static void MX_SPI2_Init(void);
|
||||
static void MX_TIM2_Init(void);
|
||||
static void MX_LPTIM1_Init(void);
|
||||
/* USER CODE BEGIN PFP */
|
||||
void ble_rx(void);
|
||||
void btstack_port(void);
|
||||
|
||||
/* USER CODE END PFP */
|
||||
|
||||
@ -118,7 +118,7 @@ int main(void)
|
||||
// Enable SX1280 Clock
|
||||
HAL_GPIO_WritePin(RF_TXCO_GPIO_Port, RF_TXCO_Pin, GPIO_PIN_SET);
|
||||
|
||||
ble_rx();
|
||||
btstack_port();
|
||||
|
||||
/* USER CODE END 2 */
|
||||
|
||||
|
@ -35,6 +35,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define BTSTACK_FILE__ "controller.c"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <string.h>
|
||||
|
@ -35,6 +35,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define BTSTACK_FILE__ "ll_sx1280.c"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <string.h>
|
||||
@ -151,6 +153,7 @@ typedef enum {
|
||||
RADIO_RX_ERROR,
|
||||
RADIO_TX_TIMEOUT,
|
||||
RADIO_W4_TX_DONE_TO_RX,
|
||||
RADIO_W4_TIMER,
|
||||
} radio_state_t;
|
||||
|
||||
// Link Layer State
|
||||
@ -291,7 +294,8 @@ static struct {
|
||||
uint8_t adv_data[31];
|
||||
|
||||
// adv param
|
||||
uint8_t adv_map;
|
||||
uint8_t adv_map;
|
||||
uint32_t adv_interval_us;
|
||||
|
||||
// next expected sequence number
|
||||
volatile uint8_t next_expected_sequence_number;
|
||||
@ -338,6 +342,9 @@ static uint8_t ll_outgoing_hci_event[258];
|
||||
static bool ll_send_disconnected;
|
||||
static bool ll_send_connection_complete;
|
||||
|
||||
// prototypes
|
||||
static void radio_set_timer(uint32_t anchor_offset_us);
|
||||
|
||||
|
||||
// memory pool for acl-le pdus
|
||||
static ll_pdu_t * btstack_memory_ll_pdu_get(void){
|
||||
@ -398,6 +405,32 @@ static void next_channel(void){
|
||||
select_channel(ctx.channel);
|
||||
}
|
||||
|
||||
static void ll_advertising_statemachine(void){
|
||||
switch ( radio_state) {
|
||||
case RADIO_RX_ERROR:
|
||||
case RADIO_LOWPOWER:
|
||||
// find next channel
|
||||
while (ctx.channel < 40){
|
||||
ctx.channel++;
|
||||
if ((ctx.adv_map & (1 << (ctx.channel - 37))) != 0) {
|
||||
// Set Channel
|
||||
select_channel(ctx.channel);
|
||||
radio_state = RADIO_W4_TX_DONE_TO_RX;
|
||||
send_adv();
|
||||
break;
|
||||
}
|
||||
if (ctx.channel >= 40){
|
||||
// Set timer
|
||||
radio_state = RADIO_W4_TIMER;
|
||||
radio_set_timer(ctx.adv_interval_us);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void start_advertising(void){
|
||||
|
||||
Radio.SetAutoTx(AUTO_RX_TX_OFFSET);
|
||||
@ -418,10 +451,15 @@ static void start_advertising(void){
|
||||
// Set AccessAddress for ADV packets
|
||||
Radio.SetBleAdvertizerAccessAddress( );
|
||||
|
||||
radio_state = RADIO_LOWPOWER;
|
||||
ll_state = LL_STATE_ADVERTISING;
|
||||
|
||||
// dummy channel
|
||||
// prepare
|
||||
ctx.channel = 36;
|
||||
ctx.anchor_ticks = HAL_LPTIM_ReadCounter(&hlptim1);
|
||||
|
||||
// and get started
|
||||
ll_advertising_statemachine();
|
||||
}
|
||||
|
||||
static void start_hopping(void){
|
||||
@ -434,16 +472,16 @@ static void start_hopping(void){
|
||||
Radio.SetPacketParams( &packetParams );
|
||||
|
||||
}
|
||||
static void stop_timer_for_sync_hop(void){
|
||||
static void radio_stop_timer(void){
|
||||
__HAL_LPTIM_DISABLE_IT(&hlptim1, LPTIM_IT_CMPM);
|
||||
__HAL_LPTIM_CLEAR_FLAG(&hlptim1, LPTIM_IT_CMPM);
|
||||
}
|
||||
|
||||
static void set_timer_for_sync_hop(void){
|
||||
static void radio_set_timer(uint32_t anchor_offset_us){
|
||||
// stop
|
||||
stop_timer_for_sync_hop();
|
||||
// set timer
|
||||
uint16_t timeout_ticks = ctx.anchor_ticks + US_TO_TICKS(ctx.conn_interval_us - SYNC_HOP_DELAY_US);
|
||||
radio_stop_timer();
|
||||
// set timer for next radio event relative to anchor
|
||||
uint16_t timeout_ticks = ctx.anchor_ticks + US_TO_TICKS(anchor_offset_us);
|
||||
__HAL_LPTIM_COMPARE_SET(&hlptim1, timeout_ticks);
|
||||
__HAL_LPTIM_ENABLE_IT(&hlptim1, LPTIM_IT_CMPM);
|
||||
}
|
||||
@ -451,7 +489,7 @@ static void set_timer_for_sync_hop(void){
|
||||
static void ll_terminate(void){
|
||||
ll_state = LL_STATE_STANDBY;
|
||||
// stop sync hop timer
|
||||
stop_timer_for_sync_hop();
|
||||
radio_stop_timer();
|
||||
// free outgoing tx packet
|
||||
if ((ctx.tx_pdu != NULL) && (ctx.tx_pdu != &ll_tx_packet)){
|
||||
btstack_memory_ll_pdu_free(ctx.tx_pdu);
|
||||
@ -463,58 +501,73 @@ static void ll_terminate(void){
|
||||
ll_send_disconnected = true;
|
||||
}
|
||||
|
||||
static void sync_next_hop(void){
|
||||
static void radio_timer_handler(void){
|
||||
|
||||
uint16_t t0 = HAL_LPTIM_ReadCounter(&hlptim1);
|
||||
|
||||
// check supervision timeout
|
||||
ctx.time_without_any_packets_us += ctx.conn_interval_us;
|
||||
if (ctx.time_without_any_packets_us > ctx.supervision_timeout_us) {
|
||||
printf("Supervision timeout\n\n");
|
||||
ll_terminate();
|
||||
return;
|
||||
switch (ll_state){
|
||||
case LL_STATE_CONNECTED:
|
||||
// check supervision timeout
|
||||
ctx.time_without_any_packets_us += ctx.conn_interval_us;
|
||||
if (ctx.time_without_any_packets_us > ctx.supervision_timeout_us) {
|
||||
printf("Supervision timeout\n\n");
|
||||
ll_terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare next connection event
|
||||
ctx.connection_event++;
|
||||
ctx.anchor_ticks += US_TO_TICKS(ctx.conn_interval_us);
|
||||
|
||||
ctx.packet_nr_in_connection_event = 0;
|
||||
next_channel();
|
||||
|
||||
if (ctx.channel_map_update_pending && (ctx.channel_map_update_instant == ctx.connection_event)) {
|
||||
hopping_set_channel_map( &h, (const uint8_t *) &ctx.channel_map_update_map );
|
||||
ctx.channel_map_update_pending = false;
|
||||
}
|
||||
|
||||
if ( ctx.conn_param_update_pending && ((ctx.conn_param_update_instant) == ctx.connection_event) ) {
|
||||
ctx.conn_interval_us = ctx.conn_param_update_interval_us;
|
||||
ctx.conn_latency = ctx.conn_param_update_latency;
|
||||
ctx.supervision_timeout_us = ctx.conn_param_update_timeout_us;
|
||||
ctx.conn_param_update_pending = false;
|
||||
|
||||
radio_stop_timer();
|
||||
ctx.synced = false;
|
||||
}
|
||||
|
||||
// restart radio timer (might get overwritten by first packet)
|
||||
radio_set_timer(ctx.conn_interval_us - SYNC_HOP_DELAY_US);
|
||||
|
||||
receive_master();
|
||||
|
||||
printf("--SYNC-Ch %02u-Event %04u - t %08u--\n", ctx.channel, ctx.connection_event, t0);
|
||||
break;
|
||||
case LL_STATE_ADVERTISING:
|
||||
// send adv on all configured channels
|
||||
ctx.channel = 36;
|
||||
ctx.anchor_ticks = t0;
|
||||
radio_stop_timer();
|
||||
ll_advertising_statemachine();
|
||||
radio_state = RADIO_LOWPOWER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// prepare next connection event
|
||||
ctx.connection_event++;
|
||||
ctx.anchor_ticks += US_TO_TICKS(ctx.conn_interval_us);
|
||||
|
||||
ctx.packet_nr_in_connection_event = 0;
|
||||
next_channel();
|
||||
|
||||
if (ctx.channel_map_update_pending && (ctx.channel_map_update_instant == ctx.connection_event)) {
|
||||
hopping_set_channel_map( &h, (const uint8_t *) &ctx.channel_map_update_map );
|
||||
ctx.channel_map_update_pending = false;
|
||||
}
|
||||
|
||||
if ( ctx.conn_param_update_pending && ((ctx.conn_param_update_instant) == ctx.connection_event) ) {
|
||||
ctx.conn_interval_us = ctx.conn_param_update_interval_us;
|
||||
ctx.conn_latency = ctx.conn_param_update_latency;
|
||||
ctx.supervision_timeout_us = ctx.conn_param_update_timeout_us;
|
||||
ctx.conn_param_update_pending = false;
|
||||
|
||||
stop_timer_for_sync_hop();
|
||||
ctx.synced = false;
|
||||
}
|
||||
|
||||
// restart sync next hop timer (might get overwritten by first packet)
|
||||
set_timer_for_sync_hop();
|
||||
|
||||
receive_master();
|
||||
|
||||
printf("--SYNC-Ch %02u-Event %04u - t %08u--\n", ctx.channel, ctx.connection_event, t0);
|
||||
}
|
||||
|
||||
void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim){
|
||||
UNUSED(hlptim);
|
||||
sync_next_hop();
|
||||
radio_timer_handler();
|
||||
}
|
||||
|
||||
void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim){
|
||||
UNUSED(hlptim);
|
||||
static uint32_t time_seconds = 0;
|
||||
time_seconds += 2;
|
||||
printf("Time: %4u s\n", time_seconds);
|
||||
// printf("Time: %4u s\n", time_seconds);
|
||||
}
|
||||
|
||||
/** Radio IRQ handlers */
|
||||
@ -602,7 +655,7 @@ static void radio_on_rx_done(void ){
|
||||
if (ctx.packet_nr_in_connection_event == 0){
|
||||
ctx.anchor_ticks = packet_start_ticks;
|
||||
ctx.synced = true;
|
||||
set_timer_for_sync_hop();
|
||||
radio_set_timer(ctx.conn_interval_us - SYNC_HOP_DELAY_US);
|
||||
}
|
||||
|
||||
ctx.packet_nr_in_connection_event++;
|
||||
@ -667,8 +720,9 @@ void ll_init(void){
|
||||
// set test bd addr 33:33:33:33:33:33
|
||||
memset(ctx.bd_addr_le, 0x33, 6);
|
||||
|
||||
// default channels
|
||||
// default channels, advertising interval
|
||||
ctx.adv_map = 0x7;
|
||||
ctx.adv_interval_us = 1280000;
|
||||
}
|
||||
|
||||
void ll_radio_on(void){
|
||||
@ -737,7 +791,6 @@ static void ll_handle_conn_ind(ll_pdu_t * rx_packet){
|
||||
// convert to us
|
||||
ctx.conn_interval_us = ctx.conn_interval_1250us * 1250;
|
||||
ctx.supervision_timeout_us = ctx.supervision_timeout_10ms * 10000;
|
||||
|
||||
ctx.connection_event = 0;
|
||||
ctx.packet_nr_in_connection_event = 0;
|
||||
ctx.next_expected_sequence_number = 0;
|
||||
@ -905,7 +958,7 @@ uint8_t ll_set_scan_enable(uint8_t le_scan_enable, uint8_t filter_duplicates){
|
||||
static uint8_t ll_start_advertising(void){
|
||||
// COMMAND DISALLOWED if wrong state.
|
||||
if (ll_state != LL_STATE_STANDBY) return ERROR_CODE_COMMAND_DISALLOWED;
|
||||
printf("Start Advertising on channels 0x%0x\n", ctx.adv_map);
|
||||
log_info("Start Advertising on channels 0x%0x, interval %lu us", ctx.adv_map, ctx.adv_interval_us);
|
||||
start_advertising();
|
||||
return ERROR_CODE_SUCCESS;
|
||||
}
|
||||
@ -929,9 +982,20 @@ uint8_t ll_set_advertise_enable(uint8_t le_adv_enable){
|
||||
uint8_t ll_set_advertising_parameters(uint16_t advertising_interval_min, uint16_t advertising_interval_max,
|
||||
uint8_t advertising_type, uint8_t own_address_type, uint8_t peer_address_types, uint8_t * peer_address,
|
||||
uint8_t advertising_channel_map, uint8_t advertising_filter_policy){
|
||||
|
||||
// validate channel map
|
||||
if (advertising_channel_map == 0) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
if ((advertising_channel_map & 0xf8) != 0) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
|
||||
// validate advertising interval
|
||||
if (advertising_interval_min < 0x20) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
if (advertising_interval_min > 0x4000) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
if (advertising_interval_max < 0x20) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
if (advertising_interval_max > 0x4000) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
if (advertising_interval_min > advertising_interval_max) return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
|
||||
ctx.adv_map = advertising_channel_map;
|
||||
ctx.adv_interval_us = advertising_interval_max * 625;
|
||||
|
||||
// TODO: validate other params
|
||||
// TODO: process other params
|
||||
@ -981,27 +1045,8 @@ void ll_execute_once(void){
|
||||
|
||||
switch ( ll_state ){
|
||||
case LL_STATE_ADVERTISING:
|
||||
switch ( radio_state) {
|
||||
case RADIO_RX_ERROR:
|
||||
case RADIO_LOWPOWER:
|
||||
// find next channel
|
||||
while (ctx.adv_map != 0){
|
||||
ctx.channel++;
|
||||
if ((ctx.adv_map & (1 << (ctx.channel - 37))) != 0) {
|
||||
// Set Channel
|
||||
select_channel(ctx.channel);
|
||||
radio_state = RADIO_W4_TX_DONE_TO_RX;
|
||||
send_adv();
|
||||
break;
|
||||
}
|
||||
if (ctx.channel >= 40){
|
||||
ctx.channel = 36;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ll_advertising_statemachine();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -35,6 +35,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define BTSTACK_FILE__ "btstack_port.c"
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <string.h>
|
||||
@ -67,7 +69,7 @@ void hal_cpu_enable_irqs(void){}
|
||||
void hal_cpu_enable_irqs_and_sleep(void){}
|
||||
|
||||
void btstack_main(void);
|
||||
void ble_rx( void ){
|
||||
void btstack_port(void){
|
||||
|
||||
// test code
|
||||
// lptim1_calibration();
|
||||
|
Loading…
x
Reference in New Issue
Block a user