From c271ad92ae201e147b1538cf9ebab0adc4c30288 Mon Sep 17 00:00:00 2001 From: Frankie Arzu <32604366+frankiearzu@users.noreply.github.com> Date: Tue, 16 Jun 2026 23:25:04 -0500 Subject: [PATCH 1/2] DSMP V2 Enhacements 1. 16 channels (X-Plus channels) 2. Show Firmware date instead of just version 3. Automatically choose "Enable AETR". --- radio/src/gui/gui_common.cpp | 11 +++-- radio/src/pulses/dsmp.cpp | 71 ++++++++++++++++++++-------- radio/src/pulses/dsmp.h | 4 ++ radio/src/pulses/modules_helpers.cpp | 13 ++++- radio/src/pulses/modules_helpers.h | 4 +- 5 files changed, 77 insertions(+), 26 deletions(-) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index b71f9c3bbe3..00be1bba3e7 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -973,12 +973,13 @@ bool isExternalModuleAvailable(int moduleType) return false; #endif -#if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_STD) +#if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_STD) // Ignore Standard Size modules if (moduleType == MODULE_TYPE_R9M_PXX1 || moduleType == MODULE_TYPE_R9M_PXX2 || moduleType == MODULE_TYPE_XJT_PXX1 || - moduleType == MODULE_TYPE_DSM2 || - moduleType == MODULE_TYPE_LEMON_DSMP ) + moduleType == MODULE_TYPE_DSM2 // || + //moduleType == MODULE_TYPE_LEMON_DSMP /* Lemon DSMP now has small/lite size too */ + ) return false; #endif @@ -1015,6 +1016,10 @@ bool isExternalModuleAvailable(int moduleType) return false; #endif +#if !defined(DSMP) + if (moduleType == MODULE_TYPE_DSMP) return false; +#endif + #if !defined(SBUS) if (moduleType == MODULE_TYPE_SBUS) return false; diff --git a/radio/src/pulses/dsmp.cpp b/radio/src/pulses/dsmp.cpp index ff179fcb6f9..cc9c7654cc8 100644 --- a/radio/src/pulses/dsmp.cpp +++ b/radio/src/pulses/dsmp.cpp @@ -26,7 +26,7 @@ #include "edgetx.h" #include "telemetry/spektrum.h" -#define DSMP_SEND_X_PLUS 0 +#define DSMP_SEND_X_PLUS 1 #define DSMP_BITRATE 115200 @@ -63,6 +63,8 @@ static uint8_t AETR_TAER_MAP[] = {2, 0, 1}; static DSMPModuleStatus dsmpStatus = DSMPModuleStatus(); + + // Power cycle of the DSMP module // The DSMP module code has the channel data initialized to 0 and initial number of bits as 10b (ch resolution 1024) // The Setup message pass the last BIND configuration to the Module via the setup package (for example, 2048 it was bound to DSMX). @@ -356,11 +358,19 @@ static void processDSMPBindPacket(uint8_t module, uint8_t* packet) static void processDSMPManufacturerData(uint8_t module, uint8_t* packet) { - // Format M,M,M,M, V, V where M is 4 byte manufacturer data, and V is 2 byte + // Format M,M,M,M, V, V, yy,yy, mm, dd, rel + // where M is 4 byte manufacturer data, and V is 2 byte + dsmpStatus.version[0] = packet[4]; // Major dsmpStatus.version[1] = packet[5]; // Minor + dsmpStatus.fm_year = (packet[6] << 8) | packet[7]; // FM Year + dsmpStatus.fm_mm = packet[8]; // FM Month + dsmpStatus.fm_dd = packet[9]; // FM Day + dsmpStatus.fm_rev = packet[10]; // FM Rev TRACE("LemonDSMP: Ver [%d.%d]", dsmpStatus.version[0], dsmpStatus.version[1]); + TRACE("LemonDSMP: FW [%d-%d-%d.%d]", + dsmpStatus.fm_year, dsmpStatus.fm_mm, dsmpStatus.fm_dd, dsmpStatus.fm_rev); if (dsmpStatus.version[0] > 1 && mixerSchedulerGetPeriod(module) != SCHEDULER_PERIOD_V2) { // V2 suppors 11ms @@ -448,8 +458,9 @@ static void dsmpProcessData(void* ctx, uint8_t data, uint8_t* buffer, } if (rxBufferCount < TELEMETRY_RX_PACKET_SIZE) { - + #if 0 TRACE("[DSMP] Data 0x%02X, len = %d", data, rxBufferCount); + #endif buffer[rxBufferCount++] = data; // Keep building message } else { TRACE("[DSMP] array size %d error", rxBufferCount); @@ -465,23 +476,48 @@ static void dsmpProcessData(void* ctx, uint8_t data, uint8_t* buffer, void DSMPModuleStatus::getStatusString(char* statusText) const { - if (!isValid()) { - strcpy(statusText, STR_MODULE_NO_TELEMETRY); - return; - } + if (!isValid()) { + strcpy(statusText, STR_MODULE_NO_TELEMETRY); + return; + } - const auto& md = g_model.moduleData[EXTERNAL_MODULE]; - auto channels = md.getChannelsCount(); + const auto& md = g_model.moduleData[EXTERNAL_MODULE]; + auto channels = md.getChannelsCount(); + + char* tmp = statusText; - char* tmp = statusText; + *tmp = 0; - // Version - *tmp = 0; - tmp = strAppend(tmp, "v", 1); + const char* mode; + + // Protocol Used + mode = (flags & DSMP_FLAGS_DSMX) ? "X" : "2"; // DSMX or DSM2 + tmp = strAppend(tmp, mode, strlen(mode)); + mode = + (flags & DSMP_FLAGS_11mS) ? "_2F" : "_1F"; // 1 or 2 Frames (11ms/22ms) + tmp = strAppend(tmp, mode, strlen(mode)); + + // Version + tmp = strAppend(tmp, " v", 2); + if (dsmpStatus.fm_year > 0) { + // Firmware Build Date (Compact, ex:251012.1) + tmp = strAppendUnsigned(tmp, dsmpStatus.fm_year % 100); + tmp = strAppendUnsigned(tmp, dsmpStatus.fm_mm / 10); + tmp = strAppendUnsigned(tmp, dsmpStatus.fm_mm % 10); + tmp = strAppendUnsigned(tmp, dsmpStatus.fm_dd / 10); + tmp = strAppendUnsigned(tmp, dsmpStatus.fm_dd % 10); + tmp = strAppend(tmp, ".", 1); + tmp = strAppendUnsigned(tmp, dsmpStatus.fm_rev); + } else { + // Simple version format tmp = strAppendUnsigned(tmp, dsmpStatus.version[0]); tmp = strAppend(tmp, ".", 1); tmp = strAppendUnsigned(tmp, dsmpStatus.version[1]); + } +#if 0 + // Already displayin the TAER checkbox, so probably not needed + // Channel Order char b[] = "? "; if (ch_order != 0xFF) { // Same encoding as MultiModule uint8_t temp = ch_order; @@ -496,14 +532,7 @@ void DSMPModuleStatus::getStatusString(char* statusText) const tmp = strAppend(tmp, " ", 1); tmp = strAppend(tmp, b, strlen(b)); - - const char* mode; - - mode = (flags & DSMP_FLAGS_DSMX) ? " X" : " 2"; // DSMX or DSM2 - tmp = strAppend(tmp, mode, strlen(mode)); - - mode = (flags & DSMP_FLAGS_11mS) ? "_2F" : "_1F"; // 1 or 2 Frames (11ms/22ms) - tmp = strAppend(tmp, mode, strlen(mode)); +#endif #if 0 // Good for Debugging, but not much for regular users diff --git a/radio/src/pulses/dsmp.h b/radio/src/pulses/dsmp.h index 608d6424214..31b059decd2 100644 --- a/radio/src/pulses/dsmp.h +++ b/radio/src/pulses/dsmp.h @@ -28,6 +28,10 @@ struct DSMPModuleStatus { tmr10ms_t lastUpdate; uint8_t ch_order = 0xFF; uint8_t flags = 0; + uint16_t fm_year = 0; + uint8_t fm_mm = 0; + uint8_t fm_dd = 0; + uint8_t fm_rev = 0; inline bool isValid() const { return (bool)(get_tmr10ms() - lastUpdate < 500);} void getStatusString(char *statusText) const; diff --git a/radio/src/pulses/modules_helpers.cpp b/radio/src/pulses/modules_helpers.cpp index d1fe9dfe3dc..83f6ff7a6d6 100644 --- a/radio/src/pulses/modules_helpers.cpp +++ b/radio/src/pulses/modules_helpers.cpp @@ -68,7 +68,7 @@ int8_t maxModuleChannels_M8(uint8_t moduleIdx) } else if (isModuleMultimoduleDSM2(moduleIdx)) { return 4; // 12 channels } else if (isModuleDSMP(moduleIdx)) { - return 4; // 12 channels + return 8; // 16 channels supported for V2 } else { return maxChannelsModules_M8[g_model.moduleData[moduleIdx].type]; } @@ -130,6 +130,17 @@ void setModuleType(uint8_t moduleIdx, uint8_t moduleType) resetAfhds3Options(moduleIdx); } else if (moduleData.type == MODULE_TYPE_LEMON_DSMP) { + // When changing the Module Type to DSMP. + // Check Radio Config to see if it is AETR + auto ch1 = inputMappingChannelOrder(0); + auto ch3 = inputMappingChannelOrder(2); + bool isAETR = (ch1 == 3) && (ch3 == inputMappingGetThrottle()); +#if defined(DEBUG) + char *chFun = "RETA"; + TRACE("DSMP Setup: Ch1=%c, ch3=%c, isAETR=%d",chFun[ch1], chFun[ch3], isAETR); +#endif + + moduleData.dsmp.enableAETR = isAETR; restartModule(moduleIdx); // Restart DSMP when switching to it (example PPM->DSMP) } else diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 840b177e1e5..5b71bbd4498 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -495,7 +495,9 @@ inline int8_t minModuleChannels(uint8_t idx) inline int8_t defaultModuleChannels_M8(uint8_t idx) { if (isModulePPM(idx)) - return 0; // 8 channels + return 0; // 8 channels + else if (isModuleDSMP(idx)) + return 4; // 12 channels else return maxModuleChannels_M8(idx); } From 6960e3aea06bc3ff5fe51ee052e80d014e7ea2c2 Mon Sep 17 00:00:00 2001 From: Frankie Arzu <32604366+frankiearzu@users.noreply.github.com> Date: Tue, 23 Jun 2026 08:20:41 -0500 Subject: [PATCH 2/2] Remove automatic detection of flag "Enable AETR". Default OFF, let the user choose. --- radio/src/pulses/modules_helpers.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/radio/src/pulses/modules_helpers.cpp b/radio/src/pulses/modules_helpers.cpp index 83f6ff7a6d6..f05c57b586f 100644 --- a/radio/src/pulses/modules_helpers.cpp +++ b/radio/src/pulses/modules_helpers.cpp @@ -130,17 +130,6 @@ void setModuleType(uint8_t moduleIdx, uint8_t moduleType) resetAfhds3Options(moduleIdx); } else if (moduleData.type == MODULE_TYPE_LEMON_DSMP) { - // When changing the Module Type to DSMP. - // Check Radio Config to see if it is AETR - auto ch1 = inputMappingChannelOrder(0); - auto ch3 = inputMappingChannelOrder(2); - bool isAETR = (ch1 == 3) && (ch3 == inputMappingGetThrottle()); -#if defined(DEBUG) - char *chFun = "RETA"; - TRACE("DSMP Setup: Ch1=%c, ch3=%c, isAETR=%d",chFun[ch1], chFun[ch3], isAETR); -#endif - - moduleData.dsmp.enableAETR = isAETR; restartModule(moduleIdx); // Restart DSMP when switching to it (example PPM->DSMP) } else