From 7d237f873001b1f08775ca5da80d7a284ab20e8f Mon Sep 17 00:00:00 2001 From: mikecarper Date: Fri, 8 May 2026 16:57:03 -0700 Subject: [PATCH] Update keymind retry controls --- docs/cli_commands.md | 10 +-- docs/halo_keymind_settings.md | 11 +++- examples/simple_repeater/MyMesh.cpp | 37 ++++++++--- src/Mesh.cpp | 5 +- src/helpers/ArduinoSerialInterface.cpp | 4 ++ src/helpers/ArduinoSerialInterface.h | 3 +- src/helpers/CommonCLI.cpp | 86 ++++++++++++++++++-------- src/helpers/CommonCLI.h | 2 + 8 files changed, 114 insertions(+), 44 deletions(-) diff --git a/docs/cli_commands.md b/docs/cli_commands.md index 505a82059..18e801637 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md @@ -559,18 +559,18 @@ This document provides an overview of CLI commands that can be sent to MeshCore #### View or change adaptive coding rate for direct retry packets **Usage:** - `get direct.retry.cr` -- `set direct.retry.cr ,,` -- `set direct.retry.cr ,,,` +- `set direct.retry.cr ,,,` +- `set direct.retry.cr off` **Parameters:** - `cr4_min`: SNR in dB where retry packets use `CR4` - `cr5_min`: SNR in dB where retry packets use `CR5` +- `cr7_min`: SNR in dB where retry packets use `CR7` - `cr8_max`: SNR in dB where retry packets use `CR8` -- `low`: optional repeated low boundary; both low values must match **Default:** `10.0,7.5,2.5,2.5` -**Note:** DM retry packets with a recent repeater table entry use that entry's SNR to pick a local transmit coding rate. With the default, SNR `10.0 dB` and up uses `CR4`, SNR `7.5 dB` and up uses `CR5`, SNR `2.5 dB` and down uses `CR8`, and the middle band uses `CR7`. `CR6` is never selected. The shorter form `set direct.retry.cr 10.0,7.5,2.5` is equivalent to `set direct.retry.cr 10.0,7.5,2.5,2.5`. +**Note:** DM retry packets use the next-hop SNR from a recent repeater table entry to pick a local transmit coding rate; if no recent entry is available, retry packets use `CR5`. With the default, SNR `10.0 dB` and up uses `CR4`, SNR `7.5 dB` and up uses `CR5`, SNR `2.5 dB` and down uses `CR8`, and the middle band uses `CR7`. `CR6` is never selected. Use `set direct.retry.cr off` to disable adaptive coding-rate overrides. If adaptive selection chooses `CR4`, retries after the third attempt use `CR5`. --- @@ -778,7 +778,7 @@ This document provides an overview of CLI commands that can be sent to MeshCore - `set flood.retry.count ` **Parameters:** -- `value`: Maximum retry attempts after initial flood TX (`0`-`3`) +- `value`: Maximum retry attempts after initial flood TX (`0`-`15`) **Default:** `3` for `rooftop` and `mobile`, `1` for `infra` diff --git a/docs/halo_keymind_settings.md b/docs/halo_keymind_settings.md index 908c390ca..1be3ddb0f 100644 --- a/docs/halo_keymind_settings.md +++ b/docs/halo_keymind_settings.md @@ -111,6 +111,15 @@ Direct retry applies to direct-routed packets. A queued resend is canceled when | `direct.retry.count` | Maximum direct retry attempts after initial TX. | `get direct.retry.count`, `set direct.retry.count <1-15>` | `set direct.retry.count 15` | | `direct.retry.base` | Base wait in milliseconds before retry. | `get direct.retry.base`, `set direct.retry.base <10-5000>` | `set direct.retry.base 175` | | `direct.retry.step` | Milliseconds added per retry attempt. | `get direct.retry.step`, `set direct.retry.step <0-5000>` | `set direct.retry.step 100` | +| `direct.retry.cr` | Adaptive coding-rate thresholds for direct retry packets. Uses `CR4`, `CR5`, `CR7`, or `CR8`; `CR6` is never selected. | `get direct.retry.cr`, `set direct.retry.cr ,,,`, `set direct.retry.cr off` | `set direct.retry.cr 10.0,7.5,2.5,0` | + +The default adaptive coding-rate profile is `10.0,7.5,2.5,2.5`. +SNR `10.0 dB` and up uses `CR4`, `7.5 dB` and up uses `CR5`, +`2.5 dB` and down uses `CR8`, and the middle band uses `CR7`. If no +recent repeater table entry is available, retry packets use `CR5`. Use +`set direct.retry.cr off` to disable adaptive coding-rate overrides. If +adaptive selection chooses `CR4`, retries after the third attempt use +`CR5`. Preset details: @@ -141,7 +150,7 @@ Flood retry applies to flood-routed packets. A queued retry is canceled when a q | Setting | What it does | How to use | Example | | --- | --- | --- | --- | -| `flood.retry.count` | Maximum flood retry attempts after initial TX. `0` disables flood retry. | `get flood.retry.count`, `set flood.retry.count <0-3>` | `set flood.retry.count 3` | +| `flood.retry.count` | Maximum flood retry attempts after initial TX. `0` disables flood retry. | `get flood.retry.count`, `set flood.retry.count <0-15>` | `set flood.retry.count 7` | | `flood.retry.path` | Maximum path hash count eligible for flood retry, or `off` to disable the gate. | `get flood.retry.path`, `set flood.retry.path <0-63/off>` | `set flood.retry.path 1` | | `flood.retry.advert` | Allows or blocks retry for node advert packets (`type=4`). Default is `off`. | `get flood.retry.advert`, `set flood.retry.advert on/off` | `set flood.retry.advert off` | | `flood.retry.prefixes` | Target prefixes. If set, only matching downstream echoes cancel a retry. | `get flood.retry.prefixes`, `set flood.retry.prefixes ` | `set flood.retry.prefixes BEEBB0,425E5C` | diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index b127db30b..d8e72cde8 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -744,7 +744,8 @@ void MyMesh::onDirectRetryEvent(const char* event, const mesh::Packet* packet, u time_label = "echo_ms"; } - MESH_DEBUG_PRINTLN("%s direct retry %s (retry=%u, type=%d, route=%s, payload_len=%d, hop=%s, next_hop=%s, pkt=%s, tbl=%s, %s=%lu)", + uint8_t log_cr = (packet->tx_cr >= 4 && packet->tx_cr <= 8) ? packet->tx_cr : active_cr; + MESH_DEBUG_PRINTLN("%s direct retry %s (retry=%u, type=%d, route=%s, payload_len=%d, hop=%s, next_hop=%s, pkt=%s, tbl=%s, cr=%u, %s=%lu)", getLogDateTime(), event, (unsigned int)retry_attempt, @@ -755,6 +756,7 @@ void MyMesh::onDirectRetryEvent(const char* event, const mesh::Packet* packet, u next_hop, snr_pkt_text, snr_table_text, + (unsigned int)log_cr, time_label, (unsigned long)delay_millis); @@ -762,7 +764,7 @@ void MyMesh::onDirectRetryEvent(const char* event, const mesh::Packet* packet, u File f = openAppend(PACKET_LOG_FILE); if (f) { f.print(getLogDateTime()); - f.printf(": DIRECT RETRY %s (retry=%u, type=%d, route=%s, payload_len=%d, hop=%s, next_hop=%s, pkt=%s, tbl=%s, %s=%lu)\n", + f.printf(": DIRECT RETRY %s (retry=%u, type=%d, route=%s, payload_len=%d, hop=%s, next_hop=%s, pkt=%s, tbl=%s, cr=%u, %s=%lu)\n", event, (unsigned int)retry_attempt, (uint32_t)packet->getPayloadType(), @@ -772,6 +774,7 @@ void MyMesh::onDirectRetryEvent(const char* event, const mesh::Packet* packet, u next_hop, snr_pkt_text, snr_table_text, + (unsigned int)log_cr, time_label, (unsigned long)delay_millis); f.close(); @@ -847,6 +850,12 @@ bool MyMesh::allowDirectRetry(const mesh::Packet* packet, const uint8_t* next_ho return true; } uint8_t MyMesh::getDirectRetryCodingRateForSNR(int8_t snr_x4) const { + if (_prefs.direct_retry_cr4_snr_x4 == 0 + && _prefs.direct_retry_cr5_snr_x4 == 0 + && _prefs.direct_retry_cr7_snr_x4 == 0 + && _prefs.direct_retry_cr8_snr_x4 == 0) { + return 0; + } if (snr_x4 >= _prefs.direct_retry_cr4_snr_x4) { return 4; } @@ -856,11 +865,13 @@ uint8_t MyMesh::getDirectRetryCodingRateForSNR(int8_t snr_x4) const { if (snr_x4 <= _prefs.direct_retry_cr8_snr_x4) { return 8; } + if (snr_x4 >= _prefs.direct_retry_cr7_snr_x4) { + return 7; + } return 7; } void MyMesh::configureDirectRetryPacket(mesh::Packet* retry, const mesh::Packet* original, uint8_t retry_attempt) { (void) original; - (void) retry_attempt; if (retry == NULL || !retry->isRouteDirect()) { return; @@ -873,6 +884,7 @@ void MyMesh::configureDirectRetryPacket(mesh::Packet* retry, const mesh::Packet* case PAYLOAD_TYPE_RESPONSE: case PAYLOAD_TYPE_TXT_MSG: case PAYLOAD_TYPE_ANON_REQ: + case PAYLOAD_TYPE_TRACE: case PAYLOAD_TYPE_MULTIPART: break; default: @@ -885,13 +897,19 @@ void MyMesh::configureDirectRetryPacket(mesh::Packet* retry, const mesh::Packet* return; } - const auto* recent = ((const SimpleMeshTables *)getTables())->findRecentRepeaterByHash(prefix, prefix_len); - if (recent == NULL) { + if (_prefs.direct_retry_cr4_snr_x4 == 0 + && _prefs.direct_retry_cr5_snr_x4 == 0 + && _prefs.direct_retry_cr7_snr_x4 == 0 + && _prefs.direct_retry_cr8_snr_x4 == 0) { return; } - uint8_t retry_cr = getDirectRetryCodingRateForSNR(recent->snr_x4); - if (retry_cr >= 4 && retry_cr <= 8 && retry_cr != active_cr) { + const auto* recent = ((const SimpleMeshTables *)getTables())->findRecentRepeaterByHash(prefix, prefix_len); + uint8_t retry_cr = (recent != NULL) ? getDirectRetryCodingRateForSNR(recent->snr_x4) : 5; + if (retry_cr == 4 && retry_attempt > 3) { + retry_cr = 5; + } + if (retry_cr >= 4 && retry_cr <= 8 && retry_cr != 6 && retry_cr != active_cr) { retry->tx_cr = retry_cr; } } @@ -1145,7 +1163,7 @@ uint32_t MyMesh::getDirectRetryEchoDelay(const mesh::Packet* packet) const { return base_wait_millis + scaled_wait_millis; } bool MyMesh::allowFloodRetry(const mesh::Packet* packet) const { - if (_prefs.disable_fwd || constrain(_prefs.flood_retry_attempts, (uint8_t)0, (uint8_t)3) == 0) { + if (_prefs.disable_fwd || constrain(_prefs.flood_retry_attempts, (uint8_t)0, (uint8_t)15) == 0) { return false; } if (packet != NULL && packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && !_prefs.flood_retry_advert_enabled) { @@ -1401,7 +1419,7 @@ uint8_t MyMesh::getFloodRetryMaxAttempts(const mesh::Packet* packet) const { if (_prefs.disable_fwd) { return 0; } - return constrain(_prefs.flood_retry_attempts, (uint8_t)0, (uint8_t)3); + return constrain(_prefs.flood_retry_attempts, (uint8_t)0, (uint8_t)15); } bool MyMesh::isFloodRetryEchoTarget(const mesh::Packet* packet, uint8_t progress_marker) const { if (packet == NULL || !packet->isRouteFlood()) { @@ -1809,6 +1827,7 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc _prefs.flood_retry_advert_enabled = 0; _prefs.direct_retry_cr4_snr_x4 = DIRECT_RETRY_CR4_MIN_SNR_X4_DEFAULT; _prefs.direct_retry_cr5_snr_x4 = DIRECT_RETRY_CR5_MIN_SNR_X4_DEFAULT; + _prefs.direct_retry_cr7_snr_x4 = DIRECT_RETRY_CR7_MIN_SNR_X4_DEFAULT; _prefs.direct_retry_cr8_snr_x4 = DIRECT_RETRY_CR8_MAX_SNR_X4_DEFAULT; StrHelper::strncpy(_prefs.node_name, ADVERT_NAME, sizeof(_prefs.node_name)); _prefs.node_lat = ADVERT_LAT; diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 730d9f499..747ab36df 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -6,6 +6,7 @@ namespace mesh { static const uint8_t DIRECT_RETRY_MAX_ATTEMPTS_DEFAULT = 15; static const uint8_t DIRECT_RETRY_MAX_ATTEMPTS_HARD_MAX = 15; static const uint8_t FLOOD_RETRY_MAX_ATTEMPTS_DEFAULT = 3; +static const uint8_t FLOOD_RETRY_MAX_ATTEMPTS_HARD_MAX = 15; static uint8_t decodeTraceHashSize(uint8_t flags, uint8_t route_bytes) { uint8_t code = flags & 0x03; @@ -966,8 +967,8 @@ void Mesh::armFloodRetryOnSendComplete(const Packet* packet) { uint8_t max_attempts = getFloodRetryMaxAttempts(packet); if (max_attempts < 1) { max_attempts = 1; - } else if (max_attempts > FLOOD_RETRY_MAX_ATTEMPTS_DEFAULT) { - max_attempts = FLOOD_RETRY_MAX_ATTEMPTS_DEFAULT; + } else if (max_attempts > FLOOD_RETRY_MAX_ATTEMPTS_HARD_MAX) { + max_attempts = FLOOD_RETRY_MAX_ATTEMPTS_HARD_MAX; } if (_flood_retries[i].retry_attempts_sent >= max_attempts) { Packet* final_wait = obtainNewPacket(); diff --git a/src/helpers/ArduinoSerialInterface.cpp b/src/helpers/ArduinoSerialInterface.cpp index a01fa5866..6b4439740 100644 --- a/src/helpers/ArduinoSerialInterface.cpp +++ b/src/helpers/ArduinoSerialInterface.cpp @@ -17,6 +17,10 @@ bool ArduinoSerialInterface::isConnected() const { return true; // no way of knowing, so assume yes } +bool ArduinoSerialInterface::isReadBusy() const { + return false; +} + bool ArduinoSerialInterface::isWriteBusy() const { return false; } diff --git a/src/helpers/ArduinoSerialInterface.h b/src/helpers/ArduinoSerialInterface.h index c4086353a..4fa2b75d1 100644 --- a/src/helpers/ArduinoSerialInterface.h +++ b/src/helpers/ArduinoSerialInterface.h @@ -28,7 +28,8 @@ public: bool isConnected() const override; + bool isReadBusy() const override; bool isWriteBusy() const override; size_t writeFrame(const uint8_t src[], size_t len) override; size_t checkRecvFrame(uint8_t dest[]) override; -}; \ No newline at end of file +}; diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 6a383ce44..db56c5585 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -33,7 +33,7 @@ #define FLOOD_RETRY_PREFS_MAGIC_0 0xF4 #define FLOOD_RETRY_PREFS_MAGIC_1 0x52 #define FLOOD_RETRY_COUNT_MIN 0 -#define FLOOD_RETRY_COUNT_MAX 3 +#define FLOOD_RETRY_COUNT_MAX 15 #define FLOOD_RETRY_ADVERT_DEFAULT 0 // Believe it or not, this std C function is busted on some platforms! @@ -121,29 +121,53 @@ static float directRetryCrX4ToDb(int8_t snr_x4) { static void setDirectRetryCrDefaults(NodePrefs* prefs) { prefs->direct_retry_cr4_snr_x4 = DIRECT_RETRY_CR4_MIN_SNR_X4_DEFAULT; prefs->direct_retry_cr5_snr_x4 = DIRECT_RETRY_CR5_MIN_SNR_X4_DEFAULT; + prefs->direct_retry_cr7_snr_x4 = DIRECT_RETRY_CR7_MIN_SNR_X4_DEFAULT; prefs->direct_retry_cr8_snr_x4 = DIRECT_RETRY_CR8_MAX_SNR_X4_DEFAULT; } -static bool directRetryCrThresholdsAreValid(int8_t cr4_snr_x4, int8_t cr5_snr_x4, int8_t cr8_snr_x4) { - return (cr4_snr_x4 != 0 || cr5_snr_x4 != 0 || cr8_snr_x4 != 0) - && cr4_snr_x4 >= cr5_snr_x4 - && cr5_snr_x4 >= cr8_snr_x4; +static void setDirectRetryCrOff(NodePrefs* prefs) { + prefs->direct_retry_cr4_snr_x4 = 0; + prefs->direct_retry_cr5_snr_x4 = 0; + prefs->direct_retry_cr7_snr_x4 = 0; + prefs->direct_retry_cr8_snr_x4 = 0; +} + +static bool directRetryCrThresholdsAreOff(int8_t cr4_snr_x4, int8_t cr5_snr_x4, int8_t cr7_snr_x4, int8_t cr8_snr_x4) { + return cr4_snr_x4 == 0 && cr5_snr_x4 == 0 && cr7_snr_x4 == 0 && cr8_snr_x4 == 0; +} + +static bool directRetryCrThresholdsAreValid(int8_t cr4_snr_x4, int8_t cr5_snr_x4, int8_t cr7_snr_x4, int8_t cr8_snr_x4) { + return directRetryCrThresholdsAreOff(cr4_snr_x4, cr5_snr_x4, cr7_snr_x4, cr8_snr_x4) + || ((cr4_snr_x4 != 0 || cr5_snr_x4 != 0 || cr7_snr_x4 != 0 || cr8_snr_x4 != 0) + && cr4_snr_x4 >= cr5_snr_x4 + && cr5_snr_x4 >= cr7_snr_x4 + && cr7_snr_x4 >= cr8_snr_x4); } static void sanitizeDirectRetryCrThresholds(NodePrefs* prefs) { if (!directRetryCrThresholdsAreValid(prefs->direct_retry_cr4_snr_x4, prefs->direct_retry_cr5_snr_x4, + prefs->direct_retry_cr7_snr_x4, prefs->direct_retry_cr8_snr_x4)) { setDirectRetryCrDefaults(prefs); } } static void formatDirectRetryCrThresholds(const NodePrefs* prefs, char* reply) { - char cr4[12], cr5[12], cr8[12]; + if (directRetryCrThresholdsAreOff(prefs->direct_retry_cr4_snr_x4, + prefs->direct_retry_cr5_snr_x4, + prefs->direct_retry_cr7_snr_x4, + prefs->direct_retry_cr8_snr_x4)) { + strcpy(reply, "> off"); + return; + } + + char cr4[12], cr5[12], cr7[12], cr8[12]; strcpy(cr4, StrHelper::ftoa(directRetryCrX4ToDb(prefs->direct_retry_cr4_snr_x4))); strcpy(cr5, StrHelper::ftoa(directRetryCrX4ToDb(prefs->direct_retry_cr5_snr_x4))); + strcpy(cr7, StrHelper::ftoa(directRetryCrX4ToDb(prefs->direct_retry_cr7_snr_x4))); strcpy(cr8, StrHelper::ftoa(directRetryCrX4ToDb(prefs->direct_retry_cr8_snr_x4))); - sprintf(reply, "> %s,%s,%s,%s", cr4, cr5, cr8, cr8); + sprintf(reply, "> %s,%s,%s,%s", cr4, cr5, cr7, cr8); } static uint16_t retryPresetStepDefault(uint8_t preset) { @@ -388,35 +412,36 @@ static bool parseDirectRetryCrThresholds(char* value, NodePrefs* prefs) { if (value == NULL || prefs == NULL) { return false; } + if (strcmp(value, "off") == 0) { + setDirectRetryCrOff(prefs); + return true; + } - const char* parts[4]; - int num = mesh::Utils::parseTextParts(value, parts, 4); - if (num != 3 && num != 4) { + const char* parts[5]; + int num = mesh::Utils::parseTextParts(value, parts, 5); + if (num != 4) { return false; } int8_t cr4_snr_x4; int8_t cr5_snr_x4; + int8_t cr7_snr_x4; int8_t cr8_snr_x4; if (!parseDirectRetryCrDb(parts[0], cr4_snr_x4) || !parseDirectRetryCrDb(parts[1], cr5_snr_x4) - || !parseDirectRetryCrDb(parts[num == 4 ? 3 : 2], cr8_snr_x4)) { + || !parseDirectRetryCrDb(parts[2], cr7_snr_x4) + || !parseDirectRetryCrDb(parts[3], cr8_snr_x4)) { return false; } - if (num == 4) { - int8_t repeated_low_snr_x4; - if (!parseDirectRetryCrDb(parts[2], repeated_low_snr_x4) || repeated_low_snr_x4 != cr8_snr_x4) { - return false; - } - } - - if (!directRetryCrThresholdsAreValid(cr4_snr_x4, cr5_snr_x4, cr8_snr_x4)) { + if (directRetryCrThresholdsAreOff(cr4_snr_x4, cr5_snr_x4, cr7_snr_x4, cr8_snr_x4) + || !directRetryCrThresholdsAreValid(cr4_snr_x4, cr5_snr_x4, cr7_snr_x4, cr8_snr_x4)) { return false; } prefs->direct_retry_cr4_snr_x4 = cr4_snr_x4; prefs->direct_retry_cr5_snr_x4 = cr5_snr_x4; + prefs->direct_retry_cr7_snr_x4 = cr7_snr_x4; prefs->direct_retry_cr8_snr_x4 = cr8_snr_x4; return true; } @@ -527,8 +552,10 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { sizeof(_prefs->direct_retry_cr4_snr_x4)); // 660 retry_cr_read += file.read((uint8_t *)&_prefs->direct_retry_cr5_snr_x4, sizeof(_prefs->direct_retry_cr5_snr_x4)); // 661 + retry_cr_read += file.read((uint8_t *)&_prefs->direct_retry_cr7_snr_x4, + sizeof(_prefs->direct_retry_cr7_snr_x4)); // 662 retry_cr_read += file.read((uint8_t *)&_prefs->direct_retry_cr8_snr_x4, - sizeof(_prefs->direct_retry_cr8_snr_x4)); // 662 + sizeof(_prefs->direct_retry_cr8_snr_x4)); // 663 // PowerSaving-only prefs stored radio_fem_rxgain at 291, before direct retry timing existed. if (radio_fem_rxgain_read != sizeof(_prefs->radio_fem_rxgain) && legacy_retry_attempts_read == sizeof(legacy_retry_attempts_or_radio_fem_rxgain) @@ -536,7 +563,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { || _prefs->direct_retry_timing_magic[1] != DIRECT_RETRY_TIMING_MAGIC_1)) { _prefs->radio_fem_rxgain = constrain(legacy_retry_attempts_or_radio_fem_rxgain, 0, 1); } - // next: 663 + // next: 664 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -614,8 +641,14 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { _prefs->flood_retry_advert_enabled = constrain(_prefs->flood_retry_advert_enabled, 0, 1); } } - if (retry_cr_read != sizeof(_prefs->direct_retry_cr4_snr_x4) + if (retry_cr_read == sizeof(_prefs->direct_retry_cr4_snr_x4) + sizeof(_prefs->direct_retry_cr5_snr_x4) + + sizeof(_prefs->direct_retry_cr7_snr_x4)) { + _prefs->direct_retry_cr8_snr_x4 = _prefs->direct_retry_cr7_snr_x4; + sanitizeDirectRetryCrThresholds(_prefs); + } else if (retry_cr_read != sizeof(_prefs->direct_retry_cr4_snr_x4) + + sizeof(_prefs->direct_retry_cr5_snr_x4) + + sizeof(_prefs->direct_retry_cr7_snr_x4) + sizeof(_prefs->direct_retry_cr8_snr_x4)) { setDirectRetryCrDefaults(_prefs); } else { @@ -704,8 +737,9 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *)&_prefs->flood_retry_advert_enabled, sizeof(_prefs->flood_retry_advert_enabled)); // 659 file.write((uint8_t *)&_prefs->direct_retry_cr4_snr_x4, sizeof(_prefs->direct_retry_cr4_snr_x4)); // 660 file.write((uint8_t *)&_prefs->direct_retry_cr5_snr_x4, sizeof(_prefs->direct_retry_cr5_snr_x4)); // 661 - file.write((uint8_t *)&_prefs->direct_retry_cr8_snr_x4, sizeof(_prefs->direct_retry_cr8_snr_x4)); // 662 - // next: 663 + file.write((uint8_t *)&_prefs->direct_retry_cr7_snr_x4, sizeof(_prefs->direct_retry_cr7_snr_x4)); // 662 + file.write((uint8_t *)&_prefs->direct_retry_cr8_snr_x4, sizeof(_prefs->direct_retry_cr8_snr_x4)); // 663 + // next: 664 file.close(); } @@ -1285,7 +1319,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re savePrefs(); formatDirectRetryCrThresholds(_prefs, reply); } else { - strcpy(reply, "Error, expected cr4,cr5,cr8 or cr4,cr5,low,low"); + strcpy(reply, "Error, expected off or cr4,cr5,cr7,cr8"); } } else if (memcmp(config, "owner.info ", 11) == 0) { config += 11; @@ -1919,7 +1953,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep savePrefs(); formatDirectRetryCrThresholds(_prefs, reply); } else { - strcpy(reply, "Error, expected cr4,cr5,cr8 or cr4,cr5,low,low"); + strcpy(reply, "Error, expected off or cr4,cr5,cr7,cr8"); } } else if (memcmp(config, "owner.info ", 11) == 0) { config += 11; diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index ed5736497..104a7150c 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -65,6 +65,7 @@ #define DIRECT_RETRY_CR4_MIN_SNR_X4_DEFAULT 40 // 10.0 dB and up => CR4 #define DIRECT_RETRY_CR5_MIN_SNR_X4_DEFAULT 30 // 7.5 dB and up => CR5 +#define DIRECT_RETRY_CR7_MIN_SNR_X4_DEFAULT 10 // 2.5 dB and up => CR7 #define DIRECT_RETRY_CR8_MAX_SNR_X4_DEFAULT 10 // 2.5 dB and down => CR8 #define DIRECT_RETRY_CR_SNR_X4_MIN -128 #define DIRECT_RETRY_CR_SNR_X4_MAX 127 @@ -129,6 +130,7 @@ struct NodePrefs { // persisted to file uint8_t flood_retry_advert_enabled; int8_t direct_retry_cr4_snr_x4; int8_t direct_retry_cr5_snr_x4; + int8_t direct_retry_cr7_snr_x4; int8_t direct_retry_cr8_snr_x4; };