Add MEDIUM_TURBO modem preset (#10988)
* Protobufs * Wire up MEDIUM_TURBO modem preset MEDIUM_TURBO (500 kHz, SF9, CR 4/5) already existed in the protobuf enum but was never wired into firmware, so selecting it silently fell through to the LONG_FAST default and rendered an "Invalid" display name. Add its bw/sf/cr mapping (modemPresetToParams), display name (MediumTurbo/MedT), PRESETS_STD membership (standard regions only — 500 kHz does not fit EU868's 250 kHz band, so it stays out of PRESETS_EU_868 and is rejected/clamped there), and the MEDIUM SNR-grading bucket. Includes positive coverage in test_radio, EU868-reject + US-accept coverage in test_admin_radio and test_mesh_beacon, the STD preset count 9->10, an extended fuzz range, and the client-spec doc. * Address review feedback on MEDIUM_TURBO tests - test_mesh_beacon: assert has_mesh_beacon before checking the invalid preset was cleared, so the EU868-cleared test can't pass on a dropped message (matches the existing SHORT_TURBO test). - test_fuzz_packets: draw modem presets from _ModemPreset_ARRAYSIZE instead of a hard-coded 17 so the fuzz range tracks future enum additions automatically.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
.pio
|
.pio
|
||||||
pio
|
pio
|
||||||
|
.pio-docker
|
||||||
pio.tar
|
pio.tar
|
||||||
web
|
web
|
||||||
web.tar
|
web.tar
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ message LoRaRegionPresetMap {
|
|||||||
### 2.3 Why grouped (and the size envelope clients should respect)
|
### 2.3 Why grouped (and the size envelope clients should respect)
|
||||||
|
|
||||||
A `FromRadio` packet is capped at **512 bytes** (`MAX_TO_FROM_RADIO_SIZE`). Most regions
|
A `FromRadio` packet is capped at **512 bytes** (`MAX_TO_FROM_RADIO_SIZE`). Most regions
|
||||||
share one identical preset list (the "standard" 9-preset list), so the map is delivered
|
share one identical preset list (the "standard" 10-preset list), so the map is delivered
|
||||||
**grouped**: `groups` holds each _distinct_ preset list once, and `region_groups` maps every
|
**grouped**: `groups` holds each _distinct_ preset list once, and `region_groups` maps every
|
||||||
known region to one of those groups by index. This keeps the encoded size additive
|
known region to one of those groups by index. This keeps the encoded size additive
|
||||||
(`groups` + `region_groups`) rather than multiplicative, well under the cap.
|
(`groups` + `region_groups`) rather than multiplicative, well under the cap.
|
||||||
@@ -247,8 +247,8 @@ indices are assigned in region-table order (first region to use a profile create
|
|||||||
so they are stable as listed here:
|
so they are stable as listed here:
|
||||||
|
|
||||||
| group_index | default_preset | licensed_only | presets |
|
| group_index | default_preset | licensed_only | presets |
|
||||||
| ----------------------- | -------------- | ------------- | -------------------------------------------------------------------------------------------------------------- |
|
| ----------------------- | -------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| 0 (standard) | `LONG_FAST` | false | LONG_FAST, LONG_SLOW, MEDIUM_SLOW, MEDIUM_FAST, SHORT_SLOW, SHORT_FAST, LONG_MODERATE, SHORT_TURBO, LONG_TURBO |
|
| 0 (standard) | `LONG_FAST` | false | LONG_FAST, LONG_SLOW, MEDIUM_SLOW, MEDIUM_FAST, SHORT_SLOW, SHORT_FAST, LONG_MODERATE, SHORT_TURBO, LONG_TURBO, MEDIUM_TURBO |
|
||||||
| 1 (EU 868) | `LONG_FAST` | false | LONG_FAST, LONG_SLOW, MEDIUM_SLOW, MEDIUM_FAST, SHORT_SLOW, SHORT_FAST, LONG_MODERATE |
|
| 1 (EU 868) | `LONG_FAST` | false | LONG_FAST, LONG_SLOW, MEDIUM_SLOW, MEDIUM_FAST, SHORT_SLOW, SHORT_FAST, LONG_MODERATE |
|
||||||
| 2 (EU 866 SRD / "lite") | `LITE_FAST` | false | LITE_FAST, LITE_SLOW |
|
| 2 (EU 866 SRD / "lite") | `LITE_FAST` | false | LITE_FAST, LITE_SLOW |
|
||||||
| 3 (EU 868 narrow) | `NARROW_SLOW` | false | NARROW_FAST, NARROW_SLOW |
|
| 3 (EU 868 narrow) | `NARROW_SLOW` | false | NARROW_FAST, NARROW_SLOW |
|
||||||
|
|||||||
+1
-1
Submodule protobufs updated: 1ae3be3d54...9d589c1321
@@ -27,6 +27,9 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC
|
|||||||
case PRESET(MEDIUM_FAST):
|
case PRESET(MEDIUM_FAST):
|
||||||
return useShortName ? "MedF" : "MediumFast";
|
return useShortName ? "MedF" : "MediumFast";
|
||||||
break;
|
break;
|
||||||
|
case PRESET(MEDIUM_TURBO):
|
||||||
|
return useShortName ? "MedT" : "MediumTurbo";
|
||||||
|
break;
|
||||||
case PRESET(LONG_SLOW):
|
case PRESET(LONG_SLOW):
|
||||||
return useShortName ? "LongS" : "LongSlow";
|
return useShortName ? "LongS" : "LongSlow";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -844,6 +844,7 @@ void UIRenderer::drawFavoriteNode(OLEDDisplay *display, OLEDDisplayUiState *stat
|
|||||||
return -6.0f;
|
return -6.0f;
|
||||||
case PRESET(MEDIUM_SLOW):
|
case PRESET(MEDIUM_SLOW):
|
||||||
case PRESET(MEDIUM_FAST):
|
case PRESET(MEDIUM_FAST):
|
||||||
|
case PRESET(MEDIUM_TURBO):
|
||||||
return -5.5f;
|
return -5.5f;
|
||||||
case PRESET(SHORT_SLOW):
|
case PRESET(SHORT_SLOW):
|
||||||
case PRESET(SHORT_FAST):
|
case PRESET(SHORT_FAST):
|
||||||
|
|||||||
@@ -229,6 +229,11 @@ static inline void modemPresetToParams(meshtastic_Config_LoRaConfig_ModemPreset
|
|||||||
cr = 5;
|
cr = 5;
|
||||||
sf = 10;
|
sf = 10;
|
||||||
break;
|
break;
|
||||||
|
case PRESET(MEDIUM_TURBO):
|
||||||
|
bwKHz = wideLora ? 1625.0f : 500.0f;
|
||||||
|
cr = 5;
|
||||||
|
sf = 9;
|
||||||
|
break;
|
||||||
case PRESET(LONG_TURBO):
|
case PRESET(LONG_TURBO):
|
||||||
bwKHz = wideLora ? 1625.0f : 500.0f;
|
bwKHz = wideLora ? 1625.0f : 500.0f;
|
||||||
cr = 8;
|
cr = 8;
|
||||||
|
|||||||
@@ -39,8 +39,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = {
|
static const meshtastic_Config_LoRaConfig_ModemPreset PRESETS_STD[] = {
|
||||||
PRESET(LONG_FAST), PRESET(LONG_SLOW), PRESET(MEDIUM_SLOW), PRESET(MEDIUM_FAST), PRESET(SHORT_SLOW),
|
PRESET(LONG_FAST), PRESET(LONG_SLOW), PRESET(MEDIUM_SLOW), PRESET(MEDIUM_FAST), PRESET(SHORT_SLOW), PRESET(SHORT_FAST),
|
||||||
PRESET(SHORT_FAST), PRESET(LONG_MODERATE), PRESET(SHORT_TURBO), PRESET(LONG_TURBO), MODEM_PRESET_END};
|
PRESET(LONG_MODERATE), PRESET(SHORT_TURBO), PRESET(LONG_TURBO), PRESET(MEDIUM_TURBO), MODEM_PRESET_END};
|
||||||
|
|
||||||
static const meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = {
|
static const meshtastic_Config_LoRaConfig_ModemPreset PRESETS_EU_868[] = {
|
||||||
PRESET(LONG_FAST), PRESET(LONG_SLOW), PRESET(MEDIUM_SLOW), PRESET(MEDIUM_FAST),
|
PRESET(LONG_FAST), PRESET(LONG_SLOW), PRESET(MEDIUM_SLOW), PRESET(MEDIUM_FAST),
|
||||||
|
|||||||
@@ -374,7 +374,11 @@ typedef enum _meshtastic_Config_LoRaConfig_ModemPreset {
|
|||||||
Note: TCXO with tight tolerances (±5 ppm or better) is *absolutely required* at these narrow bandwidths.
|
Note: TCXO with tight tolerances (±5 ppm or better) is *absolutely required* at these narrow bandwidths.
|
||||||
Only compatible with SX127x and SX126x chipsets.
|
Only compatible with SX127x and SX126x chipsets.
|
||||||
Comparable link budget and data rate to LONG_MODERATE. */
|
Comparable link budget and data rate to LONG_MODERATE. */
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_TINY_SLOW = 15
|
meshtastic_Config_LoRaConfig_ModemPreset_TINY_SLOW = 15,
|
||||||
|
/* Medium Range - Turbo
|
||||||
|
This preset performs similarly to MEDIUM_FAST, but with 500kHz bandwidth.
|
||||||
|
It is not legal to use in all regions due to this wider bandwidth. */
|
||||||
|
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO = 16
|
||||||
} meshtastic_Config_LoRaConfig_ModemPreset;
|
} meshtastic_Config_LoRaConfig_ModemPreset;
|
||||||
|
|
||||||
typedef enum _meshtastic_Config_LoRaConfig_FEM_LNA_Mode {
|
typedef enum _meshtastic_Config_LoRaConfig_FEM_LNA_Mode {
|
||||||
@@ -767,8 +771,8 @@ extern "C" {
|
|||||||
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_ITU2_125CM+1))
|
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_ITU2_125CM+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
|
||||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_TINY_SLOW
|
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO
|
||||||
#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_TINY_SLOW+1))
|
#define _meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE ((meshtastic_Config_LoRaConfig_ModemPreset)(meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MIN meshtastic_Config_LoRaConfig_FEM_LNA_Mode_DISABLED
|
#define _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MIN meshtastic_Config_LoRaConfig_FEM_LNA_Mode_DISABLED
|
||||||
#define _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MAX meshtastic_Config_LoRaConfig_FEM_LNA_Mode_NOT_PRESENT
|
#define _meshtastic_Config_LoRaConfig_FEM_LNA_Mode_MAX meshtastic_Config_LoRaConfig_FEM_LNA_Mode_NOT_PRESENT
|
||||||
|
|||||||
@@ -2118,6 +2118,7 @@ static float getSnrLimit(meshtastic_Config_LoRaConfig_ModemPreset preset)
|
|||||||
return -6.0f;
|
return -6.0f;
|
||||||
case PRESET(MEDIUM_SLOW):
|
case PRESET(MEDIUM_SLOW):
|
||||||
case PRESET(MEDIUM_FAST):
|
case PRESET(MEDIUM_FAST):
|
||||||
|
case PRESET(MEDIUM_TURBO):
|
||||||
return -5.5f;
|
return -5.5f;
|
||||||
case PRESET(SHORT_SLOW):
|
case PRESET(SHORT_SLOW):
|
||||||
case PRESET(SHORT_FAST):
|
case PRESET(SHORT_FAST):
|
||||||
|
|||||||
@@ -484,7 +484,7 @@ static void test_validateConfigLora_allStdPresetsValidForUS()
|
|||||||
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST,
|
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST,
|
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO,
|
meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO,
|
meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(stdPresets) / sizeof(stdPresets[0]); i++) {
|
for (size_t i = 0; i < sizeof(stdPresets) / sizeof(stdPresets[0]); i++) {
|
||||||
@@ -498,7 +498,8 @@ static void test_validateConfigLora_allStdPresetsValidForUS()
|
|||||||
|
|
||||||
static void test_validateConfigLora_turboPresetsInvalidForEU868()
|
static void test_validateConfigLora_turboPresetsInvalidForEU868()
|
||||||
{
|
{
|
||||||
// EU_868 has PRESETS_EU_868 which excludes SHORT_TURBO and LONG_TURBO
|
// EU_868 has PRESETS_EU_868 which excludes the 500 kHz turbo presets
|
||||||
|
// (SHORT_TURBO, LONG_TURBO, MEDIUM_TURBO)
|
||||||
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
|
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
|
||||||
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_EU_868;
|
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_EU_868;
|
||||||
cfg.use_preset = true;
|
cfg.use_preset = true;
|
||||||
@@ -508,6 +509,9 @@ static void test_validateConfigLora_turboPresetsInvalidForEU868()
|
|||||||
|
|
||||||
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO;
|
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO;
|
||||||
TEST_ASSERT_FALSE_MESSAGE(RadioInterface::validateConfigLora(cfg), "LONG_TURBO should be invalid for EU_868");
|
TEST_ASSERT_FALSE_MESSAGE(RadioInterface::validateConfigLora(cfg), "LONG_TURBO should be invalid for EU_868");
|
||||||
|
|
||||||
|
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO;
|
||||||
|
TEST_ASSERT_FALSE_MESSAGE(RadioInterface::validateConfigLora(cfg), "MEDIUM_TURBO should be invalid for EU_868");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_validateConfigLora_validPresetsForEU868()
|
static void test_validateConfigLora_validPresetsForEU868()
|
||||||
@@ -598,13 +602,13 @@ static void test_validateConfigLora_unsetRegionOnlyAcceptsLongFast()
|
|||||||
|
|
||||||
static void test_validateConfigLora_allPresetsValidForLORA24()
|
static void test_validateConfigLora_allPresetsValidForLORA24()
|
||||||
{
|
{
|
||||||
// LORA_24 uses PROFILE_STD (9 presets) with wideLora=true
|
// LORA_24 uses PROFILE_STD (10 presets) with wideLora=true
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset stdPresets[] = {
|
meshtastic_Config_LoRaConfig_ModemPreset stdPresets[] = {
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW,
|
meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST,
|
meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST,
|
meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO,
|
meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE, meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO,
|
||||||
meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO,
|
meshtastic_Config_LoRaConfig_ModemPreset_LONG_TURBO, meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(stdPresets) / sizeof(stdPresets[0]); i++) {
|
for (size_t i = 0; i < sizeof(stdPresets) / sizeof(stdPresets[0]); i++) {
|
||||||
@@ -792,11 +796,11 @@ static void test_validateConfigLora_siblingLockedPresetStillFailsValidation()
|
|||||||
// RegionInfo preset list integrity tests
|
// RegionInfo preset list integrity tests
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
static void test_presetsStd_hasNineEntries()
|
static void test_presetsStd_hasTenEntries()
|
||||||
{
|
{
|
||||||
// PROFILE_STD should have exactly 9 presets
|
// PROFILE_STD should have exactly 10 presets (adds MEDIUM_TURBO to the turbo cluster)
|
||||||
const RegionInfo *us = getRegion(meshtastic_Config_LoRaConfig_RegionCode_US);
|
const RegionInfo *us = getRegion(meshtastic_Config_LoRaConfig_RegionCode_US);
|
||||||
TEST_ASSERT_EQUAL(9, us->getNumPresets());
|
TEST_ASSERT_EQUAL(10, us->getNumPresets());
|
||||||
TEST_ASSERT_EQUAL_PTR(PROFILE_STD.presets, us->getAvailablePresets());
|
TEST_ASSERT_EQUAL_PTR(PROFILE_STD.presets, us->getAvailablePresets());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1320,7 +1324,7 @@ void setup()
|
|||||||
RUN_TEST(test_validateConfigLora_siblingLockedPresetStillFailsValidation);
|
RUN_TEST(test_validateConfigLora_siblingLockedPresetStillFailsValidation);
|
||||||
|
|
||||||
// RegionInfo preset list integrity
|
// RegionInfo preset list integrity
|
||||||
RUN_TEST(test_presetsStd_hasNineEntries);
|
RUN_TEST(test_presetsStd_hasTenEntries);
|
||||||
RUN_TEST(test_presetsEU868_hasSevenEntries);
|
RUN_TEST(test_presetsEU868_hasSevenEntries);
|
||||||
RUN_TEST(test_presetsUndef_hasOneEntry);
|
RUN_TEST(test_presetsUndef_hasOneEntry);
|
||||||
RUN_TEST(test_defaultPresetIsInAvailablePresets);
|
RUN_TEST(test_defaultPresetIsInAvailablePresets);
|
||||||
|
|||||||
@@ -450,7 +450,8 @@ static meshtastic_AdminMessage fuzzAdminMessage()
|
|||||||
// manual bandwidth==0 path that used to SIGFPE the validator.
|
// manual bandwidth==0 path that used to SIGFPE the validator.
|
||||||
r.set_config.which_payload_variant = meshtastic_Config_lora_tag;
|
r.set_config.which_payload_variant = meshtastic_Config_lora_tag;
|
||||||
r.set_config.payload_variant.lora.region = (meshtastic_Config_LoRaConfig_RegionCode)rngRange(32);
|
r.set_config.payload_variant.lora.region = (meshtastic_Config_LoRaConfig_RegionCode)rngRange(32);
|
||||||
r.set_config.payload_variant.lora.modem_preset = (meshtastic_Config_LoRaConfig_ModemPreset)rngRange(16);
|
r.set_config.payload_variant.lora.modem_preset =
|
||||||
|
(meshtastic_Config_LoRaConfig_ModemPreset)rngRange(_meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE);
|
||||||
r.set_config.payload_variant.lora.use_preset = (rngRange(2) == 0);
|
r.set_config.payload_variant.lora.use_preset = (rngRange(2) == 0);
|
||||||
r.set_config.payload_variant.lora.bandwidth = rngRange(512); // includes 0
|
r.set_config.payload_variant.lora.bandwidth = rngRange(512); // includes 0
|
||||||
r.set_config.payload_variant.lora.channel_num = rngNext();
|
r.set_config.payload_variant.lora.channel_num = rngNext();
|
||||||
@@ -553,7 +554,7 @@ static meshtastic_MeshBeacon fuzzBeacon()
|
|||||||
fuzzChannelSettings(b.offer_channel);
|
fuzzChannelSettings(b.offer_channel);
|
||||||
b.offer_region = (meshtastic_Config_LoRaConfig_RegionCode)rngRange(32);
|
b.offer_region = (meshtastic_Config_LoRaConfig_RegionCode)rngRange(32);
|
||||||
b.has_offer_preset = (rngRange(2) == 0);
|
b.has_offer_preset = (rngRange(2) == 0);
|
||||||
b.offer_preset = (meshtastic_Config_LoRaConfig_ModemPreset)rngRange(16);
|
b.offer_preset = (meshtastic_Config_LoRaConfig_ModemPreset)rngRange(_meshtastic_Config_LoRaConfig_ModemPreset_ARRAYSIZE);
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -251,6 +251,44 @@ static void test_adminValidation_turboPresetOnUS_isAccepted(void)
|
|||||||
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, moduleConfig.mesh_beacon.broadcast_on_preset);
|
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO, moduleConfig.mesh_beacon.broadcast_on_preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify MEDIUM_TURBO is also cleared for EU_868. Like SHORT_TURBO/LONG_TURBO it is a 500 kHz preset
|
||||||
|
* that does not fit EU_868's 250 kHz band, so it must not survive admin validation there.
|
||||||
|
*/
|
||||||
|
static void test_adminValidation_mediumTurboPresetOnEU868_isCleared(void)
|
||||||
|
{
|
||||||
|
resetConfig();
|
||||||
|
|
||||||
|
meshtastic_ModuleConfig_MeshBeaconConfig bcfg = meshtastic_ModuleConfig_MeshBeaconConfig_init_zero;
|
||||||
|
bcfg.has_broadcast_on_preset = true;
|
||||||
|
bcfg.broadcast_on_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO;
|
||||||
|
|
||||||
|
testAdmin->handleSetModuleConfig(makeBeaconModuleConfig(bcfg));
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(moduleConfig.has_mesh_beacon);
|
||||||
|
TEST_ASSERT_FALSE(moduleConfig.mesh_beacon.has_broadcast_on_preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify MEDIUM_TURBO passes validation for US (PROFILE_STD allows the full turbo family).
|
||||||
|
* The same 500 kHz preset that is illegal in EU_868 must be preserved in permissive regions.
|
||||||
|
*/
|
||||||
|
static void test_adminValidation_mediumTurboPresetOnUS_isAccepted(void)
|
||||||
|
{
|
||||||
|
resetConfig();
|
||||||
|
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US;
|
||||||
|
initRegion();
|
||||||
|
|
||||||
|
meshtastic_ModuleConfig_MeshBeaconConfig bcfg = meshtastic_ModuleConfig_MeshBeaconConfig_init_zero;
|
||||||
|
bcfg.has_broadcast_on_preset = true;
|
||||||
|
bcfg.broadcast_on_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO;
|
||||||
|
|
||||||
|
testAdmin->handleSetModuleConfig(makeBeaconModuleConfig(bcfg));
|
||||||
|
|
||||||
|
TEST_ASSERT_TRUE(moduleConfig.mesh_beacon.has_broadcast_on_preset);
|
||||||
|
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO, moduleConfig.mesh_beacon.broadcast_on_preset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify an out-of-range region code (255) is sanitised to UNSET rather than stored verbatim.
|
* Verify an out-of-range region code (255) is sanitised to UNSET rather than stored verbatim.
|
||||||
* Important to prevent invalid proto enum values from reaching the broadcaster and being broadcast
|
* Important to prevent invalid proto enum values from reaching the broadcaster and being broadcast
|
||||||
@@ -1360,6 +1398,8 @@ BEACON_TEST_ENTRY void setup()
|
|||||||
RUN_TEST(test_adminValidation_turboPresetOnEU868_isCleared);
|
RUN_TEST(test_adminValidation_turboPresetOnEU868_isCleared);
|
||||||
RUN_TEST(test_adminValidation_longTurboPresetOnEU868_isCleared);
|
RUN_TEST(test_adminValidation_longTurboPresetOnEU868_isCleared);
|
||||||
RUN_TEST(test_adminValidation_turboPresetOnUS_isAccepted);
|
RUN_TEST(test_adminValidation_turboPresetOnUS_isAccepted);
|
||||||
|
RUN_TEST(test_adminValidation_mediumTurboPresetOnEU868_isCleared);
|
||||||
|
RUN_TEST(test_adminValidation_mediumTurboPresetOnUS_isAccepted);
|
||||||
RUN_TEST(test_adminValidation_unknownOfferRegion_isCleared);
|
RUN_TEST(test_adminValidation_unknownOfferRegion_isCleared);
|
||||||
RUN_TEST(test_adminValidation_validOfferRegion_isPreserved);
|
RUN_TEST(test_adminValidation_validOfferRegion_isPreserved);
|
||||||
RUN_TEST(test_adminValidation_targetUnknownRegion_isCleared);
|
RUN_TEST(test_adminValidation_targetUnknownRegion_isCleared);
|
||||||
|
|||||||
@@ -195,6 +195,47 @@ static void test_applyModemConfig_customCodingRateLowerThanPreset()
|
|||||||
TEST_ASSERT_EQUAL_UINT8(8, testRadio->getCr());
|
TEST_ASSERT_EQUAL_UINT8(8, testRadio->getCr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MEDIUM_TURBO performs like MEDIUM_FAST (sf=9, cr=5) but at 500 kHz. Verify the params resolve.
|
||||||
|
static void test_applyModemConfig_mediumTurbo()
|
||||||
|
{
|
||||||
|
config.lora = meshtastic_Config_LoRaConfig_init_zero;
|
||||||
|
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US;
|
||||||
|
config.lora.use_preset = true;
|
||||||
|
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO;
|
||||||
|
|
||||||
|
testRadio->reconfigure();
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(5, testRadio->getCr());
|
||||||
|
TEST_ASSERT_EQUAL_UINT8(9, testRadio->getSf());
|
||||||
|
TEST_ASSERT_FLOAT_WITHIN(0.01f, 500.0f, testRadio->getBw());
|
||||||
|
}
|
||||||
|
|
||||||
|
// MEDIUM_TURBO is a 500 kHz preset, so it is invalid for EU_868 and must clamp to the region default.
|
||||||
|
static void test_clampConfigLora_mediumTurboInvalidForEU868()
|
||||||
|
{
|
||||||
|
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
|
||||||
|
cfg.use_preset = true;
|
||||||
|
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_EU_868;
|
||||||
|
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO;
|
||||||
|
|
||||||
|
RadioInterface::clampConfigLora(cfg);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST, cfg.modem_preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MEDIUM_TURBO is valid for US (PROFILE_STD) and must be left unchanged.
|
||||||
|
static void test_clampConfigLora_mediumTurboValidForUS()
|
||||||
|
{
|
||||||
|
meshtastic_Config_LoRaConfig cfg = meshtastic_Config_LoRaConfig_init_zero;
|
||||||
|
cfg.use_preset = true;
|
||||||
|
cfg.region = meshtastic_Config_LoRaConfig_RegionCode_US;
|
||||||
|
cfg.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO;
|
||||||
|
|
||||||
|
RadioInterface::clampConfigLora(cfg);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_TURBO, cfg.modem_preset);
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// getRegionPresetMap() - region->valid-preset map sent to clients during want_config
|
// getRegionPresetMap() - region->valid-preset map sent to clients during want_config
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@@ -317,6 +358,9 @@ void setup()
|
|||||||
RUN_TEST(test_applyModemConfig_codingRateMatchesPreset);
|
RUN_TEST(test_applyModemConfig_codingRateMatchesPreset);
|
||||||
RUN_TEST(test_applyModemConfig_customCodingRateHigherThanPreset);
|
RUN_TEST(test_applyModemConfig_customCodingRateHigherThanPreset);
|
||||||
RUN_TEST(test_applyModemConfig_customCodingRateLowerThanPreset);
|
RUN_TEST(test_applyModemConfig_customCodingRateLowerThanPreset);
|
||||||
|
RUN_TEST(test_applyModemConfig_mediumTurbo);
|
||||||
|
RUN_TEST(test_clampConfigLora_mediumTurboInvalidForEU868);
|
||||||
|
RUN_TEST(test_clampConfigLora_mediumTurboValidForUS);
|
||||||
RUN_TEST(test_regionPresetMap_coversAllRegionsWithinBounds);
|
RUN_TEST(test_regionPresetMap_coversAllRegionsWithinBounds);
|
||||||
RUN_TEST(test_regionPresetMap_matchesRegionTable);
|
RUN_TEST(test_regionPresetMap_matchesRegionTable);
|
||||||
exit(UNITY_END());
|
exit(UNITY_END());
|
||||||
|
|||||||
Reference in New Issue
Block a user