Skip to content

Commit

Permalink
feat: Support for MPM DSM clone mode (#3974)
Browse files Browse the repository at this point in the history
  • Loading branch information
3djc authored Oct 10, 2023
1 parent 2295148 commit f4f04c1
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 82 deletions.
1 change: 1 addition & 0 deletions radio/src/MultiProtoDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ enum ModuleSubtypeMulti {
//
#define BAYANG_OPTION_TELEMETRY_NAMES "Off","On","Off+Aux","On+Aux"
#define DSM2_OPTION_SERVOFREQ_NAMES "22ms","11ms"
#define DSM_CLONE_NAMES "Normal","Cloned"

//
// Common list of protocols the MPM doesn't allow to be selected (not sent by MPM protocol scan)
Expand Down
17 changes: 14 additions & 3 deletions radio/src/gui/128x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ void editTimerCountdown(int timerIdx, coord_t y, LcdFlags attr, event_t event)
MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND */ \
EXTERNAL_ANTENNA_ROW /* ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA */ \
MODULE_POWER_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER */ \
IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE */ \
IF_INTERNAL_MODULE_ON(FAILSAFE_ROW(INTERNAL_MODULE)), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE */ \
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE */ \
IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS */ \
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1 */ \
Expand Down Expand Up @@ -515,7 +515,7 @@ void editTimerCountdown(int timerIdx, coord_t y, LcdFlags attr, event_t event)
MODULE_POWER_ROW(EXTERNAL_MODULE), \
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), \
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) \
FAILSAFE_ROWS(EXTERNAL_MODULE), /* ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE */ \
FAILSAFE_ROW(EXTERNAL_MODULE), /* ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE */ \
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), /* Range check and Register buttons */ \
IF_PXX2_MODULE(EXTERNAL_MODULE, 0), /* Module options */ \
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), /* Receiver 1 */ \
Expand Down Expand Up @@ -1397,7 +1397,11 @@ void menuModelSetup(event_t event)
#endif
{
lcdDrawTextAlignedLeft(y, STR_SUBTYPE);
lcdDrawMultiSubProtocolString(MODEL_SETUP_2ND_COLUMN, y, moduleIdx, g_model.moduleData[moduleIdx].subType, attr);
lcdDrawMultiSubProtocolString(MODEL_SETUP_2ND_COLUMN, y, moduleIdx, g_model.moduleData[moduleIdx].subType, menuHorizontalPosition == 0 ? attr : 0);
int8_t optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0x04) >> 2;
if (isMultiProtocolDSMCloneAvailable(moduleIdx)) {
lcdDrawTextAtIndex(LCD_W, y, STR_MULTI_DSM_CLONE, optionValue, RIGHT | (menuHorizontalPosition == 1 ? attr : 0));
}
if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:{
Expand All @@ -1407,6 +1411,13 @@ void menuModelSetup(event_t event)
}
break;
}
case 1:{
CHECK_INCDEC_MODELVAR(event, optionValue, 0, 1);
if (checkIncDec_Ret) {
g_model.moduleData[moduleIdx].multi.optionValue = (g_model.moduleData[moduleIdx].multi.optionValue & 0xFB) + (optionValue << 2);
}
break;
}
}
}
}
Expand Down
152 changes: 80 additions & 72 deletions radio/src/gui/212x64/model_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ enum MenuModelSetupItems {
#endif
#if defined (MULTIMODULE)
ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_DSM_CLONED,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS,
ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS,
#endif
Expand Down Expand Up @@ -509,72 +510,73 @@ void menuModelSetup(event_t event)
MENU_TAB({
HEADER_LINE_COLUMNS

0, // Model name
0, // Model image
0, // ITEM_MODEL_SETUP_NAME
0, // ITEM_MODEL_SETUP_BITMAP

TIMERS_ROWS,

TOPLCD_ROWS

0, // Extended limits
1, // Extended trims
0, // Show trims
0, // Trims step

0, // Throttle section
THROTTLE_ROW(0), // Throttle reverse
THROTTLE_ROW(0), // Throttle trace source
THROTTLE_ROW(0), // Throttle trim
THROTTLE_ROW(0), // Throttle trim switch

0, // Preflight section
PREFLIGHT_ROW(0), // Checklist
PREFLIGHT_ROW(0), // Checklist interactive
PREFLIGHT_ROW(0), // Throttle warning
PREFLIGHT_ROW(0), // Custom position for throttle warning enable
PREFLIGHT_ROW(0), // Custom position for throttle warning value
SW_WARN_ROWS, // Switch warning
POT_WARN_ROWS, // Pot warning

uint8_t(NAVIGATION_LINE_BY_LINE | (adcGetInputOffset(ADC_INPUT_POT + 1) - 1)), // Center beeps

0, // ADC Jitter filter

REGISTRATION_ID_ROWS

LABEL(InternalModule),
INTERNAL_MODULE_TYPE_ROWS,
MODULE_CHANNELS_ROWS(INTERNAL_MODULE),
IF_ALLOW_RACING_MODE(INTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), // RxNum, [Bind] and [Range] buttons
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // RxNum for ACCESS
IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), // Failsafe
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), // [Range] and [Register] buttons
IF_PXX2_MODULE(INTERNAL_MODULE, 0), // Module options
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // Receiver 1
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // Receiver 2
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // Receiver 3

LABEL(ExternalModule),
EXTERNAL_MODULE_TYPE_ROW(),
IF_MODULE_BAUDRATE_ADJUST(EXTERNAL_MODULE, 0), // Baudrate
IF_MODULE_SYNCED(EXTERNAL_MODULE, 0), // Sync rate + errors
MULTIMODULE_TYPE_ROW(EXTERNAL_MODULE)
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE)
AFHDS3_MODE_ROWS(EXTERNAL_MODULE)
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE),
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum for ACCESS
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)),
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE)
AFHDS3_MODULE_ROWS(EXTERNAL_MODULE)
MODULE_POWER_ROW(EXTERNAL_MODULE),
FAILSAFE_ROWS(EXTERNAL_MODULE),
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons
IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 1
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 2
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 3
0, // ITEM_MODEL_SETUP_EXTENDED_LIMITS
1, // ITEM_MODEL_SETUP_EXTENDED_TRIMS
0, // ITEM_MODEL_SETUP_DISPLAY_TRIMS
0, // ITEM_MODEL_SETUP_TRIM_INC

0, // ITEM_MODEL_SETUP_THROTTLE_LABEL
THROTTLE_ROW(0), // ITEM_MODEL_SETUP_THROTTLE_REVERSED
THROTTLE_ROW(0), // ITEM_MODEL_SETUP_THROTTLE_TRACE
THROTTLE_ROW(0), // ITEM_MODEL_SETUP_THROTTLE_TRIM
THROTTLE_ROW(0), // ITEM_MODEL_SETUP_THROTTLE_TRIM_SWITCH

0, // ITEM_MODEL_SETUP_PREFLIGHT_LABEL
PREFLIGHT_ROW(0), // ITEM_MODEL_SETUP_CHECKLIST_DISPLAY
PREFLIGHT_ROW(0), // ITEM_MODEL_SETUP_CHECKLIST_INTERACTIVE
PREFLIGHT_ROW(0), // ITEM_MODEL_SETUP_THROTTLE_WARNING
PREFLIGHT_ROW(0), // ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING
PREFLIGHT_ROW(0), // ITEM_MODEL_SETUP_CUSTOM_THROTTLE_WARNING_VALUE
SW_WARN_ROWS, // ITEM_MODEL_SETUP_SWITCHES_WARNING1
POT_WARN_ROWS, // ITEM_MODEL_SETUP_POTS_WARNING

uint8_t(NAVIGATION_LINE_BY_LINE | (adcGetInputOffset(ADC_INPUT_POT + 1) - 1)), // ITEM_MODEL_SETUP_BEEP_CENTER

0, // ITEM_MODEL_SETUP_USE_JITTER_FILTER

REGISTRATION_ID_ROWS // ITEM_MODEL_SETUP_REGISTRATION_ID

LABEL(InternalModule), // ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL
INTERNAL_MODULE_TYPE_ROWS, // ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE
MODULE_CHANNELS_ROWS(INTERNAL_MODULE), // ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS
IF_ALLOW_RACING_MODE(INTERNAL_MODULE), // ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE
IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), // ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM
IF_INTERNAL_MODULE_ON(FAILSAFE_ROW(INTERNAL_MODULE)), // ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), // ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE
IF_PXX2_MODULE(INTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2
IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_3

LABEL(ExternalModule), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL - 37
EXTERNAL_MODULE_TYPE_ROW(), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE
IF_MODULE_BAUDRATE_ADJUST(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_BAUDRATE
IF_MODULE_SYNCED(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_SERIALSTATUS
MULTIMODULE_TYPE_ROW(EXTERNAL_MODULE) // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL
MULTIMODULE_DSM_CLONED_RAW(EXTERNAL_MODULE), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_DSM_CLONED
MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) // ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS + ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS
AFHDS3_MODE_ROWS(EXTERNAL_MODULE) // ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_MODE + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_STATUS + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_POWER_STATUS
MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS
IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM
IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS
MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) // ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND + (ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM) + ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING
AFHDS3_MODULE_ROWS(EXTERNAL_MODULE) // ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_RX_FREQ + ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS3_ACTUAL_POWER
MODULE_POWER_ROW(EXTERNAL_MODULE), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER
FAILSAFE_ROW(EXTERNAL_MODULE), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_REGISTER_RANGE
IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_OPTIONS
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_1
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_2
IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_3

TRAINER_ROWS,

Expand Down Expand Up @@ -1203,17 +1205,6 @@ void menuModelSetup(event_t event)
pulsesModuleSettingsUpdate(EXTERNAL_MODULE);
}
break;

#if defined(MULTIMODULE)
case 2:
CHECK_INCDEC_MODELVAR(
event, g_model.moduleData[EXTERNAL_MODULE].subType, 0,
getMaxMultiSubtype(EXTERNAL_MODULE));
if (checkIncDec_Ret) {
resetMultiProtocolsOptions(EXTERNAL_MODULE);
}
break;
#endif
}
}
#if POPUP_LEVEL > 1
Expand Down Expand Up @@ -1243,6 +1234,23 @@ void menuModelSetup(event_t event)
}
break;

#if defined(MULTIMODULE)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DSM_CLONED: {
int8_t optionValue =
(g_model.moduleData[EXTERNAL_MODULE].multi.optionValue & 0x04) >> 2;
lcdDrawText(INDENT_WIDTH / 2, y, STR_SUBTYPE);
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_DSM_CLONE, optionValue, attr | LEFT);

if (attr && s_editMode > 0) {
CHECK_INCDEC_MODELVAR(event, optionValue, 0, 1);
if (checkIncDec_Ret) {
g_model.moduleData[EXTERNAL_MODULE].multi.optionValue = (g_model.moduleData[EXTERNAL_MODULE].multi.optionValue & 0xFB) + (optionValue << 2);
}
}
break;
}
#endif

#if defined(CROSSFIRE) || defined(GHOST)
case ITEM_MODEL_SETUP_EXTERNAL_MODULE_BAUDRATE: {
ModuleData &moduleData = g_model.moduleData[EXTERNAL_MODULE];
Expand Down
30 changes: 30 additions & 0 deletions radio/src/gui/colorlcd/mpm_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,28 @@ void MPMSubtype::update(const MultiRfProtocols::RfProto* rfProto, uint8_t module
lv_event_send(choice->getLvObj(), LV_EVENT_VALUE_CHANGED, &stop);
}

struct MPMDSMCloned : public FormWindow::Line {
MPMDSMCloned(FormWindow* form, FlexGridLayout* layout, uint8_t moduleIdx);
void update() const { lv_event_send(choice->getLvObj(), LV_EVENT_VALUE_CHANGED, nullptr); }

private:
Choice* choice;
};

MPMDSMCloned::MPMDSMCloned(FormWindow* form, FlexGridLayout *layout, uint8_t moduleIdx) :
FormWindow::Line(form, layout)
{
if (layout) layout->resetPos();
new StaticText(this, rect_t{}, STR_SUBTYPE, 0, COLOR_THEME_PRIMARY1);

auto md = &g_model.moduleData[moduleIdx];
choice = new Choice(this, rect_t{}, STR_MULTI_DSM_CLONE, 0, 1, 0, 0);

choice->setGetValueHandler(GET_DEFAULT((md->multi.optionValue & 0x04) >> 2));
choice->setSetValueHandler(SET_VALUE(
md->multi.optionValue, (md->multi.optionValue & 0xFB) + (newValue << 2)));
}

struct MPMServoRate : public FormWindow::Line {
MPMServoRate(FormWindow* form, FlexGridLayout* layout, uint8_t moduleIdx);
void update() const { lv_event_send(choice->getLvObj(), LV_EVENT_VALUE_CHANGED, nullptr); }
Expand Down Expand Up @@ -329,6 +351,7 @@ MultimoduleSettings::MultimoduleSettings(Window *parent,
lv_obj_add_event_cb(st_line->getLvObj(), update_mpm_settings,
LV_EVENT_VALUE_CHANGED, this);

cl_line = new MPMDSMCloned(this, &grid, moduleIdx);
opt_line = new MPMProtoOption(this, &grid);
sr_line = new MPMServoRate(this, &grid, moduleIdx);
ab_line = new MPMAutobind(this, &grid, moduleIdx);
Expand Down Expand Up @@ -370,6 +393,13 @@ void MultimoduleSettings::update()
ab_line->update();
}

if (isMultiProtocolDSMCloneAvailable(moduleIdx)) {
lv_obj_clear_flag(cl_line->getLvObj(), LV_OBJ_FLAG_HIDDEN);
cl_line->update();
} else {
lv_obj_add_flag(cl_line->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}

lp_mode->update();
#if defined(MANUFACTURER_FRSKY)
disable_telem->update();
Expand Down
2 changes: 2 additions & 0 deletions radio/src/gui/colorlcd/mpm_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ToggleSwitch;
struct ModuleData;
struct MPMProtoOption;
struct MPMSubtype;
struct MPMDSMCloned;
struct MPMServoRate;
struct MPMAutobind;
struct MPMChannelMap;
Expand All @@ -40,6 +41,7 @@ class MultimoduleSettings : public FormWindow, public ModuleOptions

MPMSubtype* st_line;
MPMProtoOption* opt_line;
MPMDSMCloned* cl_line;
MPMServoRate* sr_line;
MPMAutobind* ab_line;
ToggleSwitch* lp_mode;
Expand Down
9 changes: 7 additions & 2 deletions radio/src/gui/gui_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,10 @@ inline bool MULTIMODULE_HAS_SUBTYPE(uint8_t moduleIdx)
inline uint8_t MULTIMODULE_RFPROTO_COLUMNS(uint8_t moduleIdx)
{
#if LCD_W < 212
return (MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW);
if (g_model.moduleData[moduleIdx].multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2)
return (MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t) 1 : HIDDEN_ROW);
else
return (MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW);
#else
return (MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t) 1 : 0);
#endif
Expand All @@ -324,6 +327,7 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
#else
#define MULTIMODULE_MODULE_ROWS(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) && !IS_RX_MULTI(moduleIdx)) ? (uint8_t) 0 : HIDDEN_ROW, MULTI_DISABLE_CHAN_MAP_ROW(moduleIdx), // AUTOBIND, DISABLE CN.MAP
#endif
#define MULTIMODULE_DSM_CLONED_RAW(moduleIdx) isMultiProtocolDSMCloneAvailable(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW
#define MULTIMODULE_TYPE_ROW(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW,
#define MULTIMODULE_STATUS_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(moduleIdx) && getModuleSyncStatus(moduleIdx).isValid()) ? TITLE_ROW : HIDDEN_ROW,
#define MULTIMODULE_MODE_ROWS(moduleIdx) (g_model.moduleData[moduleIdx].multi.customProto) ? (uint8_t) 3 : MULTIMODULE_HAS_SUBTYPE(moduleIdx) ? (uint8_t)2 : (uint8_t)1
Expand All @@ -333,6 +337,7 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
#define MODULE_POWER_ROW(moduleIdx) (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleAFHDS3(moduleIdx)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW

#else
#define MULTIMODULE_DSM_CLONED_RAW(moduleIdx)
#define MULTIMODULE_TYPE_ROWS(moduleIdx)
#define MULTIMODULE_STATUS_ROWS(moduleIdx)
#define MULTIMODULE_MODULE_ROWS(moduleIdx)
Expand All @@ -354,7 +359,7 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
#define AFHDS3_MODULE_ROWS(moduleIdx)
#endif

#define FAILSAFE_ROWS(moduleIdx) isModuleFailsafeAvailable(moduleIdx) ? (g_model.moduleData[moduleIdx].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW
#define FAILSAFE_ROW(moduleIdx) isModuleFailsafeAvailable(moduleIdx) ? (g_model.moduleData[moduleIdx].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW

inline uint8_t MODULE_OPTION_ROW(uint8_t moduleIdx) {
if(isModuleR9MNonAccess(moduleIdx) || isModuleSBUS(moduleIdx))
Expand Down
17 changes: 17 additions & 0 deletions radio/src/pulses/modules_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,23 @@ inline bool isModuleFailsafeAvailable(uint8_t moduleIdx)
return false;
}

#if defined(MULTIMODULE)
constexpr int32_t MULTI_DSM_CLONE_VERSION = (1 << 24) | (3 << 16) | (3 << 8) | 30;

inline bool isMultiProtocolDSMCloneAvailable(uint8_t moduleIdx)
{
if (!isModuleMultimodule(moduleIdx))
return false;

MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
if (status.isValid() && ((status.major << 24) | (status.minor << 16) | (status.revision << 8) | status.patch) < MULTI_DSM_CLONE_VERSION) {
return false;
}

return g_model.moduleData[moduleIdx].multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2;
}
#endif

inline bool isModuleBindRangeAvailable(uint8_t moduleIdx)
{
return isModulePXX2(moduleIdx) || isModulePXX1(moduleIdx) ||
Expand Down
2 changes: 2 additions & 0 deletions radio/src/pulses/multi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ void sendFrameProtocolHeader(uint8_t*& p_buf, uint8_t module, bool failsafe)
optionValue = 0x00;
if (g_model.moduleData[module].multi.optionValue & 0x02)
optionValue |= 0x40; // 11ms servo refresh
if (g_model.moduleData[module].multi.optionValue & 0x04)
optionValue |= 0x20; // Cloned
optionValue |= sentModuleChannels(module); //add number of channels
}

Expand Down
3 changes: 1 addition & 2 deletions radio/src/translations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ ISTR(MULTI_PROTOCOLS);
ISTR(MULTI_POWER);
ISTR(MULTI_BAYANG_OPTIONS);
ISTR(MULTI_DSM_OPTIONS);
ISTR(MULTI_DSM_CLONE);
ISTR(MULTI_WBUS_MODE);
#endif

Expand Down Expand Up @@ -913,9 +914,7 @@ const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[] =TR_AFHDS3_ONE_TO_ONE_TELEMETRY;
const char STR_AFHDS3_ONE_TO_MANY[] = TR_AFHDS3_ONE_TO_MANY;
#endif

#if LCD_W < 212
const char STR_SUBTYPE[] = TR_SUBTYPE;
#endif

const char STR_BACKUP_MODEL[] = TR_BACKUP_MODEL;
const char STR_RESTORE_MODEL[] = TR_RESTORE_MODEL;
Expand Down
Loading

0 comments on commit f4f04c1

Please sign in to comment.