From 9b63f75e1d4edfee845325544f2dec82dd84bf40 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 18 Sep 2021 10:43:55 +0200 Subject: [PATCH 1/3] Fix max # channels and default channel range Resolves #299 --- radio/src/gui/colorlcd/model_setup.cpp | 60 ++++++++++------ radio/src/pulses/modules_helpers.h | 94 +++++++++++++++----------- radio/src/pulses/pxx1.cpp | 9 ++- 3 files changed, 98 insertions(+), 65 deletions(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 64eb1e99b..6347755c5 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -736,17 +736,24 @@ class ModuleWindow : public FormGroup { void addChannelRange(FormGridLayout &grid) { - new StaticText(this, grid.getLabelSlot(true), STR_CHANNELRANGE, 0, COLOR_THEME_PRIMARY1); - auto channelStart = new NumberEdit(this, grid.getFieldSlot(2, 0), 1, - MAX_OUTPUT_CHANNELS - sentModuleChannels(moduleIdx) + 1, - GET_DEFAULT(1 + g_model.moduleData[moduleIdx].channelsStart)); - auto channelEnd = new NumberEdit(this, grid.getFieldSlot(2, 1), - g_model.moduleData[moduleIdx].channelsStart + minModuleChannels(moduleIdx), - min(MAX_OUTPUT_CHANNELS, g_model.moduleData[moduleIdx].channelsStart + maxModuleChannels(moduleIdx)), - GET_DEFAULT(g_model.moduleData[moduleIdx].channelsStart + 8 + g_model.moduleData[moduleIdx].channelsCount)); + new StaticText(this, grid.getLabelSlot(true), STR_CHANNELRANGE, 0, + COLOR_THEME_PRIMARY1); + auto channelStart = new NumberEdit( + this, grid.getFieldSlot(2, 0), 1, + MAX_OUTPUT_CHANNELS - sentModuleChannels(moduleIdx) + 1, + GET_DEFAULT(1 + g_model.moduleData[moduleIdx].channelsStart)); + auto channelEnd = new NumberEdit( + this, grid.getFieldSlot(2, 1), + g_model.moduleData[moduleIdx].channelsStart + + minModuleChannels(moduleIdx), + min(MAX_OUTPUT_CHANNELS, + g_model.moduleData[moduleIdx].channelsStart + + maxModuleChannels(moduleIdx)), + GET_DEFAULT(g_model.moduleData[moduleIdx].channelsStart + 8 + + g_model.moduleData[moduleIdx].channelsCount)); if (isModulePXX2(moduleIdx)) { channelEnd->setAvailableHandler([=](int value) { - return isPxx2IsrmChannelsCountAllowed(value - 8); + return isPxx2IsrmChannelsCountAllowed(value - 8); }); } channelStart->setPrefix(STR_CH); @@ -754,17 +761,24 @@ class ModuleWindow : public FormGroup { channelStart->setSetValueHandler([=](int32_t newValue) { g_model.moduleData[moduleIdx].channelsStart = newValue - 1; SET_DIRTY(); - channelEnd->setMin(g_model.moduleData[moduleIdx].channelsStart + minModuleChannels(moduleIdx)); - channelEnd->setMax(min(MAX_OUTPUT_CHANNELS, g_model.moduleData[moduleIdx].channelsStart + maxModuleChannels(moduleIdx))); + channelEnd->setMin(g_model.moduleData[moduleIdx].channelsStart + + minModuleChannels(moduleIdx)); + channelEnd->setMax(min( + MAX_OUTPUT_CHANNELS, g_model.moduleData[moduleIdx].channelsStart + + maxModuleChannels(moduleIdx))); channelEnd->invalidate(); }); channelEnd->setSetValueHandler([=](int32_t newValue) { - g_model.moduleData[moduleIdx].channelsCount = newValue - g_model.moduleData[moduleIdx].channelsStart - 8; + g_model.moduleData[moduleIdx].channelsCount = + newValue - g_model.moduleData[moduleIdx].channelsStart - 8; SET_DIRTY(); - channelStart->setMax(MAX_OUTPUT_CHANNELS - sentModuleChannels(moduleIdx) + 1); + channelStart->setMax(MAX_OUTPUT_CHANNELS - + sentModuleChannels(moduleIdx) + 1); }); - channelEnd->enable(minModuleChannels(moduleIdx) < maxModuleChannels(moduleIdx)); - if (channelEnd->getValue() > channelEnd->getMax()) channelEnd->setValue(channelEnd->getMax()); + channelEnd->enable(minModuleChannels(moduleIdx) < + maxModuleChannels(moduleIdx)); + if (channelEnd->getValue() > channelEnd->getMax()) + channelEnd->setValue(channelEnd->getMax()); } void update() @@ -778,11 +792,10 @@ class ModuleWindow : public FormGroup { MODULE_TYPE_NONE, MODULE_TYPE_COUNT - 1, GET_DEFAULT(g_model.moduleData[moduleIdx].type), [=](int32_t newValue) { - g_model.moduleData[moduleIdx].type = newValue; - SET_DIRTY(); - // TODO resetModuleSettings(moduleIdx); + setModuleType(moduleIdx, newValue); update(); moduleChoice->setFocus(SET_FOCUS_DEFAULT); + SET_DIRTY(); }); moduleChoice->setAvailableHandler([=](int8_t moduleType) { return moduleIdx == INTERNAL_MODULE ? isInternalModuleAvailable(moduleType) : isExternalModuleAvailable(moduleType); @@ -1088,10 +1101,13 @@ class ModuleWindow : public FormGroup { new StaticText(this, grid.getLabelSlot(true), STR_PPMFRAME, 0, COLOR_THEME_PRIMARY1); // PPM frame length - auto edit = new NumberEdit(this, grid.getFieldSlot(3, 0), 125, 35 * 5 + 225, - GET_DEFAULT(g_model.moduleData[moduleIdx].ppm.frameLength * 5 + 225), - SET_VALUE(g_model.moduleData[moduleIdx].ppm.frameLength, (newValue - 225) / 5), - 0, PREC1); + auto edit = new NumberEdit( + this, grid.getFieldSlot(3, 0), 125, 35 * 5 + 225, + GET_DEFAULT(g_model.moduleData[moduleIdx].ppm.frameLength * 5 + + 225), + SET_VALUE(g_model.moduleData[moduleIdx].ppm.frameLength, + (newValue - 225) / 5), + 0, PREC1); edit->setStep(5); edit->setSuffix(STR_MS); diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 2f23dccde..8d2bc10f5 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -337,10 +337,42 @@ inline bool isModuleAFHDS3(uint8_t idx) && (g_model.moduleData[idx].subType == FLYSKY_SUBTYPE_AFHDS3); } -// order is the same as in enum Protocols in myeeprom.h (none, ppm, pxx, pxx2, dsm, crossfire, multi, r9m, r9m2, sbus) -//qba667 count is not matching! -static const int8_t maxChannelsModules_M8[] = { 0, 8, 8, 16, -2, 8, 4, 8, 16, 8, 10 }; // relative to 8! -static const int8_t maxChannelsXJT_M8[] = { 0, 8, 0, 4 }; // relative to 8! +// See enum ModuleType in modules_constant.h +// relative to 8! +static const int8_t maxChannelsModules_M8[] = { + 0, // MODULE_TYPE_NONE + 8, // MODULE_TYPE_PPM + 0, // MODULE_TYPE_XJT_PXX1: index NOT USED + 16,// MODULE_TYPE_ISRM_PXX2 + -2,// MODULE_TYPE_DSM2 + 8, // MODULE_TYPE_CROSSFIRE + 8, // MODULE_TYPE_MULTIMODULE + 0, // MODULE_TYPE_R9M_PXX1: index NOT USED + 0, // MODULE_TYPE_R9M_PXX2: index NOT USED + 0, // MODULE_TYPE_R9M_LITE_PXX1: index NOT USED + 0, // MODULE_TYPE_R9M_LITE_PXX2: index NOT USED + 4, // MODULE_TYPE_GHOST + 0, // MODULE_TYPE_R9M_LITE_PRO_PXX2: index NOT USED + 8, // MODULE_TYPE_SBUS + 0, // MODULE_TYPE_XJT_LITE_PXX2: index NOT USED + 6, // MODULE_TYPE_FLYSKY: 14 channels for AFHDS2A, AFHDS3 special cased +}; + +static_assert(MODULE_TYPE_COUNT == sizeof(maxChannelsModules_M8), + "MODULE_TYPE_COUNT != sizeof(maxChannelsModules_M8)"); + +// See enum ModuleSubtypePXX1 in modules_constant.h +// relative to 8! +static const int8_t maxChannelsXJT_M8[] = { + 0, // MODULE_SUBTYPE_PXX1_OFF + 8, // MODULE_SUBTYPE_PXX1_ACCST_D16 + 0, // MODULE_SUBTYPE_PXX1_ACCST_D8 + 4 // MODULE_SUBTYPE_PXX1_ACCST_LR12 +}; + +// MODULE_SUBTYPE_PXX1_OFF == -1 +static_assert(MODULE_SUBTYPE_PXX1_LAST + 2 == sizeof(maxChannelsXJT_M8), + "MODULE_SUBTYPE_PXX1_LAST + 2 != sizeof(maxChannelsXJT_M8)"); constexpr int8_t MAX_TRAINER_CHANNELS_M8 = MAX_TRAINER_CHANNELS - 8; constexpr int8_t MAX_EXTRA_MODULE_CHANNELS_M8 = 8; // only 16ch PPM @@ -349,35 +381,27 @@ inline int8_t maxModuleChannels_M8(uint8_t moduleIdx) { if (isExtraModule(moduleIdx)) { return MAX_EXTRA_MODULE_CHANNELS_M8; - } - else if (isModuleXJT(moduleIdx)) { + } else if (isModuleXJT(moduleIdx)) { return maxChannelsXJT_M8[1 + g_model.moduleData[moduleIdx].subType]; - } - else if (isModuleR9M(moduleIdx)) { + } else if (isModuleR9M(moduleIdx)) { if (isModuleR9M_LBT(moduleIdx)) { if (isModuleR9MLite(moduleIdx)) - return g_model.moduleData[moduleIdx].pxx.power == R9M_LITE_LBT_POWER_25_8CH ? 0 : 8; + return g_model.moduleData[moduleIdx].pxx.power == + R9M_LITE_LBT_POWER_25_8CH + ? 0 + : 8; else - return g_model.moduleData[moduleIdx].pxx.power == R9M_LBT_POWER_25_8CH ? 0 : 8; + return g_model.moduleData[moduleIdx].pxx.power == R9M_LBT_POWER_25_8CH + ? 0 + : 8; + } else { + return 8; // always 16 channels in FCC / FLEX } - else { - return 8; // always 16 channels in FCC / FLEX - } - } - else if (isModuleAFHDS3(moduleIdx)) { + } else if (isModuleAFHDS3(moduleIdx)) { return 10; - } - else if (isModuleDSM2(moduleIdx)) { - return -2; // 6 channels - } - else if (isModuleMultimoduleDSM2(moduleIdx)) { - return 4; // 12 channels - } - //TODO: This should be based on the selected protocol - else if(isModuleMultimodule(moduleIdx)) { - return 8; // 16 channels - } - else { + } else if (isModuleMultimoduleDSM2(moduleIdx)) { + return 4; // 12 channels + } else { return maxChannelsModules_M8[g_model.moduleData[moduleIdx].type]; } } @@ -399,18 +423,6 @@ inline int8_t defaultModuleChannels_M8(uint8_t idx) { if (isModulePPM(idx)) return 0; // 8 channels - else if (isModuleDSM2(idx)) - return 0; // 8 channels - else if (isModuleMultimoduleDSM2(idx)) - return -1; // 7 channels - else if (isModuleXJTD8(idx)) - return 0; // 8 channels - else if (isModuleXJTLR12(idx)) - return 4; // 12 channels - else if (isModulePXX2(idx)) - return 8; // 16 channels - else if (isModuleGhost(idx)) - return 4; // 12 channels else return maxModuleChannels_M8(idx); } @@ -637,7 +649,9 @@ inline void removePXX2ReceiverIfEmpty(uint8_t moduleIdx, uint8_t receiverIdx) inline void setDefaultPpmFrameLength(uint8_t moduleIdx) { - g_model.moduleData[moduleIdx].ppm.frameLength = 4 * max(0, g_model.moduleData[moduleIdx].channelsCount); + // channelsCount + 8 ??? + g_model.moduleData[moduleIdx].ppm.frameLength = + 4 * max(0, g_model.moduleData[moduleIdx].channelsCount); } inline void resetAccessAuthenticationCount() diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp index ba05d026e..5ef8c395b 100644 --- a/radio/src/pulses/pxx1.cpp +++ b/radio/src/pulses/pxx1.cpp @@ -194,12 +194,15 @@ void Pxx1Pulses::setupFrame(uint8_t module) #endif if (moduleState[module].counter & 0x01) { + // channelsCount is shifted by 8 sendUpperChannels = g_model.moduleData[module].channelsCount; + // if real channels count > 8 if (sendUpperChannels && moduleState[module].counter == 1) { - sendFailsafe = (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER); + sendFailsafe = + (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && + g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER); } - } - else { + } else { if (moduleState[module].counter == 0) { sendFailsafe = (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER); } From b5da0e164ce580a119b6285cd86ff2b12aa8d13f Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 18 Sep 2021 12:52:03 +0200 Subject: [PATCH 2/3] Add GHST and SBUS to the list of protos with fixed # channels The end-channel is thus non-editable. --- radio/src/pulses/modules_helpers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 8d2bc10f5..4ad0fb3bf 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -414,6 +414,10 @@ inline int8_t maxModuleChannels(uint8_t moduleIdx) inline int8_t minModuleChannels(uint8_t idx) { if (isModuleCrossfire(idx)) + return CROSSFIRE_CHANNELS_COUNT; + else if (isModuleGhost(idx)) + return GHOST_CHANNELS_COUNT; + else if (isModuleSBUS(idx)) return 16; else return 1; From ccc83b9d2eb940e01eea676197141d8d5e5f4513 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 18 Sep 2021 13:03:51 +0200 Subject: [PATCH 3/3] Set the record straight on GHST channels --- radio/src/pulses/modules_helpers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 4ad0fb3bf..f9d91a5df 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -33,7 +33,7 @@ #endif #define CROSSFIRE_CHANNELS_COUNT 16 -#define GHOST_CHANNELS_COUNT 12 +#define GHOST_CHANNELS_COUNT 16 #if defined(MULTIMODULE) // When using packed, the pointer in here end up not being aligned, which clang and gcc complain about @@ -345,13 +345,13 @@ static const int8_t maxChannelsModules_M8[] = { 0, // MODULE_TYPE_XJT_PXX1: index NOT USED 16,// MODULE_TYPE_ISRM_PXX2 -2,// MODULE_TYPE_DSM2 - 8, // MODULE_TYPE_CROSSFIRE + CROSSFIRE_CHANNELS_COUNT - 8, // MODULE_TYPE_CROSSFIRE 8, // MODULE_TYPE_MULTIMODULE 0, // MODULE_TYPE_R9M_PXX1: index NOT USED 0, // MODULE_TYPE_R9M_PXX2: index NOT USED 0, // MODULE_TYPE_R9M_LITE_PXX1: index NOT USED 0, // MODULE_TYPE_R9M_LITE_PXX2: index NOT USED - 4, // MODULE_TYPE_GHOST + GHOST_CHANNELS_COUNT - 8, // MODULE_TYPE_GHOST 0, // MODULE_TYPE_R9M_LITE_PRO_PXX2: index NOT USED 8, // MODULE_TYPE_SBUS 0, // MODULE_TYPE_XJT_LITE_PXX2: index NOT USED