Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
tuning_config.h
Go to the documentation of this file.
1#pragma once
2
3/// @file tuning_config.h
4/// @brief Runtime tuning configuration for pairing and radio diagnostics.
5/// @ingroup hioc_tuning
6///
7/// Provides a centralized, non-persistent tuning layer used by the hub and radio
8/// drivers. The `TuningConfig` struct carries all tunable parameters and helpers
9/// for logging and applying defaults.
10
11#include "proto_frame.h"
12#include "proto_timing.h"
13
14#include <cstddef>
15#include <cstdint>
16#include <optional>
17#include <string>
18#include <vector>
19
20namespace esphome {
21namespace home_io_control {
22
23/// @brief Valid SX1262 RX bandwidth options (kHz register values).
24///
25/// The numeric values are the register-encoded (double-sideband) bandwidth selectors used by
26/// `RadioSX1262::set_rx_bandwidth()` — a regular (mantissa, exponent) grid, with the bandwidth
27/// roughly doubling per group.
28///
29/// Byte-for-byte identical to `LR1121RxBandwidth` below, since both chips share the same Semtech
30/// GFSK bandwidth grid; the `Sx1262AndLr1121BandwidthTablesAgree` test pins that. If these two
31/// tables ever need to diverge for a real chip difference, say why here.
32enum class SX1262RxBandwidth : uint8_t {
33 BW_39_0_KHZ = 0x1C, ///< 39.0 kHz — narrowest; closest to the SX1276's validated 41.7 kHz.
34 BW_46_9_KHZ = 0x14, ///< 46.9 kHz — narrow.
35 BW_58_6_KHZ = 0x0C, ///< 58.6 kHz — default; the narrowest value validated on real hardware here.
36 BW_78_2_KHZ = 0x1B, ///< 78.2 kHz — just above the ~77 kHz Carson figure for this waveform.
37 BW_117_3_KHZ = 0x0B, ///< 117.3 kHz — the former default.
38 BW_156_2_KHZ = 0x1A, ///< 156.2 kHz.
39 BW_187_2_KHZ = 0x12, ///< 187.2 kHz — widest selectable option.
40};
41
42/// @brief Valid SX1276 RX bandwidth options (RegRxBw register bytes).
43///
44/// The numeric values are the SX1276 RegRxBw encodings (RxBwMant in bits[4:3], RxBwExp in
45/// bits[2:0]) written verbatim to both REG_RX_BW and REG_AFC_BW. Double-sideband bandwidth =
46/// FXOSC / (RxBwMant * 2^(RxBwExp+2)) with FXOSC = 32 MHz. Narrower rejects more out-of-band
47/// noise (higher sensitivity); wider tolerates more LO frequency offset.
48enum class SX1276RxBandwidth : uint8_t {
49 BW_20_8_KHZ = 0x14, ///< 20.8 kHz — narrowest; maximal noise rejection, least LO-offset tolerance.
50 BW_41_7_KHZ = 0x13, ///< 41.7 kHz — default (validated against real devices).
51 BW_62_5_KHZ = 0x03, ///< 62.5 kHz.
52 BW_83_3_KHZ = 0x12, ///< 83.3 kHz.
53 BW_125_0_KHZ = 0x02, ///< 125.0 kHz — widest selectable option.
54};
55
56/// @brief Valid LR1121 RX bandwidth options (register values).
57///
58/// Byte-for-byte identical to `SX1262RxBandwidth` — both chips use the same Semtech GFSK
59/// bandwidth grid — and kept as a distinct enum only so each driver's options can diverge if a
60/// future chip's table does. See `Sx1262AndLr1121BandwidthTablesAgree`, which pins the two tables
61/// together; if they ever need to differ for a real chip difference, say why here.
62enum class LR1121RxBandwidth : uint8_t {
63 BW_39_0_KHZ = 0x1C, ///< 39.0 kHz — narrowest; close to SX1276's validated 41.7 kHz default.
64 BW_46_9_KHZ = 0x14, ///< 46.9 kHz — narrow.
65 BW_58_6_KHZ = 0x0C, ///< 58.6 kHz.
66 BW_78_2_KHZ = 0x1B, ///< 78.2 kHz.
67 BW_117_3_KHZ = 0x0B, ///< 117.3 kHz — default.
68 BW_156_2_KHZ = 0x1A, ///< 156.2 kHz — wider tolerance for LO offset.
69 BW_187_2_KHZ = 0x12, ///< 187.2 kHz — widest selectable option.
70};
71
72/// @brief Discovery request command codes.
73enum class DiscoveryCommand : uint8_t {
74 DISCOVER = 0x28, ///< Standard broadcast discovery request (to 0x00003B).
75 DISCOVER_SPE = 0x2A, ///< SPE roll-call request (self-authenticating; see CMD_DISCOVER_SPE_REQ).
76 ///< Deliberately **not** offered as a `pairing_discovery_commands` preset
77 ///< in tuning.py: only devices that already hold the system key answer it,
78 ///< so it can never help reach a device in learning mode. Retained here
79 ///< because the command byte is still needed to *send* a roll-call, and
80 ///< because discovery_command_from_string() stays permissive enough to
81 ///< parse it — do not remove either as dead code.
82 DISCOVER_ALT = 0x2E, ///< Alternate broadcast discovery (to 0x00003F), with optional payload byte.
83};
84
85// Chip-specific radio defaults live here beside the TuningConfig fields they initialize — the
86// single source of truth for defaults. proto_timing.h holds only chip-neutral protocol values;
87// the radio drivers consume these via apply_tuning / hop_dwell_ms.
88
89/// SX1262-specific preamble for response/continuation frames within an exchange.
90///
91/// Applies to any tight-turnaround frame sent immediately after receiving from the device —
92/// 0x3D challenge responses, 0x32 key transfers after receiving 0x3C, and any future protocol
93/// frame in that position — giving the peer's receiver time to lock back on after the SX1262's
94/// own TX→RX turnaround.
95///
96/// 8 bytes was validated on real hardware (Heltec V3.2 ↔ Device actuator) as the minimum that
97/// gives reliable lock-on without perturbing exchange timing; it matches the protocol's own
98/// nominal SHORT_PREAMBLE floor.
99///
100/// This constant is byte-denominated, like every other preamble value in this codebase
101/// (LONG_PREAMBLE, SHORT_PREAMBLE) — `RadioSX1262::set_packet_params_()` is the one place that
102/// converts to the chip's bit-denominated SetPacketParams field, right before the value leaves
103/// for the wire.
104static constexpr uint16_t SX1262_RESPONSE_PREAMBLE = 8;
105
106/// SX1262-specific post-TX settling delay before re-entering RX.
107///
108/// The SX1262 GFSK demodulator needs time to stabilize after TX before it can
109/// reliably receive the next frame. A 500 µs delay was validated as the minimum
110/// that prevents challenge-byte corruption during pairing and tight-turnaround
111/// authenticated exchanges.
112static constexpr uint16_t SX1262_POST_TX_SETTLE_US = 500;
113
114/// SX1276 preamble for response/continuation frames within an exchange.
115///
116/// Defaults to 12 bytes — longer than the protocol's 8-byte SHORT_PREAMBLE. On real hardware the
117/// extra length improves the peer device's lock-on without measurably affecting exchange timing.
118/// Runtime-tunable down to SHORT_PREAMBLE or up for a marginal-range install.
119static constexpr uint16_t SX1276_RESPONSE_PREAMBLE = 12;
120
121/// Per-channel dwell while SX1276 pairing discovery hops across channels.
122///
123/// The SX1276 supports FastHop (no standby transition), so a short slice keeps
124/// discovery sweeping all three channels quickly.
125static constexpr uint16_t SX1276_DISCOVERY_HOP_SLICE_MS = 5;
126
127/// Per-channel dwell while SX1262 pairing discovery hops across channels.
128///
129/// SX1262 frequency changes require a standby→SetRfFrequency→RX cycle, unlike the SX1276's
130/// FastHop, but that changes only how much a single retune costs, not how long the radio should
131/// then sit still: a short dwell fits more retunes into the listen window than a long one, so the
132/// receiver is more often already parked on the right channel by the time a reply starts. The
133/// preamble/sync linger guard (`ListenSpec::linger_on_preamble`) is what makes a dwell this short
134/// safe — it keeps a caught reply from being cut off mid-reception by extending the dwell instead
135/// of hopping away. A dwell in the low single-digit milliseconds performs best; shorter than that,
136/// coverage degrades gradually and only truly collapses at `0`, where `wait_for_packet(..., 0)`
137/// returns before any guard can observe activity at all. `7` is the best-performing value found in
138/// that range.
139static constexpr uint16_t SX1262_DISCOVERY_HOP_SLICE_MS = 7;
140
141/// LR1121-specific preamble for response/continuation frames within an exchange.
142///
143/// Seeded from the SX1262-validated default, on the principle that a validated timing value
144/// encodes protocol-side reality more than a chip quirk. Not yet independently validated on
145/// LR1121 hardware; a value measured by loopback tuning would fold back here.
147
148/// LR1121-specific post-TX settling delay before re-entering RX.
149///
150/// Seeded from the SX1262-validated default; same rationale as @ref LR1121_RESPONSE_PREAMBLE.
152
153/// Per-channel dwell while LR1121 pairing discovery hops across channels.
154///
155/// Measured independently on LR1121 hardware rather than inherited from
156/// @ref SX1262_DISCOVERY_HOP_SLICE_MS — that constant's short-dwell reasoning applies equally
157/// here, but the two chips are validated separately and could in principle diverge, so this stays
158/// its own literal rather than an alias.
159static constexpr uint16_t LR1121_DISCOVERY_HOP_SLICE_MS = 7;
160
161/// @brief All runtime tunable parameters for pairing and radio diagnostics.
162///
163/// Values reset to their defaults on every boot. Each field initializes from a
164/// canonical constant — chip-neutral defaults live in `proto_timing.h`, chip-specific
165/// defaults in this header — shared with the ESPHome YAML schema. The hub stores a single
166/// `TuningConfig` instance and passes it to the radio driver and pairing flow. UI
167/// callbacks update the hub instance directly; the snapshot helpers emit the current
168/// values in YAML-compatible form so a working combination can be copied back into the
169/// configuration file.
171 // --- Radio / physical layer ---
172 /// SX1262 RX bandwidth selector.
173 ///
174 /// 58.6 kHz: narrower rejects more noise, and reception improves as the filter narrows on this
175 /// waveform. Matches the SX1276's long-validated 41.7 kHz default on the identical waveform. A
176 /// wide default would exist only to tolerate local-oscillator offset across the TX->RX
177 /// turnaround, but that turnaround is now a measured ~390 us plus a 500 us settle, well within
178 /// what the narrow filter tolerates.
180 uint16_t sx1262_response_preamble{SX1262_RESPONSE_PREAMBLE}; ///< SX1262 response preamble in bytes.
181 uint16_t sx1262_post_tx_settle_us{SX1262_POST_TX_SETTLE_US}; ///< Delay after SX1262 TX before RX (µs).
183 uint16_t sx1276_response_preamble{SX1276_RESPONSE_PREAMBLE}; ///< SX1276 response preamble in bytes.
185 SX1276_DISCOVERY_HOP_SLICE_MS}; ///< Per-channel dwell while SX1276 discovery hops.
187 SX1262_DISCOVERY_HOP_SLICE_MS}; ///< Per-channel dwell while SX1262 discovery hops.
189 uint16_t lr1121_response_preamble{LR1121_RESPONSE_PREAMBLE}; ///< LR1121 response preamble in bytes.
190 uint16_t lr1121_post_tx_settle_us{LR1121_POST_TX_SETTLE_US}; ///< Delay after LR1121 TX before RX (µs).
192 LR1121_DISCOVERY_HOP_SLICE_MS}; ///< Per-channel dwell while LR1121 discovery hops.
194 COLD_BROADCAST_REPLY_PREAMBLE}; ///< Preamble for a start-flagged key-extraction broadcast reply (0x29).
196 NORMAL_START_PREAMBLE}; ///< Preamble for a directed start frame to a non-low-power target.
197 uint8_t lbt_max_retries{LBT_MAX_RETRIES}; ///< LBT retries before forced TX.
198 int16_t lbt_rssi_threshold_dbm{LBT_RSSI_THRESHOLD_DBM}; ///< LBT channel-free threshold (dBm).
199
200 // --- Exchange response windows ---
201 // How long the hub listens for a device's reply. Tunable because the right value is a property
202 // of the *device*, not of the radio or the protocol: observed reply latencies on one network
203 // span two orders of magnitude (a mains Oximo 40 at ~23 ms, a solar RS100 at 29-3052 ms). See
204 // RESPONSE_START_WAIT_MS for the measurements behind the defaults.
206 RESPONSE_START_WAIT_MS}; ///< Reply window for a start frame (wakes a sleeping device).
208 RESPONSE_WAIT_MS}; ///< Reply window for continuation frames and the post-auth final response.
209 uint16_t exchange_total_budget_ms{EXCHANGE_TOTAL_BUDGET_MS}; ///< Ceiling on one whole exchange, retries included.
210
211 // --- Pairing protocol ---
212 std::vector<DiscoveryCommand> pairing_discovery_commands{
213 DiscoveryCommand::DISCOVER}; ///< Ordered discovery commands.
214 std::vector<uint8_t> pairing_discovery_destination{0x00, 0x00, 0x00}; ///< Destination when auto=false.
215 bool pairing_discovery_destination_auto{true}; ///< When true, map commands to conventional addresses.
216 uint8_t pairing_discovery_payload{0}; ///< Optional payload byte (used for 0x2E).
217 bool pairing_discovery_payload_enabled{false}; ///< Whether the optional payload is enabled.
218 bool pairing_discovery_low_power{false}; ///< Set LOW_POWER flag in discovery frames.
220 PAIRING_DISCOVERY_PREAMBLE}; ///< Preamble for the discovery broadcast (0x28/0x2E) start frame.
222 PAIRING_DISCOVERY_WAIT_MS}; ///< Total wait window after sending discovery commands.
224 PAIRING_DISCOVERY_INITIAL_DWELL_MS}; ///< Initial dwell on CH2 before discovery hopping begins.
226 PAIRING_KEY_EXCHANGE_RETRIES}; ///< Retries for the authenticated key exchange phase.
227
228 // --- Internal state ---
229 bool active{false}; ///< True when the YAML `tuning:` block is present.
230};
231
232/// @brief One selectable RX bandwidth: the chip's register byte and its nominal kHz value.
233///
234/// The per-chip bandwidth conversion functions below (SX1262/SX1276/LR1121) are all the same
235/// logic over a different table of these; they are thin typed wrappers around the three generic
236/// helpers that follow, which own the register-byte lookup, the "%.1f" formatting, and the
237/// input normalization once instead of three times.
239 uint8_t reg;
240 float khz;
241};
242
243/// @brief Look up the kHz value for a register byte in a bandwidth table.
244/// @param table Bandwidth option table.
245/// @param n Number of entries in @p table.
246/// @param reg Register byte to look up.
247/// @param fallback kHz value returned when @p reg is not in the table.
248float bandwidth_to_khz(const BandwidthOption *table, size_t n, uint8_t reg, float fallback);
249
250/// @brief Format a kHz value as its YAML/UI option string (bare number, one decimal, e.g. "117.3").
251std::string bandwidth_to_string(float khz);
252
253/// @brief Parse a YAML/UI bandwidth string against a table, returning the matching register byte.
254///
255/// Accepts surrounding whitespace and a trailing "kHz" suffix in any case, and accepts both the
256/// one-decimal spelling ("39.0") and the integer-truncated spelling ("39") of every table entry.
257/// @return The register byte, or std::nullopt when the string matches no entry.
258std::optional<uint8_t> bandwidth_from_string(const BandwidthOption *table, size_t n, const std::string &value);
259
260/// @brief A pointer/size view over one chip's RX-bandwidth option table.
265
266/// @brief The SX1262 RX-bandwidth option table. Exposed so tests derive their legal-option
267/// lists from the same source production uses rather than re-listing them by hand.
269/// @brief The SX1276 RX-bandwidth option table (see sx1262_bandwidth_table()).
271/// @brief The LR1121 RX-bandwidth option table (see sx1262_bandwidth_table()).
273
274/// @brief Convert a bandwidth enum to the numeric kHz value used in YAML/logs.
275/// @param bw SX1262 bandwidth enum.
276/// @return Floating-point kHz value (39.0, 46.9, 58.6, 78.2, 117.3, 156.2, or 187.2).
278
279/// @brief Format a bandwidth enum as its YAML/UI option string (bare kHz number, e.g. "117.3").
280/// @param bw SX1262 bandwidth enum.
281/// @return Bandwidth rendered with one decimal place and a "kHz" suffix.
283
284/// @brief Convert a YAML bandwidth string to the enum value.
285/// @param value YAML string such as "117.3kHz" or "156.2kHz".
286/// @return Bandwidth enum, or std::nullopt on invalid input.
287std::optional<SX1262RxBandwidth> sx1262_bandwidth_from_string(const std::string &value);
288
289/// @brief Convert an SX1276 bandwidth enum to the numeric kHz value used in YAML/logs.
290/// @param bw SX1276 bandwidth enum.
291/// @return Floating-point kHz value (20.8, 41.7, 62.5, 83.3, or 125.0).
293
294/// @brief Format an SX1276 bandwidth enum as its YAML/UI option string (bare kHz number).
295/// @param bw SX1276 bandwidth enum.
296/// @return Bandwidth rendered with one decimal place (e.g. "41.7").
298
299/// @brief Convert a YAML SX1276 bandwidth string to the enum value.
300/// @param value YAML string such as "41.7" or "83.3kHz".
301/// @return Bandwidth enum, or std::nullopt on invalid input.
302std::optional<SX1276RxBandwidth> sx1276_bandwidth_from_string(const std::string &value);
303
304/// @brief Convert an LR1121 bandwidth enum to the numeric kHz value used in YAML/logs.
305/// @param bw LR1121 bandwidth enum.
306/// @return Floating-point kHz value (39.0, 46.9, 58.6, 78.2, 117.3, 156.2, or 187.2).
308
309/// @brief Format an LR1121 bandwidth enum as its YAML/UI option string (bare kHz number).
310/// @param bw LR1121 bandwidth enum.
311/// @return Bandwidth rendered with one decimal place (e.g. "117.3").
313
314/// @brief Convert a YAML LR1121 bandwidth string to the enum value.
315/// @param value YAML string such as "117.3" or "39.0kHz".
316/// @return Bandwidth enum, or std::nullopt on invalid input.
317std::optional<LR1121RxBandwidth> lr1121_bandwidth_from_string(const std::string &value);
318
319/// @brief Format the current tuning configuration as a one-line YAML-compatible snapshot.
320///
321/// Only values that differ from the default are emitted, so the line can be copied
322/// back into YAML with minimal editing. When all values are default, an empty string
323/// is returned.
324///
325/// @param cfg Current tuning configuration.
326/// @return One-line snapshot string, or empty when no overrides are active.
327std::string tuning_config_snapshot(const TuningConfig &cfg);
328
329/// @brief Format the current tuning configuration as a full one-line snapshot.
330///
331/// Emits every non-default value, regardless of whether it was changed from YAML or
332/// from the HA UI. This is logged at the start of every pairing attempt.
333///
334/// @param cfg Current tuning configuration.
335/// @return One-line snapshot string, or a "defaults" marker when nothing is overridden.
336std::string tuning_config_full_snapshot(const TuningConfig &cfg);
337
338/// @brief Format a single tuning update for the log.
339///
340/// @param name YAML key name of the updated parameter.
341/// @param value YAML-compatible string representation of the new value.
342/// @return One-line log string suitable for ESP_LOGI.
343std::string tuning_update_log_line(const std::string &name, const std::string &value);
344
345/// @brief Resolve the destination address for a discovery command.
346///
347/// When `destination_auto` is true, returns the conventional address for the
348/// given command code. Otherwise returns the configured `destination` value.
349///
350/// @param command Discovery command code.
351/// @param destination_auto Whether to use the automatic mapping.
352/// @param destination Explicit 3-byte destination when auto is false.
353/// @return Pointer to the resolved 3-byte node ID.
354const uint8_t *resolve_discovery_destination(uint8_t command, bool destination_auto,
355 const uint8_t destination[NODE_ID_SIZE]);
356
357/// @brief Parse a discovery command string (e.g., "0x28") into the enum.
358/// @param value String to parse.
359/// @return Discovery command enum, or std::nullopt on invalid input.
360std::optional<DiscoveryCommand> discovery_command_from_string(const std::string &value);
361
362/// @brief Format a discovery command enum for YAML/logs.
363/// @param cmd Discovery command enum.
364/// @return Lowercase hex string such as "0x28".
366
367/// @brief Format a destination option for YAML/logs.
368///
369/// @param destination_auto Whether automatic destination mapping is used.
370/// @param destination Explicit 3-byte destination when auto is false.
371/// @return "auto" or a hex address such as "0x00003B".
372std::string discovery_destination_to_string(bool destination_auto, const uint8_t destination[NODE_ID_SIZE]);
373
374/// @brief Format a payload option for YAML/logs.
375///
376/// @param payload_enabled Whether the optional payload is enabled.
377/// @param payload The payload byte when enabled.
378/// @return "none" or a hex byte such as "0x00".
379std::string discovery_payload_to_string(bool payload_enabled, uint8_t payload);
380
381/// @brief Format the ordered discovery command list for logs.
382///
383/// @param commands Ordered list of discovery commands.
384/// @return Bracketed comma-separated list such as "[0x28,0x2E]".
385std::string discovery_commands_to_string(const std::vector<DiscoveryCommand> &commands);
386
387/// @brief Format the ordered discovery command list as a UI/preset option string.
388///
389/// Matches the comma-separated `select` option labels (no brackets) so a boot-time
390/// snapshot round-trips to a selectable dropdown value.
391///
392/// @param commands Ordered list of discovery commands.
393/// @return Comma-separated list such as "0x28,0x2E" (empty string when the list is empty).
394std::string discovery_commands_to_csv(const std::vector<DiscoveryCommand> &commands);
395
396} // namespace home_io_control
397} // namespace esphome
BandwidthTableView lr1121_bandwidth_table()
The LR1121 RX-bandwidth option table (see sx1262_bandwidth_table()).
static constexpr uint8_t PAIRING_KEY_EXCHANGE_RETRIES
Retries for the authenticated key-exchange phase.
std::string discovery_commands_to_csv(const std::vector< DiscoveryCommand > &commands)
Format the ordered discovery command list as a UI/preset option string.
static constexpr uint8_t NODE_ID_SIZE
Device/node addresses are 3 bytes (e.g., "123ABC").
Definition proto_sizes.h:20
std::optional< LR1121RxBandwidth > lr1121_bandwidth_from_string(const std::string &value)
Convert a YAML LR1121 bandwidth string to the enum value.
SX1262RxBandwidth
Valid SX1262 RX bandwidth options (kHz register values).
@ BW_39_0_KHZ
39.0 kHz — narrowest; closest to the SX1276's validated 41.7 kHz.
@ BW_58_6_KHZ
58.6 kHz — default; the narrowest value validated on real hardware here.
@ BW_78_2_KHZ
78.2 kHz — just above the ~77 kHz Carson figure for this waveform.
@ BW_117_3_KHZ
117.3 kHz — the former default.
@ BW_187_2_KHZ
187.2 kHz — widest selectable option.
std::string discovery_payload_to_string(bool payload_enabled, uint8_t payload)
Format a payload option for YAML/logs.
std::optional< DiscoveryCommand > discovery_command_from_string(const std::string &value)
Parse a discovery command string (e.g., "0x28") into the enum.
static constexpr uint8_t LBT_MAX_RETRIES
Max carrier-sense attempts before TX anyway.
LR1121RxBandwidth
Valid LR1121 RX bandwidth options (register values).
std::string lr1121_bandwidth_to_string(LR1121RxBandwidth bw)
Format an LR1121 bandwidth enum as its YAML/UI option string (bare kHz number).
static constexpr uint16_t NORMAL_START_PREAMBLE
Default for TuningConfig::normal_start_preamble — the preamble in front of a directed start frame who...
static constexpr uint16_t SX1276_RESPONSE_PREAMBLE
SX1276 preamble for response/continuation frames within an exchange.
std::string tuning_config_snapshot(const TuningConfig &cfg)
Format the current tuning configuration as a one-line YAML-compatible snapshot.
std::optional< SX1262RxBandwidth > sx1262_bandwidth_from_string(const std::string &value)
Convert a YAML bandwidth string to the enum value.
std::string sx1276_bandwidth_to_string(SX1276RxBandwidth bw)
Format an SX1276 bandwidth enum as its YAML/UI option string (bare kHz number).
float lr1121_bandwidth_to_khz(LR1121RxBandwidth bw)
Convert an LR1121 bandwidth enum to the numeric kHz value used in YAML/logs.
std::string discovery_commands_to_string(const std::vector< DiscoveryCommand > &commands)
Format the ordered discovery command list for logs.
std::string bandwidth_to_string(float khz)
Format a kHz value as its YAML/UI option string (bare number, one decimal, e.g. "117....
std::string tuning_config_full_snapshot(const TuningConfig &cfg)
Format the current tuning configuration as a full one-line snapshot.
static constexpr uint16_t SX1262_DISCOVERY_HOP_SLICE_MS
Per-channel dwell while SX1262 pairing discovery hops across channels.
float sx1262_bandwidth_to_khz(SX1262RxBandwidth bw)
Convert a bandwidth enum to the numeric kHz value used in YAML/logs.
static constexpr uint16_t LR1121_RESPONSE_PREAMBLE
LR1121-specific preamble for response/continuation frames within an exchange.
std::string sx1262_bandwidth_to_string(SX1262RxBandwidth bw)
Format a bandwidth enum as its YAML/UI option string (bare kHz number, e.g.
BandwidthTableView sx1262_bandwidth_table()
The SX1262 RX-bandwidth option table.
static constexpr uint16_t SX1276_DISCOVERY_HOP_SLICE_MS
Per-channel dwell while SX1276 pairing discovery hops across channels.
std::string tuning_update_log_line(const std::string &name, const std::string &value)
Format a single tuning update for the log.
static constexpr uint16_t SX1262_RESPONSE_PREAMBLE
SX1262-specific preamble for response/continuation frames within an exchange.
static constexpr uint16_t PAIRING_DISCOVERY_WAIT_MS
Canonical defaults for the chip-neutral runtime-tunable pairing/discovery parameters.
std::optional< uint8_t > bandwidth_from_string(const BandwidthOption *table, size_t n, const std::string &value)
Parse a YAML/UI bandwidth string against a table, returning the matching register byte.
DiscoveryCommand
Discovery request command codes.
@ DISCOVER_SPE
SPE roll-call request (self-authenticating; see CMD_DISCOVER_SPE_REQ).
@ DISCOVER
Standard broadcast discovery request (to 0x00003B).
@ DISCOVER_ALT
Alternate broadcast discovery (to 0x00003F), with optional payload byte.
float sx1276_bandwidth_to_khz(SX1276RxBandwidth bw)
Convert an SX1276 bandwidth enum to the numeric kHz value used in YAML/logs.
static constexpr uint16_t COLD_BROADCAST_REPLY_PREAMBLE
Default for TuningConfig::cold_broadcast_reply_preamble — preamble for a broadcast reply to a frame t...
std::string discovery_command_to_string(DiscoveryCommand cmd)
Format a discovery command enum for YAML/logs.
SX1276RxBandwidth
Valid SX1276 RX bandwidth options (RegRxBw register bytes).
@ BW_41_7_KHZ
41.7 kHz — default (validated against real devices).
@ BW_125_0_KHZ
125.0 kHz — widest selectable option.
@ BW_20_8_KHZ
20.8 kHz — narrowest; maximal noise rejection, least LO-offset tolerance.
static constexpr int32_t RESPONSE_WAIT_MS
Wait for response to non-start frame.
static constexpr uint16_t SX1262_POST_TX_SETTLE_US
SX1262-specific post-TX settling delay before re-entering RX.
std::optional< SX1276RxBandwidth > sx1276_bandwidth_from_string(const std::string &value)
Convert a YAML SX1276 bandwidth string to the enum value.
static constexpr uint16_t LR1121_POST_TX_SETTLE_US
LR1121-specific post-TX settling delay before re-entering RX.
static constexpr uint16_t LR1121_DISCOVERY_HOP_SLICE_MS
Per-channel dwell while LR1121 pairing discovery hops across channels.
const uint8_t * resolve_discovery_destination(uint8_t command, bool destination_auto, const uint8_t destination[NODE_ID_SIZE])
Resolve the destination address for a discovery command.
BandwidthTableView sx1276_bandwidth_table()
The SX1276 RX-bandwidth option table (see sx1262_bandwidth_table()).
static constexpr uint16_t PAIRING_DISCOVERY_PREAMBLE
Default for TuningConfig::pairing_discovery_preamble — the preamble on the pairing discovery broadcas...
std::string discovery_destination_to_string(bool destination_auto, const uint8_t destination[NODE_ID_SIZE])
Format a destination option for YAML/logs.
float bandwidth_to_khz(const BandwidthOption *table, size_t n, uint8_t reg, float fallback)
Look up the kHz value for a register byte in a bandwidth table.
static constexpr uint16_t EXCHANGE_TOTAL_BUDGET_MS
Wall-clock ceiling on one whole exchange, retries included.
static constexpr int16_t LBT_RSSI_THRESHOLD_DBM
Listen-before-talk (LBT) parameters for ETSI EN 300 220 compliance.
static constexpr uint16_t PAIRING_DISCOVERY_INITIAL_DWELL_MS
Dwell on CH2 before discovery hopping begins.
static constexpr int32_t RESPONSE_START_WAIT_MS
Wait for a response to a start frame — the first frame of an exchange, and the one a sleeping device ...
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
Physical-layer radio and timing parameters for the IO-Homecontrol protocol.
One selectable RX bandwidth: the chip's register byte and its nominal kHz value.
A pointer/size view over one chip's RX-bandwidth option table.
All runtime tunable parameters for pairing and radio diagnostics.
bool active
True when the YAML tuning: block is present.
uint16_t pairing_discovery_initial_dwell_ms
Initial dwell on CH2 before discovery hopping begins.
bool pairing_discovery_destination_auto
When true, map commands to conventional addresses.
SX1276RxBandwidth sx1276_rx_bandwidth
SX1276 RX bandwidth selector.
uint16_t normal_start_preamble
Preamble for a directed start frame to a non-low-power target.
int16_t lbt_rssi_threshold_dbm
LBT channel-free threshold (dBm).
SX1262RxBandwidth sx1262_rx_bandwidth
SX1262 RX bandwidth selector.
uint16_t cold_broadcast_reply_preamble
Preamble for a start-flagged key-extraction broadcast reply (0x29).
std::vector< uint8_t > pairing_discovery_destination
Destination when auto=false.
std::vector< DiscoveryCommand > pairing_discovery_commands
Ordered discovery commands.
uint16_t lr1121_discovery_hop_slice_ms
Per-channel dwell while LR1121 discovery hops.
uint16_t sx1276_response_preamble
SX1276 response preamble in bytes.
uint16_t exchange_response_wait_ms
Reply window for continuation frames and the post-auth final response.
uint16_t sx1262_post_tx_settle_us
Delay after SX1262 TX before RX (µs).
uint8_t pairing_key_exchange_retries
Retries for the authenticated key exchange phase.
bool pairing_discovery_low_power
Set LOW_POWER flag in discovery frames.
uint16_t sx1276_discovery_hop_slice_ms
Per-channel dwell while SX1276 discovery hops.
uint16_t exchange_start_response_wait_ms
Reply window for a start frame (wakes a sleeping device).
uint16_t sx1262_response_preamble
SX1262 response preamble in bytes.
uint16_t pairing_discovery_preamble
Preamble for the discovery broadcast (0x28/0x2E) start frame.
uint16_t pairing_discovery_wait_ms
Total wait window after sending discovery commands.
bool pairing_discovery_payload_enabled
Whether the optional payload is enabled.
LR1121RxBandwidth lr1121_rx_bandwidth
LR1121 RX bandwidth selector.
uint16_t lr1121_post_tx_settle_us
Delay after LR1121 TX before RX (µs).
uint8_t lbt_max_retries
LBT retries before forced TX.
uint16_t sx1262_discovery_hop_slice_ms
Per-channel dwell while SX1262 discovery hops.
uint16_t exchange_total_budget_ms
Ceiling on one whole exchange, retries included.
uint16_t lr1121_response_preamble
LR1121 response preamble in bytes.
uint8_t pairing_discovery_payload
Optional payload byte (used for 0x2E).