From 32da77ce02db1f672e9e7fdde2720aa25c965923 Mon Sep 17 00:00:00 2001 From: Kevin Koenig Date: Tue, 31 Aug 2021 19:47:32 -0400 Subject: [PATCH] Fix MPM Protocol Sorting (#580) * Fixed Protocol Sorting in model_setup.cpp * update submodule for libopenui * Fix potential compilation issue * Fixed Protocol Sorting in model_setup.cpp * fix merge issue * Submodule libopenui back to edgetx master branch * Reset to libopenui 5c70891 As this was the submodule at the time this branch was started. This should remove it as a change in the PR. * fixed an off by one error in the initialization of the sorted list. When you selected the last protocol in the list it crashed. * Reset to libopenui 5c70891 As this was the submodule at the time this branch was started. Co-authored-by: kkoenig1@optonline.com Co-authored-by: Peter Feerick --- radio/src/gui/colorlcd/model_setup.cpp | 98 +++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 9fbdb3ef7..f601fb88b 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -22,9 +22,91 @@ #include "opentx.h" #include "libopenui.h" #include "storage/modelslist.h" +#include "algorithm" #define SET_DIRTY() storageDirty(EE_MODEL) +class RFProtocols +{ +private: + const char * protocols; + int maxProtocols; + std::vector labels; + uint8_t getProtoStringLength(); + +public: + RFProtocols(const char * rfProtocols, int max); + int findProtocolIndex(int rfProtcolIndex); + int lookupProtocolIndex(int selectedIndex); + std::vector &getLabels(); +}; + +uint8_t RFProtocols::getProtoStringLength() +{ + return protocols[0]; +} + +RFProtocols::RFProtocols(const char *protocols, int max) +{ + this->protocols = protocols; + maxProtocols = max; + + uint8_t len = protocols[0]; + const char * value = &protocols[1]; + + for (int i = 0; i <= max; i++) + { + std::string label = std::string(value, min(len, strlen(value))); + labels.emplace_back(label); + + value += len; + } + std::sort(labels.begin(), labels.end()); +} + +std::vector &RFProtocols::getLabels() +{ + return labels; +} + +int RFProtocols::lookupProtocolIndex(int selectedIndex) +{ + uint8_t len = getProtoStringLength(); + const char *p = &protocols[1]; + + const char *protocolLabel = labels.at(selectedIndex).c_str(); + + int protocolIndex = 0; + for (; protocolIndex < maxProtocols; protocolIndex++) + { + if (strncmp(p, protocolLabel, min((int)strlen(protocolLabel), (int)len)) == 0) + break; + + p += len; + } + assert(protocolIndex < maxProtocols); + + return protocolIndex; +} + +int RFProtocols::findProtocolIndex(int rfProtocolIndex) +{ + uint8_t len = getProtoStringLength(); + const char *protocolLabel = &protocols[1] + len * rfProtocolIndex; + + auto result = std::find_if(labels.begin(), labels.end(), [protocolLabel, len](std::string &a) { + auto theSame = strncmp(a.c_str(), protocolLabel, max((int)a.length(), (int)len)) == 0; + return theSame; + }); + assert(result != labels.end()); + return result - labels.begin(); +} + +// global pointer intialized once on the first call to update() +RFProtocols *rfProtocols = nullptr; + + + std::string switchWarninglabel(swsrc_t index) { static const char switchPositions[] = { @@ -641,15 +723,27 @@ class ModuleWindow : public FormGroup { // Multi type (CUSTOM, brand A, brand B,...) int multiRfProto = g_model.moduleData[moduleIdx].getMultiProtocol(); - + + // initialize rfProtocols if it is not initialized already. This is a hack + // because i dont know how to construct it at the exact right time after the module + // is loaded + if (rfProtocols == nullptr) + rfProtocols = new RFProtocols(STR_MULTI_PROTOCOLS, MODULE_SUBTYPE_MULTI_LAST); + + multiRfProto = rfProtocols->findProtocolIndex(multiRfProto); + // Grid count for narrow/wide screen int count = LCD_W < LCD_H ? 1 : (g_model.moduleData[moduleIdx].multi.customProto ? 3 : 2); + rfChoice = new Choice( this, grid.getFieldSlot(count, 0), - STR_MULTI_PROTOCOLS, MODULE_SUBTYPE_MULTI_FIRST, + rfProtocols->getLabels(), MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST, GET_DEFAULT(multiRfProto), [=](int32_t newValue) { + + newValue = rfProtocols->lookupProtocolIndex(newValue); + g_model.moduleData[moduleIdx].setMultiProtocol(newValue); g_model.moduleData[moduleIdx].subType = 0; if (mmSubProtocol != nullptr) mmSubProtocol->invalidate(); // always null ???