Commit ce74686d authored by Reto Da Forno's avatar Reto Da Forno
Browse files

Merge branch 'feature-max-payload-len'

parents b99db325 7566dc02
......@@ -581,7 +581,7 @@ static command_return_t gloria_rx_command_handler(command_execution_t execution)
flood.max_acks = macks;
flood.data_slots = slots;
flood.payload = message;
flood.initial = false;
flood.initiator = false;
flood.rx_timeout = cad * HS_TIMER_FREQUENCY_MS;
flood.sync_timer = (bool) sync;
flood.lp_listening = lp_listening;
......@@ -717,7 +717,7 @@ static command_return_t gloria_tx_command_handler(command_execution_t execution)
flood.max_acks = macks;
flood.data_slots = slots;
flood.payload = message;
flood.initial = true;
flood.initiator = true;
if (cont) {
tx_period = txper;
......@@ -737,7 +737,7 @@ static void sync_callback() {
}
static void gloria_cont_callback() {
if (flood.initial) {
if (flood.initiator) {
gloria_last_sync = flood.marker;
}
if (flood.msg_received) {
......@@ -753,7 +753,7 @@ static void gloria_cont_callback() {
flood.guard_time = guard_time * HS_TIMER_FREQUENCY_US;
flood.flood_idx++;
if (!flood.initial || flood.flood_idx < iterations) {
if (!flood.initiator || flood.flood_idx < iterations) {
gloria_run_flood(&flood, &gloria_cont_callback);
}
}
......@@ -762,7 +762,7 @@ static void gloria_finish_callback() {
if (flood.msg_received) {
hs_timer_generic(flood.reconstructed_marker + gloria_calculate_flood_time(flood.payload_size, flood.modulation, flood.data_slots, flood.header.sync, flood.ack_mode) + 50*HS_TIMER_FREQUENCY_MS, &sync_callback);
}
if (flood.initial) {
if (flood.initiator) {
gloria_last_sync = flood.marker;
}
......@@ -817,7 +817,7 @@ void gloria_print_flood(gloria_flood_t *print_flood) {
goto end;
}
if (cJSON_AddBoolToObject(flood_result, "initial", print_flood->initial) == NULL) {
if (cJSON_AddBoolToObject(flood_result, "initiator", print_flood->initiator) == NULL) {
goto end;
}
......
......@@ -222,10 +222,10 @@ bool elwb_update_slot_durations(uint8_t n_tx_arg, uint8_t num_hops_arg)
if (!num_hops_arg) {
num_hops_arg = num_hops;
}
uint32_t t_sched_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, (ELWB_CONF_MAX_DATA_SLOTS * sizeof(uint16_t) + ELWB_SCHED_HDR_LEN + ELWB_SCHED_CRC_LEN));
uint32_t t_data_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, ELWB_CONF_MAX_PAYLOAD_LEN + ELWB_PKT_HDR_LEN);
uint32_t t_sched_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, ELWB_MAX_SCHED_PKT_LEN);
uint32_t t_data_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, ELWB_MAX_DATA_PKT_LEN);
uint32_t t_cont_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, MAX(ELWB_REQ_PKT_LEN, ELWB_2ND_SCHED_LEN) + ELWB_PKT_HDR_LEN);
uint32_t t_dack_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, (ELWB_CONF_MAX_DATA_SLOTS + 7) / 8 + ELWB_PKT_HDR_LEN);
uint32_t t_dack_new = GLORIA_INTERFACE_FLOOD_DURATION(n_tx_arg, num_hops_arg, ELWB_MAX_DACK_PKT_LEN);
if (is_host && !elwb_sched_check_params(0, t_sched_new, t_cont_new, t_data_new)) {
return false;
......@@ -292,7 +292,7 @@ static void elwb_update_rssi_snr(void)
}
static bool elwb_bootstrap_sched_pkt_filter(uint8_t* pkt, uint8_t len)
static bool elwb_bootstrap_sched_pkt_filter(const uint8_t* gloria_hdr, uint8_t hdr_len, const uint8_t* pkt, uint8_t len)
{
if ((len > ELWB_PKT_HDR_LEN) && ELWB_IS_PKT_HEADER_VALID((elwb_packet_t*)pkt) && ELWB_IS_SCHEDULE_PACKET((elwb_packet_t*)pkt) && ELWB_SCHED_IS_FIRST((elwb_schedule_t*)pkt)) {
return true;
......@@ -300,6 +300,7 @@ static bool elwb_bootstrap_sched_pkt_filter(uint8_t* pkt, uint8_t len)
return false;
}
static bool elwb_is_schedule_valid(elwb_schedule_t* schedule)
{
if (!gloria_is_t_ref_updated() || !ELWB_IS_PKT_HEADER_VALID(schedule) || !ELWB_IS_SCHEDULE_PACKET(schedule) || (gloria_get_payload_len() < (ELWB_SCHED_HDR_LEN + ELWB_SCHED_CRC_LEN))) {
......@@ -315,12 +316,13 @@ static void elwb_bootstrap(void)
stats.bootstrap_cnt++;
LOG_VERBOSE("bootstrap");
elwb_time_t bootstrap_timeout = ELWB_TIMER_NOW() + ELWB_CONF_BOOTSTRAP_TIMEOUT;
/* keep listening until we receive a valid schedule packet */
do {
gloria_register_flood_callback(elwb_schedule_received_callback);
gloria_set_pkt_filter(elwb_bootstrap_sched_pkt_filter);
gloria_start(false, (uint8_t*)&schedule, 0, n_tx, 1);
elwb_wait_until(ELWB_TIMER_NOW() + t_sched);
gloria_start(false, (uint8_t*)&schedule, ELWB_MAX_SCHED_PKT_LEN, n_tx, 1);
elwb_wait_until(ELWB_TIMER_NOW() + ELWB_S_TO_TICKS(ELWB_CONF_SCHED_PERIOD) + t_sched);
gloria_stop();
if (ELWB_TIMER_NOW() > bootstrap_timeout) {
/* go to sleep for ELWB_CONF_T_DEEPSLEEP ticks */
......@@ -368,7 +370,7 @@ static void elwb_send_schedule(elwb_time_t start_of_round)
static void elwb_receive_schedule(elwb_time_t start_of_round)
{
gloria_start(false, (uint8_t*)&schedule, 0, n_tx, 1);
gloria_start(false, (uint8_t*)&schedule, ELWB_MAX_SCHED_PKT_LEN, n_tx, 1);
elwb_wait_until(start_of_round + t_sched + ELWB_CONF_T_GUARD_ROUND);
gloria_stop();
......@@ -528,8 +530,8 @@ static void elwb_send_packet(elwb_time_t slot_start, uint32_t slot_length, uint3
static void elwb_receive_packet(elwb_time_t slot_start, uint32_t slot_length, uint32_t slot_idx)
{
uint8_t packet_len = 0;
bool data_packet = ELWB_SCHED_HAS_DATA_SLOTS(&schedule);
uint8_t packet_len = ELWB_MAX_DATA_PKT_LEN;
bool data_packet = ELWB_SCHED_HAS_DATA_SLOTS(&schedule);
if (!data_packet) {
/* the packet length is known in the request round */
......@@ -588,7 +590,7 @@ static void elwb_receive_packet(elwb_time_t slot_start, uint32_t slot_length, ui
/* data acknowledgment slot */
static void elwb_data_ack(elwb_time_t slot_start)
{
uint8_t packet_len = 0;
uint8_t packet_len = ELWB_MAX_DACK_PKT_LEN;
if (is_host) {
/* acknowledge each received packet of the last round */
......@@ -671,6 +673,7 @@ static void elwb_data_ack(elwb_time_t slot_start)
static void elwb_contention(elwb_time_t slot_start, bool node_registered)
{
const uint8_t packet_len = ELWB_REQ_PKT_LEN + ELWB_PKT_HDR_LEN;
packet.cont.node_id = 0;
/* if there is data in the output buffer, then request a slot */
......@@ -1049,18 +1052,6 @@ void elwb_start(void)
(uint32_t)ELWB_TICKS_TO_MS(t_cont));
elwb_running = true;
/* instead of calling elwb_run(), schedule the start */
#if ELWB_CONF_STARTUP_DELAY > 0
elwb_time_t starttime = ELWB_MS_TO_TICKS(ELWB_CONF_STARTUP_DELAY);
if (is_host) {
starttime += ELWB_CONF_T_GUARD_ROUND; /* delay the host by ELWB_CONF_T_GUARD_ROUND */
}
if (ELWB_TIMER_NOW() < starttime) {
elwb_wait_until(starttime);
}
#endif /* ELWB_CONF_STARTUP_DELAY */
elwb_run();
}
......
......@@ -140,10 +140,6 @@
#define ELWB_CONF_CONT_TH 1
#endif /* ELWB_CONF_CONT_TH */
#ifndef ELWB_CONF_STARTUP_DELAY
#define ELWB_CONF_STARTUP_DELAY 1000 /* delay in milliseconds from the start of the MCU */
#endif /* ELWB_CONF_STARTUP_DELAY */
/* use more accurate high frequency reference clock to schedule the contention slot
* (requires an implementation of ELWB_GLORIA_GET_T_REF_HF()) */
#ifndef ELWB_CONF_CONT_USE_HSTIMER
......@@ -162,7 +158,10 @@
#define ELWB_SCHED_PERIOD_MAX_S (ULONG_MAX / ELWB_TIMER_FREQUENCY) /* max period in seconds */
#define ELWB_NETWORK_ID_BITMASK 0x7fff
#define ELWB_PKT_TYPE_BITMASK 0x8000
#define ELWB_PKT_BUFFER_SIZE GLORIA_INTERFACE_MAX_PAYLOAD_LEN /* must be at least as large as the gloria interface buffer */
#define ELWB_PKT_BUFFER_SIZE GLORIA_INTERFACE_MAX_PAYLOAD_LEN
#define ELWB_MAX_SCHED_PKT_LEN (ELWB_SCHED_HDR_LEN + ELWB_CONF_MAX_DATA_SLOTS * sizeof(uint16_t) + ELWB_SCHED_CRC_LEN)
#define ELWB_MAX_DATA_PKT_LEN (ELWB_PKT_HDR_LEN + ELWB_CONF_MAX_PAYLOAD_LEN)
#define ELWB_MAX_DACK_PKT_LEN (ELWB_PKT_HDR_LEN + (ELWB_CONF_MAX_DATA_SLOTS + 7) / 8)
/*---------------------------------------------------------------------------*/
......@@ -236,10 +235,11 @@
#define ELWB_TIMER_STOP() lptimer_set(0, 0)
#define ELWB_TIMER_HS_SET(t, cb) hs_timer_schedule_start(t, cb) /* high-speed timer */
#define ELWB_TICKS_TO_S(t) ((t) / ELWB_TIMER_FREQUENCY)
#define ELWB_TICKS_TO_MS(t) ((t) * 1000UL / ELWB_TIMER_FREQUENCY)
#define ELWB_TICKS_TO_MS(t) ((t) * 1000ULL / ELWB_TIMER_FREQUENCY)
#define ELWB_TICKS_TO_US(t) ((uint64_t)(t) * 1000000ULL / ELWB_TIMER_FREQUENCY)
#define ELWB_MS_TO_TICKS(ms) ((uint64_t)(ms) * ELWB_TIMER_FREQUENCY / 1000UL)
#define ELWB_S_TO_TICKS(s) ((uint64_t)(s) * ELWB_TIMER_FREQUENCY)
#define ELWB_MS_TO_TICKS(ms) ((uint64_t)(ms) * ELWB_TIMER_FREQUENCY / 1000ULL)
#define ELWB_US_TO_TICKS(us) ((uint64_t)(us) * ELWB_TIMER_FREQUENCY / 1000000ULL)
/* message passing */
#ifndef ELWB_QUEUE_SIZE
......
/*
* Copyright (c) 2018 - 2021, ETH Zurich, Computer Engineering Group (TEC)
* Copyright (c) 2018 - 2022, ETH Zurich, Computer Engineering Group (TEC)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -32,41 +32,36 @@
#if GLORIA_ENABLE
extern volatile uint64_t gloria_last_sync;
gloria_flood_t* current_flood = NULL;
static void (*flood_callback)();
static gloria_flood_t* current_flood = NULL;
static gloria_flood_cb_t flood_callback = NULL;
static void gloria_rx_callback(uint8_t* payload, uint8_t size);
static void gloria_process_rx(uint8_t* payload, uint8_t size);
static void gloria_tx_callback();
static void gloria_process_slot();
static void gloria_finish_slot();
static void gloria_tx_callback(void);
static void gloria_process_slot(void);
static void gloria_finish_slot(void);
/*
* initialize the necessary flood and message header parameters
* start the flood
*/
void gloria_run_flood(gloria_flood_t* flood, void (*callback)())
void gloria_run_flood(gloria_flood_t* flood, gloria_flood_cb_t callback)
{
current_flood = flood;
flood_callback = callback;
// initialize flood parameters
current_flood->first_rx_index = ((current_flood->ack_mode ? -2 : -1));
current_flood->header.protocol_id = PROTOCOL_ID_GLORIA;
current_flood->header.type = 0;
current_flood->header.slot_index = 0;
current_flood->msg_received = current_flood->initial;
current_flood->last_active_slot = gloria_calculate_last_active_slot(current_flood);
current_flood->first_rx_index = (current_flood->ack_mode ? -2 : -1);
current_flood->header.protocol_id = PROTOCOL_ID_GLORIA;
current_flood->header.type = GLORIA_PKT_TYPE_DATA;
current_flood->header.slot_index = 0;
current_flood->msg_received = current_flood->initiator;
current_flood->last_active_slot = gloria_calculate_last_active_slot(current_flood);
current_flood->rem_retransmissions = current_flood->max_retransmissions;
current_flood->ack_message.protocol_id = PROTOCOL_ID_GLORIA;
current_flood->ack_message.type = 0;
current_flood->ack_message.type = GLORIA_PKT_TYPE_ACK;
current_flood->ack_message.sync = 0;
current_flood->ack_message.dst = 0;
current_flood->ack_counter = 0;
......@@ -74,16 +69,18 @@ void gloria_run_flood(gloria_flood_t* flood, void (*callback)())
// calculate the message size; always needed for the initiator; other nodes need it for low power listening
current_flood->header_size = (current_flood->ack_mode ? GLORIA_HEADER_LENGTH : GLORIA_HEADER_LENGTH_MIN);
uint8_t max_packet_len = current_flood->header_size + current_flood->payload_size + GLORIA_TIMESTAMP_LENGTH;
// calculate the message size for the initiator, initialize markers
if (current_flood->initial) {
if (current_flood->initiator) {
current_flood->received_marker = flood->marker;
current_flood->reconstructed_marker = flood->marker;
// add timestamp for sync floods
if (current_flood->header.sync) {
uint64_t new_timestamp = current_flood->received_marker / GLORIA_SCHEDULE_GRANULARITY;
memcpy(current_flood->payload + current_flood->payload_size, (uint8_t*) &new_timestamp, GLORIA_TIMESTAMP_LENGTH);
memcpy(current_flood->ack_mode ? current_flood->header.ext.timestamp : current_flood->header.min.timestamp, (uint8_t*)&new_timestamp, GLORIA_TIMESTAMP_LENGTH);
current_flood->header_size += GLORIA_TIMESTAMP_LENGTH;
}
}
else {
......@@ -98,7 +95,7 @@ void gloria_run_flood(gloria_flood_t* flood, void (*callback)())
slot_time = gloria_calculate_slot_time(current_flood->modulation, current_flood->ack_mode, 1, GLORIA_ACK_LENGTH);
}
else {
slot_time = gloria_calculate_slot_time(current_flood->modulation, current_flood->ack_mode, 0, current_flood->payload_size + current_flood->header_size + current_flood->header.sync * GLORIA_TIMESTAMP_LENGTH);
slot_time = gloria_calculate_slot_time(current_flood->modulation, current_flood->ack_mode, 0, current_flood->header_size + current_flood->payload_size);
}
if (slot_time < rx2rx_trans + gloria_calculate_rx_timeout(current_flood)) {
......@@ -120,7 +117,7 @@ void gloria_run_flood(gloria_flood_t* flood, void (*callback)())
// initialize message header
if (current_flood->ack_mode) {
current_flood->header.src = (current_flood->initial ? current_flood->node_id : 0);
current_flood->header.ext.src = (current_flood->initiator ? current_flood->node_id : 0);
}
// initialize error flags
......@@ -128,19 +125,12 @@ void gloria_run_flood(gloria_flood_t* flood, void (*callback)())
current_flood->crc_timeout = false;
// set radio config
radio_set_config_tx(current_flood->modulation, current_flood->band, current_flood->power, -1, -1, -1, false, true);
radio_set_config_rx(current_flood->modulation, current_flood->band, -1, -1, -1, 0, false, 0, true, false);
radio_set_config(current_flood->modulation, current_flood->band, current_flood->power, max_packet_len);
gloria_process_slot();
}
void gloria_update()
{
//gloria_print_flood_periodic();
}
void gloria_process_slot()
{
if (current_flood->stop) {
......@@ -178,49 +168,61 @@ void gloria_process_slot()
static void gloria_rx_callback(uint8_t* payload, uint8_t size)
{
if (payload == NULL || size == 0) {
gloria_finish_slot();
}
else if (size == GLORIA_ACK_LENGTH) {
gloria_ack_msg_t* ack_message = (gloria_ack_msg_t*) payload;
if (ack_message->dst) {
current_flood->acked = true;
current_flood->ack_message.dst = ack_message->dst;
// prevent ack destination from retransmitting the ack message (ack_mode 2)
// prevent nodes that have not yet sent the message from retransmitting acks (ack mode 1)
if (!current_flood->msg_received || ((current_flood->ack_mode == 2) && ack_message->dst == current_flood->node_id) ||
((current_flood->ack_mode == 1) && (current_flood->header.slot_index - current_flood->first_rx_index == 1))) {
// increase slot index to be consistent with other flood ends
current_flood->header.slot_index++;
// finish flood
flood_callback();
return;
}
if (payload && size > 0) {
switch (((gloria_header_t*)payload)->type) {
case GLORIA_PKT_TYPE_ACK:
{
gloria_ack_msg_t* ack_message = (gloria_ack_msg_t*)payload;
if (ack_message->dst) {
current_flood->acked = true;
current_flood->ack_message.dst = ack_message->dst;
// prevent ack destination from retransmitting the ack message (ack_mode 2)
// prevent nodes that have not yet sent the message from retransmitting acks (ack mode 1)
if (!current_flood->msg_received || ((current_flood->ack_mode == 2) && ack_message->dst == current_flood->node_id) ||
((current_flood->ack_mode == 1) && (current_flood->header.slot_index - current_flood->first_rx_index == 1))) {
// increase slot index to be consistent with other flood ends
current_flood->header.slot_index++;
// finish flood
flood_callback();
return;
}
}
} break;
case GLORIA_PKT_TYPE_DATA:
if (size >= current_flood->header_size) {
gloria_process_rx(payload, size);
}
break;
default:
LOG_WARNING("unknown gloria packet type");
break;
}
gloria_finish_slot();
}
else if (size >= current_flood->header_size) {
gloria_process_rx(payload, size);
}
else {
gloria_finish_slot();
}
gloria_finish_slot();
}
static void gloria_process_rx(uint8_t* payload, uint8_t size)
{
gloria_header_t* header = (gloria_header_t*) payload;
gloria_header_t* header = (gloria_header_t*)payload;
if (!current_flood->msg_received) {
// the size of the actual payload is the message size minus the header length and for sync floods minus the timestamp length
current_flood->payload_size = size - current_flood->header_size - current_flood->header.sync * GLORIA_TIMESTAMP_LENGTH;
// copy the header
memcpy((uint8_t*)&current_flood->header, payload, current_flood->header_size);
// the size of the actual payload is the message size minus the header length
// NOTE: the received payload must not exceed the specified max. payload length on the receiver
current_flood->payload_size = MIN(current_flood->payload_size, size - current_flood->header_size);
current_flood->msg_received = true;
memcpy(current_flood->payload, payload + current_flood->header_size, size - current_flood->header_size);
memcpy(current_flood->payload, payload + current_flood->header_size, current_flood->payload_size);
current_flood->header.slot_index = header->slot_index;
//current_flood->header.slot_index = header->slot_index;
gloria_reconstruct_flood_marker(current_flood);
// make sure the timer is only synced if the flood contains a timestamp
......@@ -242,10 +244,10 @@ static void gloria_process_rx(uint8_t* payload, uint8_t size)
current_flood->guard_time = 0; // set guard time to 0 as node is now synced to this flood
// check if node is also the destination
if (current_flood->ack_mode && (header->dst == current_flood->node_id)) {
if (current_flood->ack_mode && (header->ext.dst == current_flood->node_id)) {
// prepare ack if flood should be acked
current_flood->acked = true;
current_flood->ack_message.dst = header->src;
current_flood->ack_message.dst = header->ext.src;
}
if (!current_flood->ack_mode) {
......@@ -253,8 +255,6 @@ static void gloria_process_rx(uint8_t* payload, uint8_t size)
current_flood->header.slot_index += current_flood->tx_delay_slots;
}
}
gloria_finish_slot();
}
......
/*
* Copyright (c) 2018 - 2021, ETH Zurich, Computer Engineering Group (TEC)
* Copyright (c) 2018 - 2022, ETH Zurich, Computer Engineering Group (TEC)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -47,7 +47,7 @@
#include "protocol/gloria/gloria_interface.h"
void gloria_run_flood(gloria_flood_t* flood, void (*callback)());
void gloria_update();
void gloria_run_flood(gloria_flood_t* flood, gloria_flood_cb_t callback);
#endif /* PROTOCOL_GLORIA_GLORIA_H_ */
/*
* Copyright (c) 2018 - 2021, ETH Zurich, Computer Engineering Group (TEC)
* Copyright (c) 2018 - 2022, ETH Zurich, Computer Engineering Group (TEC)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -28,94 +28,92 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* THIS FILE HAS BEEN AUTOGENERATED BY FLORA-TOOLS */
#include "flora_lib.h"
const uint8_t gloria_modulations[] = {3,5,7,9};
const int8_t gloria_powers[] = {0,10,22}; // dBm
const uint8_t gloria_default_power_levels[] = {0,0,0,0,0,0,0,0,2,2}; // see radio_powers
const uint8_t gloria_default_retransmissions[] = {3,3,3,3,3,3,3,3,3,3,3};
const uint8_t gloria_default_acks[] = {3,3,3,3,3,3,3,3,3,3,3};
const uint8_t gloria_default_data_slots[] = {4,4,4,4,8,8,12,12,16,16,16};
const uint8_t gloria_modulations[] = { 3, 5, 7, 9 };
const int8_t gloria_powers[] = { 0, 10, 22 }; // dBm
const uint8_t gloria_default_power_levels[] = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2 }; // see radio_powers
const uint8_t gloria_default_retransmissions[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
const uint8_t gloria_default_acks[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
const uint8_t gloria_default_data_slots[] = { 4, 4, 4, 4, 8, 8, 12, 12, 16, 16, 16 };
const gloria_timings_t gloria_timings[] = {
{ // 0 (SF12)
.slotOverhead = 4179556, // 522.444 ms
.slotAckOverhead = 4965988, // 620.749 ms
.floodInitOverhead = 795938, // 99.492 ms
.rxOffset = 786432, // 98.304 ms
.txSync = 6078848, // 759.856 ms (updated 20200812)
.slotOverhead = 4179556, // 522.444 ms
.slotAckOverhead = 4965988, // 620.749 ms
.floodInitOverhead = 795938, // 99.492 ms
.rxOffset = 786432, // 98.304 ms
.txSync = 6078848, // 759.856 ms (updated 20200812)
},
{ // 1 (SF11)
.slotOverhead = 2132075, // 266.509 ms
.slotAckOverhead = 2525291, // 315.661 ms
.floodInitOverhead = 402722, // 50.340 ms
.rxOffset = 393216, // 49.152 ms
.txSync = 3032500, // 379.063 ms (updated 20200812)
.slotOverhead = 2132075, // 266.509 ms
.slotAckOverhead = 2525291, // 315.661 ms
.floodInitOverhead = 402722, // 50.340 ms
.rxOffset = 393216, // 49.152 ms
.txSync = 3032500, // 379.063 ms (updated 20200812)
},
{ // 2 (SF10)
.slotOverhead = 1050062, // 131.258 ms
.slotAckOverhead = 1246670, // 155.834 ms
.floodInitOverhead = 206114, // 25.764 ms
.rxOffset = 196608, // 24.576 ms
.txSync = 1513412, // 189.177 ms (updated 20200812)
.slotOverhead = 1050062, // 131.258 ms
.slotAckOverhead = 1246670, // 155.834 ms
.floodInitOverhead = 206114, // 25.764 ms
.rxOffset = 196608, // 24.576 ms
.txSync = 1513412, // 189.177 ms (updated 20200812)
},
{ // 3 (SF9)
.slotOverhead = 537151, // 67.144 ms
.slotAckOverhead = 635455, // 79.432 ms
.floodInitOverhead = 107810, // 13.476 ms
.rxOffset = 98304, // 12.288 ms
.txSync = 755928, // 94.491 ms (updated 20200812)
.slotOverhead = 537151, // 67.144 ms
.slotAckOverhead = 635455, // 79.432 ms
.floodInitOverhead = 107810, // 13.476 ms
.rxOffset = 98304, // 12.288 ms
.txSync = 755928, // 94.491 ms (updated 20200812)
},
{ // 4 (SF8)
.slotOverhead = 283375, // 35.422 ms
.slotAckOverhead = 332527, // 41.566 ms
.floodInitOverhead = 58658, // 7.332 ms
.rxOffset = 49152, // 6.144 ms
.txSync = 378216, // 47.277 ms (updated 20200812)
.slotOverhead = 283375, // 35.422 ms
.slotAckOverhead = 332527, // 41.566 ms
.floodInitOverhead = 58658, // 7.332 ms
.rxOffset = 49152, // 6.144 ms
.txSync = 378216, // 47.277 ms (updated 20200812)
},
{ // 5 (SF7)
.slotOverhead = 153639, // 19.205 ms
.slotAckOverhead = 178215, // 22.277 ms
.floodInitOverhead = 34082, // 4.260 ms
.rxOffset = 24576, // 3.072 ms
.txSync = 189864, // 23.733 ms (updated 20200812)
.slotOverhead = 153639, // 19.205 ms
.slotAckOverhead = 178215, // 22.277 ms
.floodInitOverhead = 34082, // 4.260 ms
.rxOffset = 24576, // 3.072 ms
.txSync = 189864, // 23.733 ms (updated 20200812)
},
{ // 6 (SF6)
.slotOverhead = 79827, // 9.978 ms
.slotAckOverhead = 102827, // 12.853 ms
.floodInitOverhead = 32507, // 4.063 ms
.rxOffset = 23001, // 2.875 ms
.txSync = 112356, // 14.045 ms (updated 20200812)
.slotOverhead = 79827, // 9.978 ms
.slotAckOverhead = 102827, // 12.853 ms
.floodInitOverhead = 32507, // 4.063 ms
.rxOffset = 23001, // 2.875 ms
.txSync = 112356, // 14.045 ms (updated 20200812)
},
{ // 7 (SF5)
.slotOverhead = 50171, // 6.271 ms
.slotAckOverhead = 61672, // 7.709 ms
.floodInitOverhead = 21007, // 2.626 ms
.rxOffset = 11500, // 1.438 ms
.txSync = 57316, // 7.165 ms (updated 20200812)
.slotOverhead = 50171, // 6.271 ms
.slotAckOverhead = 61672, // 7.709 ms
.floodInitOverhead = 21007, // 2.626 ms
.rxOffset = 11500, // 1.438 ms
.txSync = 57316, // 7.165 ms (updated 20200812)
},
{ // 8 (FSK 125k)
.slotOverhead = 28000, // 3.5 ms (adapted by kelmicha)
.slotAckOverhead = 28000, // 3.5 ms (adapted by kelmicha)
.floodInitOverhead = 18000, // 2.25 ms
.rxOffset = 4096, // 512.000 us
.txSync = 4137, // 517.125 us (updated 20200812)
.slotOverhead = 28000, // 3.5 ms
.slotAckOverhead = 28000, // 3.5 ms
.floodInitOverhead = 18000, // 2.25 ms
.rxOffset = 4096, // 512.000 us
.txSync = 4137, // 517.125 us (updated 20200812)
},
{ // 9 (FSK 200k)
.slotOverhead = 26400, // 3.3 ms (adapted by kelmicha)
.slotAckOverhead = 26400, // 3.3 ms (adapted by kelmicha)
.floodInitOverhead = 18000, // 2.25 ms
.rxOffset = 2560, // 320.000 us
// .txSync = 3206, // 400.75 us (adapted by kelmicha)
.txSync = 3034, // 379.25 us (updated 20200812)
.slotOverhead = 26400, // 3.3 ms
.slotAckOverhead = 26400, // 3.3 ms
.floodInitOverhead = 18000, // 2.25 ms
.rxOffset = 2560, // 320.000 us
// .txSync = 3206, // 400.75 us
.txSync = 3034, // 379.25 us (updated 20200812)
},
{ // 10 (FSK 250k)
.slotOverhead = 14000, // 1.75 ms
.slotAckOverhead = 14000, // 1.75 ms
.floodInitOverhead = 18000, // 2.25 ms
.rxOffset = 2560, // 320.000 us (copy from 9)
.txSync = 3140, // 392.5 us (updated 20200814)
.slotOverhead = 14000, // 1.75 ms
.slotAckOverhead = 14000, // 1.75 ms