mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 19:05:07 +00:00
Mesh gets contacts, channels, delivery receipts, QR sharing and an ESP-NOW radio. Mesh Chat is split into Mesh Contacts and Mesh Channels, `mesh inspect` replaces the Mesh Inspect app, and ESP-NOW and Wi-Fi now share the Wi-Fi radio safely.
45 lines
2.0 KiB
C++
45 lines
2.0 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
#include <mesh/mesh_airtime.h>
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
uint32_t mesh_airtime_estimate_ms(const MeshRadioProfile& profile, size_t length) {
|
|
if (profile.modulation == RADIO_MODULATION_LORA && profile.bandwidth > 0) {
|
|
// Semtech AN1200.13, explicit header with CRC
|
|
const double symbolMs = std::pow(2.0, profile.spreading_factor) * 1000.0 / profile.bandwidth;
|
|
const int lowDataRateOptimize = (symbolMs > 16.0) ? 1 : 0;
|
|
const int codingRate = std::clamp<int>(profile.coding_rate - 4, 1, 4);
|
|
const double numerator = 8.0 * (double)length - 4.0 * profile.spreading_factor + 28.0 + 16.0;
|
|
const double denominator = 4.0 * (profile.spreading_factor - 2 * lowDataRateOptimize);
|
|
const double payloadSymbols = 8.0 + std::max(std::ceil(numerator / denominator) * (codingRate + 4), 0.0);
|
|
const double preambleMs = (profile.preamble_length + 4.25) * symbolMs;
|
|
return (uint32_t)std::ceil(preambleMs + payloadSymbols * symbolMs);
|
|
}
|
|
|
|
if (profile.modulation == RADIO_MODULATION_ESPNOW) {
|
|
// Wi-Fi long range runs at 0.5 Mbit/s, and a frame has about 100 bytes of headers
|
|
constexpr double BIT_RATE = 500000.0;
|
|
return (uint32_t)std::ceil((100.0 + length) * 8.0 * 1000.0 / BIT_RATE);
|
|
}
|
|
|
|
// FSK-family: preamble, sync word, length byte, payload and CRC. The data rate is not part of the
|
|
// profile, so a conservative 4.8 kbit/s is assumed.
|
|
constexpr double FALLBACK_BIT_RATE = 4800.0;
|
|
const double bits = profile.preamble_length + (4 + 1 + length + 2) * 8.0;
|
|
return (uint32_t)std::ceil(bits * 1000.0 / FALLBACK_BIT_RATE);
|
|
}
|
|
|
|
uint32_t mesh_airtime_duty_cycle_percent(RadioRegion region, int32_t frequency) {
|
|
switch (region) {
|
|
case RADIO_REGION_EU_868:
|
|
return (frequency >= 869400000 && frequency <= 869650000) ? 10 : 1;
|
|
case RADIO_REGION_EU_433:
|
|
return 10;
|
|
case RADIO_REGION_RU_868:
|
|
return 1;
|
|
default:
|
|
return 100;
|
|
}
|
|
}
|