Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
tuning_config.cpp
Go to the documentation of this file.
1/// @file tuning_config.cpp
2/// @brief Runtime tuning configuration helpers and snapshot formatting.
3/// @ingroup hioc_tuning
4
5#include "tuning_config.h"
6
7#include "proto_constants.h"
8#include "tuning_registry.h"
9
10#include <algorithm>
11#include <cctype>
12#include <cstdio>
13
14namespace esphome {
15namespace home_io_control {
16
17namespace {
18
19/// Default tuning configuration used for diffing and reset behavior.
20const TuningConfig DEFAULTS{};
21
22/// Buffer size for a formatted single hex byte such as "0x2E" (4 chars + slack).
23constexpr size_t HEX_BYTE_STR_SIZE = 8;
24/// Buffer size for a formatted 3-byte hex address such as "0x00003B".
25constexpr size_t HEX_ADDR_STR_SIZE = 16;
26/// Buffer size for a formatted bandwidth string such as "117.3kHz".
27constexpr size_t BANDWIDTH_STR_SIZE = 16;
28
29/// One selectable RX bandwidth per chip: register byte plus its nominal kHz value.
30///
31/// SX1262 and LR1121 share the Semtech GFSK bandwidth grid, so these two tables are
32/// byte-for-byte identical today (the `Sx1262AndLr1121BandwidthTablesAgree` test pins that);
33/// they are kept separate only so each chip's option set can diverge for a real chip
34/// difference. SX1276 has its own RegRxBw encoding. Keys must match `tuning.py`'s
35/// `*_BANDWIDTH_OPTIONS`, which `scripts/check-tuning-sync.py` verifies.
36// The register byte in every row comes from the chip's bandwidth enum so it keeps exactly one
37// definition; the kHz literal is this table's only added datum. `scripts/check-tuning-sync.py`
38// pins the kHz column against `tuning.py`; the enum cast pins the register byte.
39constexpr BandwidthOption SX1262_BANDWIDTHS[] = {
40 {static_cast<uint8_t>(SX1262RxBandwidth::BW_39_0_KHZ), 39.0F},
41 {static_cast<uint8_t>(SX1262RxBandwidth::BW_46_9_KHZ), 46.9F},
42 {static_cast<uint8_t>(SX1262RxBandwidth::BW_58_6_KHZ), 58.6F},
43 {static_cast<uint8_t>(SX1262RxBandwidth::BW_78_2_KHZ), 78.2F},
44 {static_cast<uint8_t>(SX1262RxBandwidth::BW_117_3_KHZ), 117.3F},
45 {static_cast<uint8_t>(SX1262RxBandwidth::BW_156_2_KHZ), 156.2F},
46 {static_cast<uint8_t>(SX1262RxBandwidth::BW_187_2_KHZ), 187.2F},
47};
48constexpr BandwidthOption SX1276_BANDWIDTHS[] = {
49 {static_cast<uint8_t>(SX1276RxBandwidth::BW_20_8_KHZ), 20.8F},
50 {static_cast<uint8_t>(SX1276RxBandwidth::BW_41_7_KHZ), 41.7F},
51 {static_cast<uint8_t>(SX1276RxBandwidth::BW_62_5_KHZ), 62.5F},
52 {static_cast<uint8_t>(SX1276RxBandwidth::BW_83_3_KHZ), 83.3F},
53 {static_cast<uint8_t>(SX1276RxBandwidth::BW_125_0_KHZ), 125.0F},
54};
55constexpr BandwidthOption LR1121_BANDWIDTHS[] = {
56 {static_cast<uint8_t>(LR1121RxBandwidth::BW_39_0_KHZ), 39.0F},
57 {static_cast<uint8_t>(LR1121RxBandwidth::BW_46_9_KHZ), 46.9F},
58 {static_cast<uint8_t>(LR1121RxBandwidth::BW_58_6_KHZ), 58.6F},
59 {static_cast<uint8_t>(LR1121RxBandwidth::BW_78_2_KHZ), 78.2F},
60 {static_cast<uint8_t>(LR1121RxBandwidth::BW_117_3_KHZ), 117.3F},
61 {static_cast<uint8_t>(LR1121RxBandwidth::BW_156_2_KHZ), 156.2F},
62 {static_cast<uint8_t>(LR1121RxBandwidth::BW_187_2_KHZ), 187.2F},
63};
64
65/// kHz returned for a register byte not in the chip's table — the chip's configured default,
66/// matching the fall-through of the previous per-chip switch statements.
67constexpr float SX1262_BW_FALLBACK_KHZ = 117.3F;
68constexpr float SX1276_BW_FALLBACK_KHZ = 41.7F;
69constexpr float LR1121_BW_FALLBACK_KHZ = 117.3F;
70
71template<size_t N> constexpr size_t bw_count(const BandwidthOption (& /*table*/)[N]) { return N; }
72
73} // namespace
74
75float bandwidth_to_khz(const BandwidthOption *table, size_t n, uint8_t reg, float fallback) {
76 for (size_t i = 0; i < n; ++i) {
77 if (table[i].reg == reg)
78 return table[i].khz;
79 }
80 return fallback;
81}
82
83std::string bandwidth_to_string(float khz) {
84 char buf[BANDWIDTH_STR_SIZE];
85 snprintf(buf, sizeof(buf), "%.1f", khz);
86 return std::string(buf);
87}
88
89std::optional<uint8_t> bandwidth_from_string(const BandwidthOption *table, size_t n, const std::string &value) {
90 std::string normalized = value;
91 // Normalize: strip whitespace and a trailing "kHz"/"khz" suffix.
92 normalized.erase(std::remove_if(normalized.begin(), normalized.end(), ::isspace), normalized.end());
93 for (char &c : normalized)
94 c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
95 if (normalized.size() > 3 && normalized.ends_with("khz"))
96 normalized.resize(normalized.size() - 3);
97
98 for (size_t i = 0; i < n; ++i) {
99 char one_decimal[BANDWIDTH_STR_SIZE];
100 char truncated[BANDWIDTH_STR_SIZE];
101 snprintf(one_decimal, sizeof(one_decimal), "%.1f", table[i].khz);
102 snprintf(truncated, sizeof(truncated), "%d", static_cast<int>(table[i].khz));
103 if (normalized == one_decimal || normalized == truncated)
104 return table[i].reg;
105 }
106 return std::nullopt;
107}
108
109BandwidthTableView sx1262_bandwidth_table() { return {SX1262_BANDWIDTHS, bw_count(SX1262_BANDWIDTHS)}; }
110BandwidthTableView sx1276_bandwidth_table() { return {SX1276_BANDWIDTHS, bw_count(SX1276_BANDWIDTHS)}; }
111BandwidthTableView lr1121_bandwidth_table() { return {LR1121_BANDWIDTHS, bw_count(LR1121_BANDWIDTHS)}; }
112
114 return bandwidth_to_khz(SX1262_BANDWIDTHS, bw_count(SX1262_BANDWIDTHS), static_cast<uint8_t>(bw),
115 SX1262_BW_FALLBACK_KHZ);
116}
117
121
122std::optional<SX1262RxBandwidth> sx1262_bandwidth_from_string(const std::string &value) {
123 if (const auto reg = bandwidth_from_string(SX1262_BANDWIDTHS, bw_count(SX1262_BANDWIDTHS), value))
124 return static_cast<SX1262RxBandwidth>(*reg);
125 return std::nullopt;
126}
127
129 return bandwidth_to_khz(SX1276_BANDWIDTHS, bw_count(SX1276_BANDWIDTHS), static_cast<uint8_t>(bw),
130 SX1276_BW_FALLBACK_KHZ);
131}
132
136
137std::optional<SX1276RxBandwidth> sx1276_bandwidth_from_string(const std::string &value) {
138 if (const auto reg = bandwidth_from_string(SX1276_BANDWIDTHS, bw_count(SX1276_BANDWIDTHS), value))
139 return static_cast<SX1276RxBandwidth>(*reg);
140 return std::nullopt;
141}
142
144 return bandwidth_to_khz(LR1121_BANDWIDTHS, bw_count(LR1121_BANDWIDTHS), static_cast<uint8_t>(bw),
145 LR1121_BW_FALLBACK_KHZ);
146}
147
151
152std::optional<LR1121RxBandwidth> lr1121_bandwidth_from_string(const std::string &value) {
153 if (const auto reg = bandwidth_from_string(LR1121_BANDWIDTHS, bw_count(LR1121_BANDWIDTHS), value))
154 return static_cast<LR1121RxBandwidth>(*reg);
155 return std::nullopt;
156}
157
158std::optional<DiscoveryCommand> discovery_command_from_string(const std::string &value) {
159 std::string normalized = value;
160 for (char &c : normalized)
161 c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
162 if (normalized == "0x28" || normalized == "discover")
164 if (normalized == "0x2a" || normalized == "discover_spe")
166 if (normalized == "0x2e" || normalized == "discover_alt")
168 return std::nullopt;
169}
170
172 char buf[HEX_BYTE_STR_SIZE];
173 snprintf(buf, sizeof(buf), "0x%02X", static_cast<uint8_t>(cmd));
174 return std::string(buf);
175}
176
177std::string discovery_commands_to_csv(const std::vector<DiscoveryCommand> &commands) {
178 std::string result;
179 for (size_t i = 0; i < commands.size(); ++i) {
180 if (i > 0)
181 result += ',';
182 result += discovery_command_to_string(commands[i]);
183 }
184 return result;
185}
186
187std::string discovery_commands_to_string(const std::vector<DiscoveryCommand> &commands) {
188 return "[" + discovery_commands_to_csv(commands) + "]";
189}
190
191const uint8_t *resolve_discovery_destination(uint8_t command, bool destination_auto,
192 const uint8_t destination[NODE_ID_SIZE]) {
193 if (!destination_auto)
194 return destination;
195 // Conventional destinations from the protocol / reference captures: standard and SPE
196 // discovery broadcast to 0x00003B; alternate discovery (0x2E) broadcasts to 0x00003F.
197 switch (command) {
198 case CMD_DISCOVER_REQ:
199 case CMD_DISCOVER_SPE_REQ:
200 return BROADCAST_DISCOVER;
201 case CMD_DISCOVER_ALT_REQ:
203 default:
204 return BROADCAST_DISCOVER;
205 }
206}
207
208std::string discovery_destination_to_string(bool destination_auto, const uint8_t destination[NODE_ID_SIZE]) {
209 if (destination_auto)
210 return "auto";
211 char buf[HEX_ADDR_STR_SIZE];
212 snprintf(buf, sizeof(buf), "0x%02X%02X%02X", destination[0], destination[1], destination[2]);
213 return std::string(buf);
214}
215
216std::string discovery_payload_to_string(bool payload_enabled, uint8_t payload) {
217 if (!payload_enabled)
218 return "none";
219 char buf[HEX_BYTE_STR_SIZE];
220 snprintf(buf, sizeof(buf), "0x%02X", payload);
221 return std::string(buf);
222}
223
225 switch (value) {
227 return "both";
229 return power_save_mode_name(POWER_SAVE_ALWAYS_ALIVE);
231 return power_save_mode_name(POWER_SAVE_LOW_POWER);
232 }
233 return "both";
234}
235
236std::optional<ScanPowerClasses> scan_power_classes_from_string(const std::string &value) {
243 return std::nullopt;
244}
245
246bool scan_power_classes_include(ScanPowerClasses selection, uint8_t power_save_mode) {
247 switch (selection) {
249 return power_save_mode == POWER_SAVE_ALWAYS_ALIVE || power_save_mode == POWER_SAVE_LOW_POWER;
251 return power_save_mode == POWER_SAVE_ALWAYS_ALIVE;
253 return power_save_mode == POWER_SAVE_LOW_POWER;
254 }
255 return false;
256}
257
259 switch (value) {
261 return "skip";
263 return "send";
265 return "send_with_ack";
266 }
267 return "send";
268}
269
279
281 switch (value) {
283 return "skip_request";
285 return "all";
286 }
287 return "skip_request";
288}
289
290std::optional<DiscoveryListenChannels> discovery_listen_channels_from_string(const std::string &value) {
295 return std::nullopt;
296}
297
298std::string tuning_update_log_line(const std::string &name, const std::string &value) {
299 return "Tuning updated via HA: " + name + "=" + value;
300}
301
302std::string tuning_config_snapshot(const TuningConfig &cfg) {
303 std::string result;
304
305 // The three RX-bandwidth fields are enums, not plain numbers, so they stay hand-written here
306 // rather than going through the numeric loop below (they're SELECT_PARAMS, not NUMBER_PARAMS,
307 // in tuning_registry.cpp).
308 if (cfg.sx1262_rx_bandwidth != DEFAULTS.sx1262_rx_bandwidth)
309 result += " sx1262_rx_bandwidth=" + sx1262_bandwidth_to_string(cfg.sx1262_rx_bandwidth);
310 if (cfg.sx1276_rx_bandwidth != DEFAULTS.sx1276_rx_bandwidth)
311 result += " sx1276_rx_bandwidth=" + sx1276_bandwidth_to_string(cfg.sx1276_rx_bandwidth);
312 if (cfg.lr1121_rx_bandwidth != DEFAULTS.lr1121_rx_bandwidth)
313 result += " lr1121_rx_bandwidth=" + lr1121_bandwidth_to_string(cfg.lr1121_rx_bandwidth);
314
315 // Every plain numeric field is driven off the same NUMBER_PARAMS table the HA `number` entities
316 // and `make tuning-sync` use (tuning_registry.cpp) — not a second, independently-maintained list
317 // of field names. A hand-written per-field if-chain here once let a real, shipped knob
318 // (`pairing_discovery_preamble`) go completely missing from this exact diagnostic line — the one
319 // `discover_and_pair()` logs at the start of every attempt specifically so a user's bug report
320 // records which knobs were actually in effect — while still working everywhere else (HA entity,
321 // YAML, `make tuning-sync`). Table-driven means a new numeric knob can't repeat that: it either
322 // has a NUMBER_PARAMS row (and is covered) or it doesn't (and can't be set from HA at all).
324 const float current = p->get(cfg);
325 if (current != p->get(DEFAULTS))
326 result += " " + std::string(p->name) + "=" + std::to_string(static_cast<int64_t>(current));
327 }
328
329 if (cfg.low_power_wake_belief != DEFAULTS.low_power_wake_belief)
330 result += " low_power_wake_belief=" + std::string(cfg.low_power_wake_belief ? "true" : "false");
331
332 if (cfg.pairing_discovery_commands != DEFAULTS.pairing_discovery_commands)
333 result += " pairing_discovery_commands=" + discovery_commands_to_string(cfg.pairing_discovery_commands);
334 // The default is auto; an explicit destination is the only non-default state worth emitting
335 // (the destination bytes are unused while auto is set).
337 result +=
338 " pairing_discovery_destination=" + discovery_destination_to_string(cfg.pairing_discovery_destination_auto,
340 }
341 if (cfg.pairing_discovery_payload_enabled != DEFAULTS.pairing_discovery_payload_enabled ||
342 cfg.pairing_discovery_payload != DEFAULTS.pairing_discovery_payload) {
343 result += " pairing_discovery_payload=" +
345 }
346 if (cfg.pairing_discovery_low_power != DEFAULTS.pairing_discovery_low_power)
347 result += " pairing_discovery_low_power=" + std::string(cfg.pairing_discovery_low_power ? "true" : "false");
348 if (cfg.pairing_discovery_ack_capable != DEFAULTS.pairing_discovery_ack_capable)
349 result += " pairing_discovery_ack_capable=" + std::string(cfg.pairing_discovery_ack_capable ? "true" : "false");
350 // scan_power_classes is an enum, not a plain number, so it stays hand-written here like the
351 // three RX-bandwidth fields above (it's a SELECT_PARAMS row, not a NUMBER_PARAMS one).
352 if (cfg.scan_power_classes != DEFAULTS.scan_power_classes)
353 result += " scan_power_classes=" + scan_power_classes_to_string(cfg.scan_power_classes);
354 // pairing_discover_confirm is an enum, not a plain number, so it stays hand-written here like
355 // the two SELECT_PARAMS rows above; pairing_key_init_delay_ms is a plain NUMBER_PARAMS entry.
356 if (cfg.pairing_discover_confirm != DEFAULTS.pairing_discover_confirm)
357 result += " pairing_discover_confirm=" + discover_confirm_mode_to_string(cfg.pairing_discover_confirm);
358 // pairing_discovery_listen_channels is an enum SELECT_PARAMS row, same as the two above.
359 if (cfg.pairing_discovery_listen_channels != DEFAULTS.pairing_discovery_listen_channels) {
360 result += " pairing_discovery_listen_channels=" +
362 }
363 // pairing_discovery_preamble, pairing_discovery_wait_ms, pairing_discovery_initial_dwell_ms,
364 // pairing_key_exchange_retries, and pairing_key_init_delay_ms are plain NUMBER_PARAMS entries —
365 // covered by the loop above.
366
367 return result;
368}
369
371 const std::string result = tuning_config_snapshot(cfg);
372 if (result.empty())
373 return "Tuning: defaults active";
374 return "Tuning overrides active:" + result;
375}
376
377} // namespace home_io_control
378} // namespace esphome
BandwidthTableView lr1121_bandwidth_table()
The LR1121 RX-bandwidth option table (see sx1262_bandwidth_table()).
std::string discovery_commands_to_csv(const std::vector< DiscoveryCommand > &commands)
Format the ordered discovery command list as a UI/preset option string.
DiscoveryListenChannels
Which channels PairingEngine's discovery wait listens on.
@ ALL
CH1->CH2->CH3, including the request channel.
@ SKIP_REQUEST
Default. The two channels that are not the request channel.
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; half the 76.8 kHz sizing floor, for probing only.
@ 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 76.8 kHz sizing floor.
@ BW_156_2_KHZ
156.2 kHz — the value a Somfy LightVar_Wh_io dimmer needs.
@ BW_117_3_KHZ
117.3 kHz — clears the sizing floor with ~20 kHz of offset margin.
@ BW_187_2_KHZ
187.2 kHz — widest selectable option.
const TuningNumberParam * tuning_number_params_end()
const char * power_save_mode_name(uint8_t mode)
Get a human-readable power save mode name.
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.
std::optional< DiscoverConfirmMode > discover_confirm_mode_from_string(const std::string &value)
Parse a pairing_discover_confirm string into the enum.
LR1121RxBandwidth
Valid LR1121 RX bandwidth options (register values).
@ BW_39_0_KHZ
39.0 kHz — narrowest; half the 76.8 kHz sizing floor, for probing only.
@ BW_156_2_KHZ
156.2 kHz — wider tolerance for peer carrier offset.
@ BW_187_2_KHZ
187.2 kHz — widest selectable option.
std::string lr1121_bandwidth_to_string(LR1121RxBandwidth bw)
Format an LR1121 bandwidth enum as its YAML/UI option string (bare kHz number).
std::optional< ScanPowerClasses > scan_power_classes_from_string(const std::string &value)
Parse a scan_power_classes string into the enum.
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.
ScanPowerClasses
Which power classes scan_paired_devices() calls.
@ ALWAYS_ALIVE
Always-alive pass only: the single-shape roll-call, ~6 s.
@ BOTH
Low-power pass, then always-alive pass (default).
std::string sx1276_bandwidth_to_string(SX1276RxBandwidth bw)
Format an SX1276 bandwidth enum as its YAML/UI option string (bare kHz number).
bool scan_power_classes_include(ScanPowerClasses selection, uint8_t power_save_mode)
Whether selection calls the roll-call pass for power_save_mode.
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::optional< DiscoveryListenChannels > discovery_listen_channels_from_string(const std::string &value)
Parse a DiscoveryListenChannels from its YAML/select option string.
std::string bandwidth_to_string(float khz)
Format a kHz value as its YAML/UI option string (bare number, one decimal, e.g. "117....
const TuningNumberParam * tuning_number_params_begin()
std::string tuning_config_full_snapshot(const TuningConfig &cfg)
Format the current tuning configuration as a full one-line snapshot.
float sx1262_bandwidth_to_khz(SX1262RxBandwidth bw)
Convert a bandwidth enum to the numeric kHz value used in YAML/logs.
std::string sx1262_bandwidth_to_string(SX1262RxBandwidth bw)
Format a bandwidth enum as its YAML/UI option string (bare kHz number, e.g.
DiscoverConfirmMode
Whether and how PairingEngine sends CMD_DISCOVER_CONFIRM (0x2C) to a freshly-discovered device before...
@ SKIP
Kill switch: sends no 0x2C and applies no post-step pause.
@ SEND_WITH_ACK
Like SEND, but also sets CTRL1_ACK for an always-alive target (0x10) — the shape every corpus hub (VE...
BandwidthTableView sx1262_bandwidth_table()
The SX1262 RX-bandwidth option table.
std::string tuning_update_log_line(const std::string &name, const std::string &value)
Format a single tuning update for the log.
std::string discovery_listen_channels_to_string(DiscoveryListenChannels value)
Render a DiscoveryListenChannels as its YAML/select option string.
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 uint8_t BROADCAST_DISCOVER_ALT[NODE_ID_SIZE]
Alternate discovery / 1W broadcast address (0x00003F).
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.
std::optional< SX1276RxBandwidth > sx1276_bandwidth_from_string(const std::string &value)
Convert a YAML SX1276 bandwidth string to the enum value.
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()).
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.
std::string discover_confirm_mode_to_string(DiscoverConfirmMode value)
Format a DiscoverConfirmMode value for YAML/logs.
std::string scan_power_classes_to_string(ScanPowerClasses value)
Format a ScanPowerClasses value for YAML/logs.
IO-Homecontrol command IDs, result codes and protocol enumerations.
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 pairing_discovery_destination_auto
When true, map commands to conventional addresses.
SX1276RxBandwidth sx1276_rx_bandwidth
SX1276 RX bandwidth selector.
SX1262RxBandwidth sx1262_rx_bandwidth
SX1262 RX bandwidth selector.
std::vector< uint8_t > pairing_discovery_destination
Destination when auto=false.
std::vector< DiscoveryCommand > pairing_discovery_commands
Ordered discovery commands.
DiscoveryListenChannels pairing_discovery_listen_channels
Channels the discovery response wait covers.
DiscoverConfirmMode pairing_discover_confirm
Whether/how to send CMD_DISCOVER_CONFIRM (0x2C) during pairing.
bool pairing_discovery_ack_capable
Set ACK (CTRL1_ACK) on the discovery broadcast only.
bool pairing_discovery_low_power
Set LOW_POWER flag in discovery frames.
bool pairing_discovery_payload_enabled
Whether the optional payload is enabled.
LR1121RxBandwidth lr1121_rx_bandwidth
LR1121 RX bandwidth selector.
bool low_power_wake_belief
Order a low_power device's start-frame tries by its wake belief (short preamble first when it is beli...
uint8_t pairing_discovery_payload
Optional payload byte (used for 0x2E).
ScanPowerClasses scan_power_classes
Power classes the scan_paired_devices roll-call calls.
One numeric tuning parameter: its wire name plus accessors over TuningConfig.
Runtime tuning configuration for pairing and radio diagnostics.
Table-driven registry of runtime tuning parameters.