diff --git a/radio/src/gui/taranis/menu_model_setup.cpp b/radio/src/gui/taranis/menu_model_setup.cpp index 501be83ca..7e10819f8 100644 --- a/radio/src/gui/taranis/menu_model_setup.cpp +++ b/radio/src/gui/taranis/menu_model_setup.cpp @@ -80,6 +80,10 @@ enum menuModelSetupItems { ITEM_MODEL_EXTERNAL_MODULE_CHANNELS, ITEM_MODEL_EXTERNAL_MODULE_BIND, ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE, +#ifdef MULTIMODULE + ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND, + ITEM_MODEL_EXTERNAL_MODULE_LOWPOWER, +#endif ITEM_MODEL_TRAINER_LABEL, ITEM_MODEL_TRAINER_MODE, ITEM_MODEL_TRAINER_CHANNELS, @@ -192,7 +196,7 @@ int getSwitchWarningsCount() #define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) #define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : TRAINER_CHANNELS_ROWS())) #if defined MULTIMODULE -#define MULTIMODULE_HASOPTIONS(x) (x == MM_RF_PROTO_HUBSAN || x == MM_RF_PROTO_FRSKY || x == MM_RF_PROTO_DSM2) +#define MULTIMODULE_HASOPTIONS(x) (x == MM_RF_PROTO_HUBSAN || x == MM_RF_PROTO_FRSKY || x == MM_RF_PROTO_DSM2 || x >= MM_RF_PROTO_CUSTOM) #define MULTIMODULE_FAILSAFEROWS(x) (IS_MODULE_MULTIMODULE(x) && (MULTIMODULE_HASOPTIONS(g_model.moduleData[x].multi.rfProtocol))) ? (uint8_t) 1: HIDDEN_ROW #else #define MULTIMODULE_FAILSAFEROWS(x) HIDDEN_ROW @@ -200,11 +204,13 @@ int getSwitchWarningsCount() #define FAILSAFE_ROWS(x) (IS_MODULE_XJT(x) && HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : MULTIMODULE_FAILSAFEROWS(x)) #define TIMER_ROWS 2|NAVIGATION_LINE_BY_LINE, 0, CASE_PERSISTENT_TIMERS(0) 0, 0 #if defined(MULTIMODULE) -#define MULTIMODULE_HAS_SUBTYPE(x) (x == MM_RF_PROTO_FLYSKY || x == MM_RF_PROTO_FRSKY || x == MM_RF_PROTO_HISKY || x == MM_RF_PROTO_DSM2 || x == MM_RF_PROTO_YD717 || x == MM_RF_PROTO_KN || x == MM_RF_PROTO_SYMAX || x == MM_RF_PROTO_CX10 || x == MM_RF_PROTO_CG023 || x == MM_RF_PROTO_MT99XX || x == MM_RF_PROTO_MJXQ) -#define MULTIMODULE_MODE_ROWS(x) MULTIMODULE_HAS_SUBTYPE(g_model.moduleData[x].multi.rfProtocol) ? (uint8_t)2 : (uint8_t)1 + +#define MULTIMODULE_HAS_SUBTYPE(x) (x == MM_RF_PROTO_FLYSKY || x == MM_RF_PROTO_FRSKY || x == MM_RF_PROTO_HISKY || x == MM_RF_PROTO_DSM2 || x == MM_RF_PROTO_YD717 || x == MM_RF_PROTO_KN || x == MM_RF_PROTO_SYMAX || x == MM_RF_PROTO_CX10 || x == MM_RF_PROTO_CG023 || x == MM_RF_PROTO_MT99XX || x == MM_RF_PROTO_MJXQ) +#define MULTIMODULE_MODE_ROWS(x) (g_model.moduleData[x].multi.rfProtocol >= MM_RF_PROTO_CUSTOM ) ? (uint8_t) 3 :MULTIMODULE_HAS_SUBTYPE(g_model.moduleData[x].multi.rfProtocol) ? (uint8_t)2 : (uint8_t)1 #define MULTIMODULE_MODULE_ROWS IS_MODULE_MULTIMODULE(EXTERNAL_MODULE) ? (uint8_t) 1 : HIDDEN_ROW, IS_MODULE_MULTIMODULE(EXTERNAL_MODULE) ? (uint8_t) 1 : HIDDEN_ROW, #else #define MULTIMODULE_MODE_ROWS(x) (uint8_t)0 +#define MULTIMODULE_MODULE_ROWS #endif #define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : IS_MODULE_MULTIMODULE(EXTERNAL_MODULE) ? MULTIMODULE_MODE_ROWS(EXTERNAL_MODULE) : (uint8_t)0 @@ -225,6 +231,7 @@ int getSwitchWarningsCount() #define TOPLCD_ROWS #endif + void menuModelSetup(uint8_t event) { horzpos_t l_posHorz = menuHorizontalPosition; @@ -256,7 +263,7 @@ void menuModelSetup(uint8_t event) EXTERNAL_MODULE_MODE_ROWS, EXTERNAL_MODULE_CHANNELS_ROWS, (IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, - FAILSAFE_ROWS(EXTERNAL_MODULE), + FAILSAFE_ROWS(EXTERNAL_MODULE), MULTIMODULE_MODULE_ROWS LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); #endif MENU_CHECK(STR_MENUSETUP, menuTabModel, e_ModelSetup, ITEM_MODEL_SETUP_MAX); @@ -681,8 +688,10 @@ void menuModelSetup(uint8_t event) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0); #if defined(MULTIMODULE) else if (IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) { - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_MULTI_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol, menuHorizontalPosition==1 ? attr : 0); - switch(g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol) { + int8_t multi_rfProto = min(g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol, (uint8_t) MM_RF_PROTO_CUSTOM); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_MULTI_PROTOCOLS, multi_rfProto, menuHorizontalPosition==1 ? attr : 0); + + switch(multi_rfProto) { case MM_RF_PROTO_FLYSKY: lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+11*FW, y, STR_SUBTYPE_FLYSKY, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0); break; @@ -716,6 +725,10 @@ void menuModelSetup(uint8_t event) case MM_RF_PROTO_MJXQ: lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+11*FW, y, STR_SUBTYPE_MJXQ, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0); break; + case MM_RF_PROTO_CUSTOM: + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+14*FW, y, g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol & 0x1f, menuHorizontalPosition==2 ? attr : 0, 2); + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+16*FW, y, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==3 ? attr : 0, 2); + break; } } #endif @@ -746,7 +759,7 @@ void menuModelSetup(uint8_t event) break; #if defined(MULTIMODULE) case 2: - switch (g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol) { + switch (min(g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol, (uint8_t) MM_RF_PROTO_CUSTOM)) { case MM_RF_PROTO_HISKY: case MM_RF_PROTO_DSM2: case MM_RF_PROTO_SYMAX: @@ -768,8 +781,15 @@ void menuModelSetup(uint8_t event) case MM_RF_PROTO_CX10: CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 7); break; + case MM_RF_PROTO_CUSTOM: + g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol = 0x20 | checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].multi.rfProtocol & 0x1f, 1, 31, EE_MODEL); + break; } break; + case 3: + // Custom protocol, third column is subtype + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 7); + break; #endif } } @@ -918,21 +938,34 @@ void menuModelSetup(uint8_t event) } #if defined(MULTIMODULE) else if (IS_MODULE_MULTIMODULE(moduleIdx)) { - switch (g_model.moduleData[moduleIdx].multi.rfProtocol) { - case MM_RF_PROTO_FRSKY: - lcd_putsLeft(y, TR_MULTI_RFTUNE); - break; - case MM_RF_PROTO_HUBSAN: - lcd_putsLeft(y, TR_MULTI_VIDFREQ); - break; - } - lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[moduleIdx].multi.optionValue, LEFT|attr); - if (attr) - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); + switch (g_model.moduleData[moduleIdx].multi.rfProtocol) { + case MM_RF_PROTO_FRSKY: + lcd_putsLeft(y, STR_MULTI_RFTUNE); + break; + case MM_RF_PROTO_HUBSAN: + lcd_putsLeft(y, STR_MULTI_VIDFREQ); + break; + default: + lcd_putsLeft(y, STR_MULTI_OPTION); + break; + } + lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.moduleData[moduleIdx].multi.optionValue, LEFT|attr); + if (attr) + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); + } } #endif break; } +#if defined(MULTIMODULE) + case ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND: + g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_AUTOBIND, attr, event); + break; + + case ITEM_MODEL_EXTERNAL_MODULE_LOWPOWER: + g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, STR_MULTI_LOWPOWER, attr, event); + break; +#endif } } diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index a23623f76..3f1143d4a 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -507,7 +507,8 @@ enum MultiModuleRFProtocols { MM_RF_PROTO_MT99XX, MM_RF_PROTO_MJXQ, MM_RF_PROTO_SHENQI, - MM_RF_PROTO_LAST= MM_RF_PROTO_SHENQI + MM_RF_PROTO_CUSTOM, + MM_RF_PROTO_LAST= MM_RF_PROTO_CUSTOM }; #define HAS_RF_PROTOCOL_FAILSAFE(rf) ((rf) == RF_PROTO_X16) diff --git a/radio/src/pulses/multi_arm.cpp b/radio/src/pulses/multi_arm.cpp index 26221a483..47eb44687 100644 --- a/radio/src/pulses/multi_arm.cpp +++ b/radio/src/pulses/multi_arm.cpp @@ -30,6 +30,7 @@ #define MULTI_SEND_BIND (1 << 7) #define MULTI_SEND_RANGECHECK (1 << 5) +#define MULTI_SEND_AUTOBIND (1 << 6) #define BITLEN_MULTI (10*2) //100000 Baud => 10uS per bit @@ -114,7 +115,7 @@ void setupPulsesMultimodule(unsigned int port) protoByte |= MULTI_SEND_RANGECHECK; // rfProtocol - // 15 is FrskyX or D16 which we map as a subprotocol of 3 (FrSky) + // 15 for Multimodule is FrskyX or D16 which we map as a subprotocol of 3 (FrSky) // all protos > frskyx are therefore also off by one if (type >=15) type= type +1; @@ -127,13 +128,19 @@ void setupPulsesMultimodule(unsigned int port) subtype = 0; } - protoByte |= (type & 0x1f); + if (g_model.moduleData[port].multi.rfProtocol >= MM_RF_PROTO_CUSTOM) + type = g_model.moduleData[port].multi.rfProtocol & 0x1f; + + protoByte |= (type & 0x1f) | (g_model.moduleData[port].multi.autoBindMode << 6); sendByteMulti(protoByte); // power always set to high (0 << 7) sendByteMulti((g_model.header.modelId[port] & 0x0f) - | (0 << 7) | ((subtype & 0x7) << 4)); + | ((subtype & 0x7) << 4) + | (g_model.moduleData[port].multi.lowPowerMode << 7) + ); + //TODO: option_protocol, use same default as multi module diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 68d169cff..3467653b8 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -448,8 +448,11 @@ const pm_char STR_SETUP_SCREENS[] PROGMEM = TR_SETUP_SCREENS; #endif #if defined(MULTIMODULE) - const pm_char STR_MULTI_RFTUNE[] PROGMEM = TR_MULTI_RFTUNE; - const pm_char STR_MULTI_VIDFREQ[] PROGMEM = TR_MULTI_VIDFREQ; +const pm_char STR_MULTI_RFTUNE[] PROGMEM = TR_MULTI_RFTUNE; +const pm_char STR_MULTI_VIDFREQ[] PROGMEM = TR_MULTI_VIDFREQ; +const pm_char STR_MULTI_OPTION[] PROGMEM = TR_MULTI_OPTION; +const pm_char STR_MULTI_AUTOBIND[] PROGMEM = TR_MULTI_AUTOBIND; +const pm_char STR_MULTI_LOWPOWER[] PROGMEM = TR_MULTI_LOWPOWER; #endif const pm_char STR_RESET_BTN[] PROGMEM = TR_RESET_BTN; diff --git a/radio/src/translations.h b/radio/src/translations.h index b5c421a11..0eadda25c 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -554,16 +554,18 @@ extern const pm_char STR_GF[]; #if defined(FAS_OFFSET) || !defined(CPUM64) extern const pm_char STR_FAS_OFFSET[]; -#endif - -#if defined(MULTIMODULE) -extern const pm_char STR_MULTI_OPT[]; #endif + +#if defined(MULTIMODULE) +extern const pm_char STR_MULTI_OPTION[]; extern const pm_char STR_MULTI_VIDFREQ[]; extern const pm_char STR_MULTI_RFTUNE[]; -#if defined(DSM2) || defined(PXX) -extern const pm_char STR_RXNUM[]; -#endif +extern const pm_char STR_MULTI_AUTOBIND[]; +extern const pm_char STR_MULTI_LOWPOWER[]; +#endif +#if defined(DSM2) || defined(PXX) +extern const pm_char STR_RXNUM[]; +#endif #if defined(PXX) || defined(CPUARM) extern const pm_char STR_SYNCMENU[]; diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 3bb41759f..eb5bdff5a 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -104,7 +104,7 @@ #define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX" #define LEN_MULTI_PROTOCOLS "\006" -#define TR_MULTI_PROTOCOLS "FlySky""Hubsan""FrSky\0""Hisky\0""V2x2\0 ""DSM2\0 ""Devo\0 ""YD717\0""KN\0 ""SymaX\0""SLT\0 ""CX10\0 ""CG023\0""Bayang""ESky\0 ""MT99XX""MJXQ\0 ""Shenqi" +#define TR_MULTI_PROTOCOLS "FlySky""Hubsan""FrSky\0""Hisky\0""V2x2\0 ""DSM2\0 ""Devo\0 ""YD717\0""KN\0 ""SymaX\0""SLT\0 ""CX10\0 ""CG023\0""Bayang""ESky\0 ""MT99XX""MJXQ\0 ""Shenqi""Custom" #define LEN_SUBTYPE_FLYSKY "\004" #define TR_SUBTYPE_FLYSKY "Std\0""V9x9""V6x6""V912" @@ -844,6 +844,9 @@ #endif #define TR_MULTI_RFTUNE INDENT "RF Freq. fine tune" #define TR_MULTI_VIDFREQ INDENT "Video frequency" +#define TR_MULTI_OPTION INDENT "Option value" +#define TR_MULTI_AUTOBIND INDENT "Autobind on power up" +#define TR_MULTI_LOWPOWER INDENT "Low power mode" #define TR_SYNCMENU "[Sync]" #define TR_LIMIT INDENT "Limit" #define TR_MINRSSI "Min Rssi"