mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-17 20:42:47 +00:00
stm32-sx1280: prepare tx buffers
This commit is contained in:
parent
f0a70bc3dd
commit
f8278fd5f2
@ -244,6 +244,12 @@ static const struct {
|
|||||||
{ 2480000000, 0x73 /* 01110011 */ },
|
{ 2480000000, 0x73 /* 01110011 */ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// tx buffer offset
|
||||||
|
static uint8_t tx_buffer_offset[] = {
|
||||||
|
SX1280_TX0_OFFSET,
|
||||||
|
SX1280_TX1_OFFSET
|
||||||
|
};
|
||||||
|
|
||||||
// hopping context
|
// hopping context
|
||||||
static hopping_t h;
|
static hopping_t h;
|
||||||
|
|
||||||
@ -325,23 +331,26 @@ static struct {
|
|||||||
// transmit sequence number
|
// transmit sequence number
|
||||||
volatile uint8_t transmit_sequence_number;
|
volatile uint8_t transmit_sequence_number;
|
||||||
|
|
||||||
// num queued tx buffers
|
|
||||||
volatile uint8_t num_tx_queued;
|
|
||||||
|
|
||||||
// num completed packets
|
// num completed packets
|
||||||
volatile uint8_t num_completed;
|
volatile uint8_t num_completed;
|
||||||
|
|
||||||
// current outgoing packet
|
// rx queue
|
||||||
ll_pdu_t * tx_pdu;
|
btstack_linked_queue_t rx_queue;
|
||||||
|
|
||||||
// current incoming packet
|
// current incoming packet
|
||||||
ll_pdu_t * rx_pdu;
|
ll_pdu_t * rx_pdu;
|
||||||
|
|
||||||
// tx queue
|
// tx queue of outgoing pdus
|
||||||
btstack_linked_queue_t tx_queue;
|
btstack_linked_queue_t tx_queue;
|
||||||
|
|
||||||
// rx queue
|
// pdus transferred into controller tx buffers
|
||||||
btstack_linked_queue_t rx_queue;
|
ll_pdu_t * tx_buffer_pdu[2];
|
||||||
|
|
||||||
|
// manage tx packets on controller
|
||||||
|
uint8_t num_tx_pdus_on_controller;
|
||||||
|
|
||||||
|
// index of next tx buffer to send
|
||||||
|
uint8_t next_tx_buffer;
|
||||||
|
|
||||||
} ctx;
|
} ctx;
|
||||||
|
|
||||||
@ -362,7 +371,6 @@ static uint32_t ll_scan_window_us;
|
|||||||
static ll_pdu_t * ll_reserved_acl_buffer;
|
static ll_pdu_t * ll_reserved_acl_buffer;
|
||||||
static void (*controller_packet_handler)(uint8_t packet_type, uint8_t * packet, uint16_t size);
|
static void (*controller_packet_handler)(uint8_t packet_type, uint8_t * packet, uint16_t size);
|
||||||
|
|
||||||
static uint8_t empty_packet[2];
|
|
||||||
static uint8_t ll_outgoing_hci_event[258];
|
static uint8_t ll_outgoing_hci_event[258];
|
||||||
static bool ll_send_disconnected;
|
static bool ll_send_disconnected;
|
||||||
static bool ll_send_connection_complete;
|
static bool ll_send_connection_complete;
|
||||||
@ -548,10 +556,13 @@ static void ll_terminate(void){
|
|||||||
ctx.channel_map_update_pending = false;
|
ctx.channel_map_update_pending = false;
|
||||||
// stop sync hop timer
|
// stop sync hop timer
|
||||||
radio_stop_timer();
|
radio_stop_timer();
|
||||||
// free outgoing tx packet
|
// free outgoing tx packets
|
||||||
if ((ctx.tx_pdu != NULL) && (ctx.tx_pdu != &ll_tx_packet)){
|
uint8_t i;
|
||||||
btstack_memory_ll_pdu_free(ctx.tx_pdu);
|
for (i=0;i<2;i++){
|
||||||
ctx.tx_pdu = NULL;
|
if ((ctx.tx_buffer_pdu[i] != NULL) && (ctx.tx_buffer_pdu[i] != &ll_tx_packet)){
|
||||||
|
btstack_memory_ll_pdu_free(ctx.tx_buffer_pdu[i]);
|
||||||
|
ctx.tx_buffer_pdu[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// free queued tx packets
|
// free queued tx packets
|
||||||
while (true){
|
while (true){
|
||||||
@ -568,6 +579,22 @@ static void ll_terminate(void){
|
|||||||
ll_send_disconnected = true;
|
ll_send_disconnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load queued tx pdu into next free tx buffer
|
||||||
|
static void preload_tx_buffer(void){
|
||||||
|
if (ctx.num_tx_pdus_on_controller >= 2) return;
|
||||||
|
|
||||||
|
ll_pdu_t * tx_pdu = (ll_pdu_t *) btstack_linked_queue_dequeue(&ctx.tx_queue);
|
||||||
|
if (tx_pdu == NULL) return;
|
||||||
|
|
||||||
|
const uint16_t max_packet_len = 2 + 27;
|
||||||
|
uint8_t index = (ctx.next_tx_buffer + ctx.num_tx_pdus_on_controller) & 1;
|
||||||
|
ctx.tx_buffer_pdu[index] = tx_pdu;
|
||||||
|
SX1280HalWriteBuffer( tx_buffer_offset[index], (uint8_t *) &ctx.tx_buffer_pdu[index]->header, max_packet_len);
|
||||||
|
|
||||||
|
ctx.num_tx_pdus_on_controller++;
|
||||||
|
// printf("preload %u bytes into %u\n", ctx.tx_buffer_pdu[index]->len, index);
|
||||||
|
}
|
||||||
|
|
||||||
static void radio_timer_handler(void){
|
static void radio_timer_handler(void){
|
||||||
|
|
||||||
uint16_t t0 = hal_timer_get_ticks();
|
uint16_t t0 = hal_timer_get_ticks();
|
||||||
@ -606,6 +633,9 @@ static void radio_timer_handler(void){
|
|||||||
ctx.synced = false;
|
ctx.synced = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preload tx pdu
|
||||||
|
preload_tx_buffer();
|
||||||
|
|
||||||
if (ctx.synced){
|
if (ctx.synced){
|
||||||
// restart radio timer (might get overwritten by first packet)
|
// restart radio timer (might get overwritten by first packet)
|
||||||
radio_set_timer_ticks(ctx.conn_sync_hop_ticks);
|
radio_set_timer_ticks(ctx.conn_sync_hop_ticks);
|
||||||
@ -666,11 +696,12 @@ static void radio_on_tx_done(void ){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (ll_state){
|
switch (ll_state){
|
||||||
case LL_STATE_CONNECTED:
|
case LL_STATE_CONNECTED:
|
||||||
radio_fetch_rx_pdu();
|
radio_fetch_rx_pdu();
|
||||||
break;
|
preload_tx_buffer();
|
||||||
default:
|
break;
|
||||||
break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,67 +726,69 @@ static void radio_on_rx_done(void ){
|
|||||||
|
|
||||||
} else if (ll_state == LL_STATE_CONNECTED){
|
} else if (ll_state == LL_STATE_CONNECTED){
|
||||||
|
|
||||||
bool tx_acked;
|
// get and parse rx pdu header
|
||||||
|
|
||||||
uint8_t sequence_number;
|
|
||||||
uint8_t next_expected_sequence_number;
|
|
||||||
// uint8_t more_data;
|
|
||||||
|
|
||||||
uint8_t rx_buffer[2];
|
uint8_t rx_buffer[2];
|
||||||
SX1280HalReadBuffer( SX1280_RX0_OFFSET, rx_buffer, 2);
|
SX1280HalReadBuffer( SX1280_RX0_OFFSET, rx_buffer, 2);
|
||||||
uint8_t rx_header = rx_buffer[0];
|
uint8_t rx_header = rx_buffer[0];
|
||||||
uint8_t rx_len = rx_buffer[1];
|
uint8_t rx_len = rx_buffer[1];
|
||||||
|
uint8_t next_expected_sequence_number = (rx_header >> 2) & 1;
|
||||||
// parse header
|
uint8_t sequence_number = (rx_header >> 3) & 1;
|
||||||
next_expected_sequence_number = (rx_header >> 2) & 1;
|
// more data field not used yet
|
||||||
sequence_number = (rx_header >> 3) & 1;
|
// uint8_t more_data = (rx_packet->header >> 4) & 1;
|
||||||
// more_data = (rx_packet->header >> 4) & 1;
|
|
||||||
|
|
||||||
// update state
|
// update state
|
||||||
ctx.next_expected_sequence_number = 1 - sequence_number;
|
ctx.next_expected_sequence_number = 1 - sequence_number;
|
||||||
|
|
||||||
// tx packet ack'ed?
|
// report outgoing packet as ack'ed and free if confirmed by peer
|
||||||
tx_acked = ctx.transmit_sequence_number != next_expected_sequence_number;
|
bool tx_acked = ctx.transmit_sequence_number != next_expected_sequence_number;
|
||||||
if (tx_acked){
|
if (tx_acked){
|
||||||
if ((ctx.tx_pdu != NULL) && (ctx.tx_pdu != &ll_tx_packet)){
|
if (ctx.num_tx_pdus_on_controller > 0){
|
||||||
btstack_memory_ll_pdu_free(ctx.tx_pdu);
|
btstack_assert(ctx.tx_buffer_pdu[ctx.next_tx_buffer] != NULL);
|
||||||
ctx.num_completed++;
|
// if non link-layer packet, free buffer and report as completed
|
||||||
}
|
if (ctx.tx_buffer_pdu[ctx.next_tx_buffer] != &ll_tx_packet){
|
||||||
ctx.tx_pdu = (ll_pdu_t *) btstack_linked_queue_dequeue(&ctx.tx_queue);
|
btstack_memory_ll_pdu_free(ctx.tx_buffer_pdu[ctx.next_tx_buffer]);
|
||||||
|
ctx.tx_buffer_pdu[ctx.next_tx_buffer] = NULL;
|
||||||
|
ctx.num_completed++;
|
||||||
|
}
|
||||||
|
// next buffer
|
||||||
|
ctx.num_tx_pdus_on_controller--;
|
||||||
|
ctx.next_tx_buffer = (ctx.next_tx_buffer + 1 ) & 1;
|
||||||
|
}
|
||||||
ctx.transmit_sequence_number = next_expected_sequence_number;
|
ctx.transmit_sequence_number = next_expected_sequence_number;
|
||||||
}
|
}
|
||||||
// refill
|
|
||||||
if (ctx.tx_pdu == NULL){
|
|
||||||
ctx.tx_pdu = (ll_pdu_t *) btstack_linked_queue_dequeue(&ctx.tx_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// restart supervision timeout
|
// restart supervision timeout
|
||||||
ctx.time_without_any_packets_us = 0;
|
ctx.time_without_any_packets_us = 0;
|
||||||
|
|
||||||
// check clock if we can sent a full packet before sync hop
|
// check if we can sent a full packet before sync hop
|
||||||
int16_t now_ticks = packet_end_ticks - ctx.anchor_ticks;
|
int16_t now_ticks = packet_end_ticks - ctx.anchor_ticks;
|
||||||
if (ctx.synced && (now_ticks > ctx.conn_latest_tx_ticks)){
|
if (ctx.synced && (now_ticks > ctx.conn_latest_tx_ticks)){
|
||||||
// abort sending of next packet / AutoTx
|
// disable AutoTX to abort sending of next packet
|
||||||
Radio.SetFs();
|
Radio.SetFs();
|
||||||
printf("Close before Sync hop: now %u > %u\n", now_ticks, ctx.conn_latest_tx_ticks);
|
log_info("Close before Sync hop: now %u > %u", now_ticks, ctx.conn_latest_tx_ticks);
|
||||||
|
|
||||||
// get rx pdu
|
// get rx pdu and
|
||||||
radio_fetch_rx_pdu();
|
radio_fetch_rx_pdu();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// tx packet ready?
|
// setup empty packet in ll buffer if no tx packet was preloaded
|
||||||
uint16_t max_packet_len = 2 + 27;
|
if (ctx.num_tx_pdus_on_controller == 0) {
|
||||||
if (ctx.tx_pdu == NULL){
|
ctx.tx_buffer_pdu[ctx.next_tx_buffer] = &ll_tx_packet;
|
||||||
empty_packet[0] = (ctx.transmit_sequence_number << 3) | (ctx.next_expected_sequence_number << 2) | PDU_DATA_LLID_DATA_CONTINUE;
|
ctx.num_tx_pdus_on_controller++;
|
||||||
empty_packet[1] = 0;
|
ll_tx_packet.header = PDU_DATA_LLID_DATA_CONTINUE;
|
||||||
SX1280HalWriteBuffer( SX1280_TX0_OFFSET, empty_packet, max_packet_len );
|
ll_tx_packet.len = 0;
|
||||||
} else {
|
}
|
||||||
uint8_t md = btstack_linked_queue_empty(&ctx.tx_queue) ? 0 : 1;
|
|
||||||
ctx.tx_pdu->header |= (md << 4) | (ctx.transmit_sequence_number << 3) | (ctx.next_expected_sequence_number << 2);
|
// setup pdu header
|
||||||
SX1280HalWriteBuffer( SX1280_TX0_OFFSET, (uint8_t *) &ctx.tx_pdu->header, max_packet_len );
|
uint8_t packet_header[2];
|
||||||
}
|
uint8_t md = btstack_linked_queue_empty(&ctx.tx_queue) ? 0 : 1;
|
||||||
|
packet_header[0] = (md << 4) | (ctx.transmit_sequence_number << 3) | (ctx.next_expected_sequence_number << 2) | ctx.tx_buffer_pdu[ctx.next_tx_buffer]->header;
|
||||||
|
packet_header[1] = ctx.tx_buffer_pdu[ctx.next_tx_buffer]->len;
|
||||||
|
|
||||||
|
// select outgoing tx buffer and update pdu header
|
||||||
|
SX1280SetBufferBaseAddresses( tx_buffer_offset[ctx.next_tx_buffer], SX1280_RX0_OFFSET);
|
||||||
|
SX1280HalWriteBuffer( tx_buffer_offset[ctx.next_tx_buffer], (uint8_t *) packet_header, sizeof(packet_header));
|
||||||
|
|
||||||
// update operating state
|
// update operating state
|
||||||
SX1280AutoTxWillStart();
|
SX1280AutoTxWillStart();
|
||||||
@ -774,7 +807,7 @@ static void radio_on_rx_done(void ){
|
|||||||
|
|
||||||
ctx.packet_nr_in_connection_event++;
|
ctx.packet_nr_in_connection_event++;
|
||||||
|
|
||||||
printf("RX %02x\n", rx_header);
|
printf("RX %02x -- tx buffer %u, %02x %02x\n", rx_header, ctx.next_tx_buffer, packet_header[0], packet_header[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,6 +1000,9 @@ static void ll_handle_conn_ind(ll_pdu_t * rx_packet){
|
|||||||
big_endian_store_16(buf, 0, AUTO_RX_TX_TIME_US);
|
big_endian_store_16(buf, 0, AUTO_RX_TX_TIME_US);
|
||||||
SX1280HalWriteCommand( RADIO_SET_AUTOTX, buf, 2 );
|
SX1280HalWriteCommand( RADIO_SET_AUTOTX, buf, 2 );
|
||||||
|
|
||||||
|
// pre-load tx pdu
|
||||||
|
preload_tx_buffer();
|
||||||
|
|
||||||
// get next packet
|
// get next packet
|
||||||
ll_state = LL_STATE_CONNECTED;
|
ll_state = LL_STATE_CONNECTED;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user