From 744bcab0b96125c776306ab36158d22bc875ef20 Mon Sep 17 00:00:00 2001 From: WismyYao Date: Sat, 30 Jan 2021 13:39:09 +0800 Subject: [PATCH 01/70] enter racing mode by spec function --- radio/src/dataconstants.h | 1 + radio/src/functions.cpp | 8 +++++++- radio/src/gui/480x272/model_setup.cpp | 1 + radio/src/gui/gui_common.h | 8 ++++++++ radio/src/opentx.h | 1 + radio/src/pulses/pulses.cpp | 5 +++-- radio/src/pulses/pulses.h | 3 ++- radio/src/pulses/pxx.h | 2 +- radio/src/pulses/pxx2.cpp | 12 +++++++++--- radio/src/pulses/pxx2.h | 2 ++ radio/src/thirdparty/libACCESS | 2 +- radio/src/translations/cz.h.txt | 3 ++- radio/src/translations/de.h.txt | 3 ++- radio/src/translations/en.h.txt | 3 ++- radio/src/translations/es.h.txt | 5 +++-- radio/src/translations/fi.h.txt | 3 ++- radio/src/translations/fr.h.txt | 3 ++- radio/src/translations/it.h.txt | 3 ++- radio/src/translations/nl.h.txt | 5 +++-- radio/src/translations/pl.h.txt | 3 ++- radio/src/translations/pt.h.txt | 3 ++- radio/src/translations/se.h.txt | 5 +++-- 22 files changed, 61 insertions(+), 23 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index dae853d12..8348f75bd 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -852,6 +852,7 @@ enum Functions { FUNC_LOGS, FUNC_BACKLIGHT, FUNC_SCREENSHOT, + FUNC_RACING_MODE, #if defined(DEBUG) FUNC_TEST, // should remain the last before MAX as not added in Companion #endif diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp index 943ee5bda..817abf157 100644 --- a/radio/src/functions.cpp +++ b/radio/src/functions.cpp @@ -376,7 +376,13 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext case FUNC_SCREENSHOT: if (!(functionsContext.activeSwitches & switch_mask)) { - mainRequestFlags |= (1 << REQUEST_SCREENSHOT); + mainRequestFlags |= (1u << REQUEST_SCREENSHOT); + } + break; + + case FUNC_RACING_MODE: + if (isRacingModeAllowed()) { + newActiveFunctions |= (1u << FUNCTION_RACING_MODE); } break; diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index cd9974ac5..f5dd8152a 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1247,6 +1247,7 @@ bool menuModelSetup(event_t event) } break; } + case ITEM_MODEL_SETUP_TRAINER_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRAINER); break; diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 8f30a624e..0140e8fa3 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -184,6 +184,14 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) } } +inline bool isRacingModeAllowed() +{ + if (isModulePXX2(INTERNAL_MODULE) && 0 == g_model.moduleData[INTERNAL_MODULE].channelsCount) + return true; + else + return false; +} + #if defined(MULTIMODULE) inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx) { diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 2580aa653..3f759a439 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -872,6 +872,7 @@ enum FunctionsActive { FUNCTION_BACKGND_MUSIC, FUNCTION_BACKGND_MUSIC_PAUSE, FUNCTION_BACKLIGHT, + FUNCTION_RACING_MODE, }; #define VARIO_FREQUENCY_ZERO 700/*Hz*/ diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index ed56f8b61..3adb49818 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -526,10 +526,11 @@ void setCustomFailsafe(uint8_t moduleIndex) g_model.failsafeChannels[ch] = channelOutputs[ch]; } } + storageDirty(EE_MODEL); } } -int32_t getChannelValue(uint8_t channel) { +int32_t getChannelValue(uint8_t channel) +{ return channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER; } - diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 84ecee015..0240d33a0 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -142,7 +142,8 @@ PACK(struct ModuleState { uint8_t protocol:4; uint8_t mode:4; uint8_t paused:1; - uint8_t spare:7; + uint8_t racingMode:1; + uint8_t spare:6; uint16_t counter; union { diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index 5d0bfaf05..70a5ae8c8 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -29,7 +29,7 @@ #define PXX2_LOWSPEED_BAUDRATE 230400 #define PXX2_HIGHSPEED_BAUDRATE 450000 -#define PXX2_PERIOD 4 // 4ms +#define PXX2_PERIOD 50 // 4ms #define PXX2_TOOLS_PERIOD 1 // 1ms #define PXX2_FRAME_MAXLENGTH 64 diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index e396db4bb..8152f92e5 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -47,14 +47,20 @@ void Pxx2Pulses::addFlag1(uint8_t module) else { subType = g_model.moduleData[module].subType; } - Pxx2Transport::addByte(subType << 4); + + uint8_t flag1 = subType << 4u; + if (isFunctionActive(FUNCTION_RACING_MODE)) { + flag1 |= PXX2_CHANNELS_FLAG1_RACING_MODE; + } + + Pxx2Transport::addByte(flag1); } void Pxx2Pulses::addPulsesValues(uint16_t low, uint16_t high) { Pxx2Transport::addByte(low); // Low byte of channel - Pxx2Transport::addByte(((low >> 8) & 0x0F) | (high << 4)); // 4 bits each from 2 channels - Pxx2Transport::addByte(high >> 4); // High byte of channel + Pxx2Transport::addByte(((low >> 8u) & 0x0Fu) | (high << 4u)); // 4 bits each from 2 channels + Pxx2Transport::addByte(high >> 4u); // High byte of channel } void Pxx2Pulses::addChannels(uint8_t module) diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index d6b3402fe..b752c06c8 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -46,6 +46,7 @@ #define PXX2_CHANNELS_FLAG0_FAILSAFE (1 << 6) #define PXX2_CHANNELS_FLAG0_RANGECHECK (1 << 7) +#define PXX2_CHANNELS_FLAG1_RACING_MODE (1 << 3) #define PXX2_RX_SETTINGS_FLAG0_WRITE (1 << 6) @@ -268,6 +269,7 @@ enum ReceiverCapabilities { RECEIVER_CAPABILITY_TELEMETRY_25MW, RECEIVER_CAPABILITY_ENABLE_PWM_CH5_CH6, RECEIVER_CAPABILITY_FPORT2, + RECEIVER_CAPABILITY_RACING_MODE, RECEIVER_CAPABILITY_COUNT }; diff --git a/radio/src/thirdparty/libACCESS b/radio/src/thirdparty/libACCESS index 63802e6d5..79a6921d2 160000 --- a/radio/src/thirdparty/libACCESS +++ b/radio/src/thirdparty/libACCESS @@ -1 +1 @@ -Subproject commit 63802e6d50a9c7e07a6ae063f162320227995248 +Subproject commit 79a6921d2386236a44e87554195bf41dc412b445 diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 59eae1a46..2e3e5bc74 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -231,9 +231,10 @@ #endif #define TR_SF_SCREENSHOT "Snímek LCD\0" +#define TR_SF_RACING_MODE "RacingMode\0" #define TR_SF_RESERVE "[rezerva]\0 " -#define TR_VFSWFUNC TR_SF_SAFETY "Trenér \0 ""Insta-Trim\0""Reset\0 ""Změna \0 " TR_ADJUST_GVAR "Hlasitost\0 " "SetFailsafe" "RangeCheck\0" "ModuleBind\0" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Podsvětlení" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Trenér \0 ""Insta-Trim\0""Reset\0 ""Změna \0 " TR_ADJUST_GVAR "Hlasitost\0 " "SetFailsafe" "RangeCheck\0" "ModuleBind\0" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Podsvětlení" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\012") diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index fb36f0021..49015a0a6 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -234,9 +234,10 @@ #endif #define TR_SF_SCREENSHOT "Screenshot" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[Reserve]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Lehrer \0 ""Inst. Trim""Rücksetz.\0""Setze \0 " TR_ADJUST_GVAR "Lautstr.\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "LCD Licht\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Lehrer \0 ""Inst. Trim""Rücksetz.\0""Setze \0 " TR_ADJUST_GVAR "Lautstr.\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "LCD Licht\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index f66e99a33..69cd7cd36 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -234,9 +234,10 @@ #endif #define TR_SF_SCREENSHOT "Screenshot" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[reserve]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 0e5fa3dc7..870a21566 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -231,10 +231,11 @@ #define TR_SF_SAFETY "---\0 " #endif -#define TR_SF_SCREENSHOT "Captura" +#define TR_SF_SCREENSHOT "Captura\0 " +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[reserv.]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Entrenador""Inst. Trim""Reset\0 ""Ajuste \0 " TR_ADJUST_GVAR "Volumen\0 " "Failsafe\0 " "CheckRango" "Enl.módulo" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Luz Fondo\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Entrenador""Inst. Trim""Reset\0 ""Ajuste \0 " TR_ADJUST_GVAR "Volumen\0 " "Failsafe\0 " "CheckRango" "Enl.módulo" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Luz Fondo\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\012") #define TR_FSW_RESET_TELEM TR("Telm", "Telemetría") diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 0bd9c954f..318c29652 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -235,9 +235,10 @@ #endif #define TR_SF_SCREENSHOT "Screenshot" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[reserve]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index fb818f7e8..8432efafe 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -237,9 +237,10 @@ #endif #define TR_SF_SCREENSHOT "Photo Ecran\0 " +#define TR_SF_RACING_MODE "Racing Mode\0 " #define TR_SF_RESERVE "[reserve]\0 " - #define TR_VFSWFUNC TR_SF_SAFETY "Ecolage\0 ""Trim instant.""Remise à 0\0 ""Déf.\0 " TR_ADJUST_GVAR "Volume\0 " "DéfFailsafe\0 " "Test Port.\0 " "Bind\0 " TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Rétroécl.\0 " TR_SF_SCREENSHOT TR_SF_TEST + #define TR_VFSWFUNC TR_SF_SAFETY "Ecolage\0 ""Trim instant.""Remise à 0\0 ""Déf.\0 " TR_ADJUST_GVAR "Volume\0 " "DéfFailsafe\0 " "Test Port.\0 " "Bind\0 " TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Rétroécl.\0 " TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\012") diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 9a0785a1e..cba642ef4 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -238,9 +238,10 @@ #endif #define TR_SF_SCREENSHOT "Screenshot\0 " +#define TR_SF_RACING_MODE "Racing Mode\0 " #define TR_SF_RESERVE "[riserva] \0" -#define TR_VFSWFUNC TR_SF_SAFETY "Maestro \0 ""Trim Instant.""Azzera\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsafe\0 " "RangeCheck\0 " "ModuleBind\0 " TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Retroillum.\0 " TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Maestro \0 ""Trim Instant.""Azzera\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsafe\0 " "RangeCheck\0 " "ModuleBind\0 " TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Retroillum.\0 " TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 13f567589..b523a44fb 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -234,10 +234,11 @@ #define TR_SF_SAFETY "---\0 " #endif -#define TR_SF_SCREENSHOT "Schermafdruk" +#define TR_SF_SCREENSHOT "Schermafdr" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[reserve]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Inst. Trim""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\012") diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index bf59714cf..30da0f4a3 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -235,9 +235,10 @@ #endif #define TR_SF_SCREENSHOT "Zrzut Ekra" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[rezerwa]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Trener \0 ""Inst-Trim ""Resetuj\0 ""Ustaw\0 " TR_ADJUST_GVAR "Głośność\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Podświetl\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Trener \0 ""Inst-Trim ""Resetuj\0 ""Ustaw\0 " TR_ADJUST_GVAR "Głośność\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Podświetl\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") /*9 decimal*/ diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 8c794822e..3b9609a28 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -231,9 +231,10 @@ #endif #define TR_SF_SCREENSHOT "Screenshot" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[reserve]\0 " -#define TR_VFSWFUNC TR_SF_SAFETY "Aprendiz\0 ""Ajuste Rapido""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsafe\0 " "RangeCheck\0 " "ModuleBind\0 " TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0 " TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Aprendiz\0 ""Ajuste Rapido""Reset\0 ""Set \0 " TR_ADJUST_GVAR "Volume\0 " "SetFailsafe\0 " "RangeCheck\0 " "ModuleBind\0 " TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Backlight\0 " TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 54c081eb3..5013a3c2c 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -231,10 +231,11 @@ #define TR_SF_SAFETY "---\0 " #endif -#define TR_SF_SCREENSHOT "Skärmbild" +#define TR_SF_SCREENSHOT "Skärmbild\0" +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[reserve]\0" -#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Sätt Trim\0""Nollställ\0""Sätt\0 " TR_ADJUST_GVAR "Volym\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Belysning\0" TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "Trainer\0 ""Sätt Trim\0""Nollställ\0""Sätt\0 " TR_ADJUST_GVAR "Volym\0 " "SetFailsfe" "RangeCheck" "ModuleBind" TR_SOUND TR_PLAY_TRACK TR_PLAY_VALUE TR_SF_RESERVE TR_SF_PLAY_SCRIPT TR_SF_RESERVE TR_SF_BG_MUSIC TR_VVARIO TR_HAPTIC TR_SDCLOGS "Belysning\0" TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\011") From baa63a54246097e57632808875b20e3d2335a997 Mon Sep 17 00:00:00 2001 From: WismyYao Date: Sat, 30 Jan 2021 15:15:29 +0800 Subject: [PATCH 02/70] add checkbox for racing mode --- radio/src/gui/128x64/model_setup.cpp | 12 ++++++++++++ radio/src/gui/212x64/model_setup.cpp | 11 +++++++++++ radio/src/gui/480x272/model_setup.cpp | 19 +++++++++++++++++++ radio/src/gui/gui_common.h | 14 +++++++++++++- radio/src/translations.cpp | 1 + radio/src/translations.h | 1 + radio/src/translations/cz.h.txt | 1 + radio/src/translations/de.h.txt | 1 + radio/src/translations/en.h.txt | 1 + radio/src/translations/es.h.txt | 1 + radio/src/translations/fi.h.txt | 1 + radio/src/translations/fr.h.txt | 1 + radio/src/translations/it.h.txt | 1 + radio/src/translations/nl.h.txt | 1 + radio/src/translations/pl.h.txt | 1 + radio/src/translations/pt.h.txt | 2 +- radio/src/translations/se.h.txt | 1 + 17 files changed, 68 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 468597b29..b38f7e6bc 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -92,6 +92,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS, #endif ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS, + ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE, ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM, ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS, @@ -323,6 +324,7 @@ void onBluetoothConnectMenu(const char * result) MULTIMODULE_SUBTYPE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_SUBTYPE */ \ MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS */ \ 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 */ \ MODULE_OPTION_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS */ \ @@ -1230,6 +1232,16 @@ void menuModelSetup(event_t event) break; } +#if defined(HARDWARE_INTERNAL_MODULE) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE: + { + ModuleData & moduleData = g_model.moduleData[moduleIdx]; + lcdDrawTextAlignedLeft(y, STR_RACING_MODE); + moduleState[moduleIdx].racingMode = editCheckBox(moduleState[moduleIdx].racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + break; + } +#endif + #if defined(PCBX7) || defined(PCBX9LITE) || defined(PCBXLITE) case ITEM_MODEL_SETUP_TRAINER_PPM_PARAMS: lcdDrawTextAlignedLeft(y, STR_PPMFRAME); diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 5a2d05446..e8b5f4c0b 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -87,6 +87,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL, ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE, ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS, + ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE, ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM, ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE, @@ -362,6 +363,7 @@ void menuModelSetup(event_t event) 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 @@ -1098,6 +1100,15 @@ void menuModelSetup(event_t event) break; } + case ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE: + { + uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); + ModuleData & moduleData = g_model.moduleData[moduleIdx]; + lcdDrawTextAlignedLeft(y, STR_RACING_MODE); + moduleState[moduleIdx].racingMode = editCheckBox(moduleState[moduleIdx].racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + break; + } + case ITEM_MODEL_SETUP_TRAINER_PPM_PARAMS: lcdDrawTextAlignedLeft(y, STR_PPMFRAME); lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.trainerData.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT); diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index f5dd8152a..1ef39d137 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -75,6 +75,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS, #endif ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS, + ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE, ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM, ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS, @@ -577,7 +578,12 @@ void onModelAntennaSwitchConfirm(const char * result) MODULE_TYPE_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE*/ \ MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS */ \ MODULE_CHANNELS_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS*/ \ +<<<<<<< HEAD IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\ +======= + IF_ALLOW_RACING_MODE(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE */ \ + IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\ +>>>>>>> 4b08d4bdeb2f13c57794ec8225bfa5b9a6ad06c9 IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM*/ \ MODULE_OPTION_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS */ \ MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND */ \ @@ -1248,6 +1254,19 @@ bool menuModelSetup(event_t event) break; } +<<<<<<< HEAD +======= +#if defined(HARDWARE_INTERNAL_MODULE) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE: + { + ModuleData & moduleData = g_model.moduleData[moduleIdx]; + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RACING_MODE); + moduleState[moduleIdx].racingMode = editCheckBox(moduleState[moduleIdx].racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + break; + } +#endif + +>>>>>>> 4b08d4bdeb2f13c57794ec8225bfa5b9a6ad06c9 case ITEM_MODEL_SETUP_TRAINER_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRAINER); break; diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 0140e8fa3..45966fd33 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -186,12 +186,24 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) inline bool isRacingModeAllowed() { - if (isModulePXX2(INTERNAL_MODULE) && 0 == g_model.moduleData[INTERNAL_MODULE].channelsCount) + if (isModulePXX2(INTERNAL_MODULE) && 0 == g_model.moduleData[INTERNAL_MODULE].channelsCount && moduleState[INTERNAL_MODULE].racingMode) return true; else return false; } +inline uint8_t IF_ALLOW_RACING_MODE(int moduleIdx) +{ + if (!IS_MODULE_ENABLED(moduleIdx)) { + return HIDDEN_ROW; + } + else if (isModulePXX2(moduleIdx)) { + if (0 == g_model.moduleData[moduleIdx].channelsCount) + return 1; + } + return HIDDEN_ROW; +} + #if defined(MULTIMODULE) inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx) { diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 455d6490d..071ee2815 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -831,3 +831,4 @@ const char STR_ABOUT_PARENTS_4[] = TR_ABOUT_PARENTS_4; const char STR_AUTH_FAILURE[] = TR_AUTH_FAILURE; const char STR_PROTOCOL[] = TR_PROTOCOL; +const char STR_RACING_MODE[] = TR_RACING_MODE; diff --git a/radio/src/translations.h b/radio/src/translations.h index a9131d8a5..b5b4ea47d 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -966,6 +966,7 @@ extern const char STR_ABOUT_PARENTS_4[]; extern const char STR_AUTH_FAILURE[]; extern const char STR_PROTOCOL[]; +extern const char STR_RACING_MODE[]; #define CHR_HOUR TR_CHR_HOUR #define CHR_INPUT TR_CHR_INPUT diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 2e3e5bc74..01e48a3d4 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1225,6 +1225,7 @@ #define TR_JITTER_FILTER "ADC Filtr" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 49015a0a6..55ec1fc61 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1231,6 +1231,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" // ---------------------------------------------------------------- #define ZSTR_VFR "VFR" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 69cd7cd36..d04dfecd8 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1229,6 +1229,7 @@ #define TR_JITTER_FILTER "ADC filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 870a21566..4a4c0e45e 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1228,6 +1228,7 @@ #define TR_JITTER_FILTER "Filtro ADC" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltaje") #define TR_AUTH_FAILURE "Fallo " LCDW_128_480_LINEBREAK "autentificación" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 318c29652..b6f72ac1a 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1237,6 +1237,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 8432efafe..abc52a10c 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1253,6 +1253,7 @@ #define TR_JITTER_FILTER "Filtre ADC" #define TR_RTC_CHECK TR("Vérif. RTC", "Vérif. pile RTC") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index cba642ef4..9e46d9846 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1246,6 +1246,7 @@ #define TR_JITTER_FILTER "Filtro ADC" #define TR_RTC_CHECK TR("Controllo RTC", "Controllo volt. RTC") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index b523a44fb..de559721c 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1238,6 +1238,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 30da0f4a3..f125ae98f 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1245,6 +1245,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 3b9609a28..9a18e4eb7 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1245,7 +1245,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" - +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 5013a3c2c..6e3b867f3 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1245,6 +1245,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" +#define TR_RACING_MODE INDENT "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" From f735360dc0631224c8d3da2b2d0d2e410114aa73 Mon Sep 17 00:00:00 2001 From: WismyYao Date: Mon, 1 Feb 2021 17:31:59 +0800 Subject: [PATCH 03/70] fix --- radio/src/gui/480x272/model_setup.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 1ef39d137..0dd737140 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -578,12 +578,8 @@ void onModelAntennaSwitchConfirm(const char * result) MODULE_TYPE_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE*/ \ MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS */ \ MODULE_CHANNELS_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS*/ \ -<<<<<<< HEAD - IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\ -======= IF_ALLOW_RACING_MODE(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE */ \ - IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\ ->>>>>>> 4b08d4bdeb2f13c57794ec8225bfa5b9a6ad06c9 + 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*/ \ MODULE_OPTION_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS */ \ MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND */ \ @@ -1254,8 +1250,6 @@ bool menuModelSetup(event_t event) break; } -<<<<<<< HEAD -======= #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE: { @@ -1266,7 +1260,6 @@ bool menuModelSetup(event_t event) } #endif ->>>>>>> 4b08d4bdeb2f13c57794ec8225bfa5b9a6ad06c9 case ITEM_MODEL_SETUP_TRAINER_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRAINER); break; From 72feef391131c551b086de5ede526953505c0a10 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 1 Feb 2021 23:02:52 +0100 Subject: [PATCH 04/70] All my comments from the PR fixed. Still missing the Companion part --- radio/src/datastructs.h | 14 +++++++++++--- radio/src/functions.cpp | 2 +- radio/src/gui/128x64/model_setup.cpp | 5 ++--- radio/src/gui/212x64/model_setup.cpp | 5 ++--- radio/src/gui/480x272/model_setup.cpp | 5 ++--- radio/src/gui/gui_common.h | 15 ++++++++------- radio/src/lua/api_model.cpp | 2 +- radio/src/pulses/pxx2.cpp | 2 +- radio/src/thirdparty/libACCESS | 2 +- radio/src/translations/cz.h.txt | 2 +- radio/src/translations/de.h.txt | 2 +- radio/src/translations/en.h.txt | 2 +- radio/src/translations/es.h.txt | 2 +- radio/src/translations/fi.h.txt | 2 +- radio/src/translations/fr.h.txt | 2 +- radio/src/translations/it.h.txt | 2 +- radio/src/translations/nl.h.txt | 2 +- radio/src/translations/pl.h.txt | 2 +- radio/src/translations/pt.h.txt | 2 +- radio/src/translations/se.h.txt | 2 +- 20 files changed, 40 insertions(+), 34 deletions(-) diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index b37dd3e55..bdb777334 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -451,7 +451,8 @@ PACK(struct ModuleData { int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms) } sbus); NOBACKUP(PACK(struct { - uint8_t receivers; // 5 bits spare + uint8_t receiver:7; // 4 bits spare + uint8_t racingMode:1; char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME]; }) pxx2); NOBACKUP(PACK(struct { @@ -475,14 +476,21 @@ PACK(struct ModuleData { }; // Helper functions to set both of the rfProto protocol at the same time - NOBACKUP(inline uint8_t getMultiProtocol() { + NOBACKUP(inline uint8_t getMultiProtocol() const + { return ((uint8_t) (rfProtocol & 0x0F)) + (multi.rfProtocolExtra << 4); }) - NOBACKUP(inline void setMultiProtocol(uint8_t proto) { + NOBACKUP(inline void setMultiProtocol(uint8_t proto) + { rfProtocol = (uint8_t) (proto & 0x0F); multi.rfProtocolExtra = (proto & 0x70) >> 4; }) + + NOBACKUP(inline uint8_t getChannelsCount() const + { + return channelsCount + 8; + }) }); /* diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp index 817abf157..cf4c87d39 100644 --- a/radio/src/functions.cpp +++ b/radio/src/functions.cpp @@ -381,7 +381,7 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext break; case FUNC_RACING_MODE: - if (isRacingModeAllowed()) { + if (isRacingModeEnabled()) { newActiveFunctions |= (1u << FUNCTION_RACING_MODE); } break; diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index b38f7e6bc..95ec079a4 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -1236,8 +1236,8 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE: { ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcdDrawTextAlignedLeft(y, STR_RACING_MODE); - moduleState[moduleIdx].racingMode = editCheckBox(moduleState[moduleIdx].racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + lcdDrawText(INDENT_WIDTH, y, STR_RACING_MODE); + moduleData.pxx2.racingMode = editCheckBox(moduleData.pxx2.racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); break; } #endif @@ -1522,7 +1522,6 @@ void menuModelSetup(event_t event) if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); setCustomFailsafe(moduleIdx); - storageDirty(EE_MODEL); AUDIO_WARNING1(); SEND_FAILSAFE_NOW(moduleIdx); } diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index e8b5f4c0b..2e719c756 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -1104,8 +1104,8 @@ void menuModelSetup(event_t event) { uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcdDrawTextAlignedLeft(y, STR_RACING_MODE); - moduleState[moduleIdx].racingMode = editCheckBox(moduleState[moduleIdx].racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + lcdDrawText(INDENT_WIDTH, y, STR_RACING_MODE); + moduleData.pxx2.racingMode = editCheckBox(moduleData.pxx2.racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); break; } @@ -1281,7 +1281,6 @@ void menuModelSetup(event_t event) if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); setCustomFailsafe(moduleIdx); - storageDirty(EE_MODEL); AUDIO_WARNING1(); SEND_FAILSAFE_NOW(moduleIdx); } diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 0dd737140..562d943f3 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1254,8 +1254,8 @@ bool menuModelSetup(event_t event) case ITEM_MODEL_SETUP_INTERNAL_MODULE_RACING_MODE: { ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RACING_MODE); - moduleState[moduleIdx].racingMode = editCheckBox(moduleState[moduleIdx].racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RACING_MODE); + moduleData.pxx2.racingMode = editCheckBox(moduleData.pxx2.racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); break; } #endif @@ -1666,7 +1666,6 @@ bool menuModelSetup(event_t event) if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); setCustomFailsafe(moduleIdx); - storageDirty(EE_MODEL); AUDIO_WARNING1(); SEND_FAILSAFE_NOW(moduleIdx); } diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 45966fd33..80401403f 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -186,10 +186,12 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) inline bool isRacingModeAllowed() { - if (isModulePXX2(INTERNAL_MODULE) && 0 == g_model.moduleData[INTERNAL_MODULE].channelsCount && moduleState[INTERNAL_MODULE].racingMode) - return true; - else - return false; + return isModulePXX2(INTERNAL_MODULE) && g_model.moduleData[INTERNAL_MODULE].getChannelsCount() == 8; +} + +inline bool isRacingModeEnabled() +{ + return isRacingModeAllowed() && g_model.moduleData[INTERNAL_MODULE].pxx2.racingMode; } inline uint8_t IF_ALLOW_RACING_MODE(int moduleIdx) @@ -197,9 +199,8 @@ inline uint8_t IF_ALLOW_RACING_MODE(int moduleIdx) if (!IS_MODULE_ENABLED(moduleIdx)) { return HIDDEN_ROW; } - else if (isModulePXX2(moduleIdx)) { - if (0 == g_model.moduleData[moduleIdx].channelsCount) - return 1; + else if (isRacingModeAllowed()) { + return 0; } return HIDDEN_ROW; } diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp index 8bc7e3a6a..f19246e62 100644 --- a/radio/src/lua/api_model.cpp +++ b/radio/src/lua/api_model.cpp @@ -135,7 +135,7 @@ static int luaModelGetModule(lua_State *L) lua_pushtableinteger(L, "subType", module.subType); lua_pushtableinteger(L, "modelId", g_model.header.modelId[idx]); lua_pushtableinteger(L, "firstChannel", module.channelsStart); - lua_pushtableinteger(L, "channelsCount", module.channelsCount + 8); + lua_pushtableinteger(L, "channelsCount", module.getChannelsCount()); lua_pushtableinteger(L, "Type", module.type); #if defined(MULTIMODULE) if (module.type == MODULE_TYPE_MULTIMODULE) { diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index 8152f92e5..a96adba3f 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -49,7 +49,7 @@ void Pxx2Pulses::addFlag1(uint8_t module) } uint8_t flag1 = subType << 4u; - if (isFunctionActive(FUNCTION_RACING_MODE)) { + if (isRacingModeEnabled() && isFunctionActive(FUNCTION_RACING_MODE)) { flag1 |= PXX2_CHANNELS_FLAG1_RACING_MODE; } diff --git a/radio/src/thirdparty/libACCESS b/radio/src/thirdparty/libACCESS index 79a6921d2..63802e6d5 160000 --- a/radio/src/thirdparty/libACCESS +++ b/radio/src/thirdparty/libACCESS @@ -1 +1 @@ -Subproject commit 79a6921d2386236a44e87554195bf41dc412b445 +Subproject commit 63802e6d50a9c7e07a6ae063f162320227995248 diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 01e48a3d4..bfb2e3006 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1225,7 +1225,7 @@ #define TR_JITTER_FILTER "ADC Filtr" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 55ec1fc61..6c906b49e 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1231,7 +1231,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" // ---------------------------------------------------------------- #define ZSTR_VFR "VFR" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index d04dfecd8..d61d940ad 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1229,7 +1229,7 @@ #define TR_JITTER_FILTER "ADC filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 4a4c0e45e..353aab18f 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1228,7 +1228,7 @@ #define TR_JITTER_FILTER "Filtro ADC" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltaje") #define TR_AUTH_FAILURE "Fallo " LCDW_128_480_LINEBREAK "autentificación" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index b6f72ac1a..025a3fd71 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1237,7 +1237,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index abc52a10c..247a4f2fc 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1253,7 +1253,7 @@ #define TR_JITTER_FILTER "Filtre ADC" #define TR_RTC_CHECK TR("Vérif. RTC", "Vérif. pile RTC") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 9e46d9846..d7878777b 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1246,7 +1246,7 @@ #define TR_JITTER_FILTER "Filtro ADC" #define TR_RTC_CHECK TR("Controllo RTC", "Controllo volt. RTC") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index de559721c..93fec41bf 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1238,7 +1238,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index f125ae98f..ba6192553 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1245,7 +1245,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 9a18e4eb7..faa4c95bb 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1245,7 +1245,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 6e3b867f3..03a3d883f 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1245,7 +1245,7 @@ #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define TR_AUTH_FAILURE "Auth-failure" -#define TR_RACING_MODE INDENT "Racing mode" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" From c5f3445f04ec56cba90da0022750ff9ad86033fe Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 1 Feb 2021 23:03:15 +0100 Subject: [PATCH 05/70] All my comments from the PR fixed. Still missing the Companion part --- radio/src/pulses/pulses.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 0240d33a0..84ecee015 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -142,8 +142,7 @@ PACK(struct ModuleState { uint8_t protocol:4; uint8_t mode:4; uint8_t paused:1; - uint8_t racingMode:1; - uint8_t spare:6; + uint8_t spare:7; uint16_t counter; union { From 20ff2328342da7c73855e148b385cc1e95add78d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 1 Feb 2021 23:19:04 +0100 Subject: [PATCH 06/70] All my comments from the PR fixed. Still missing the Companion part --- radio/src/datastructs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index bdb777334..765245b3e 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -451,7 +451,7 @@ PACK(struct ModuleData { int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms) } sbus); NOBACKUP(PACK(struct { - uint8_t receiver:7; // 4 bits spare + uint8_t receivers:7; // 4 bits spare uint8_t racingMode:1; char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME]; }) pxx2); From 8635f1521fcf951e8a4093f44b284d10e2894193 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 2 Feb 2021 08:55:05 +0100 Subject: [PATCH 07/70] Compilation fixes --- radio/src/functions.cpp | 2 ++ radio/src/gui/gui_common.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp index cf4c87d39..87d6ad199 100644 --- a/radio/src/functions.cpp +++ b/radio/src/functions.cpp @@ -380,11 +380,13 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext } break; +#if defined(PXX2) case FUNC_RACING_MODE: if (isRacingModeEnabled()) { newActiveFunctions |= (1u << FUNCTION_RACING_MODE); } break; +#endif #if defined(DEBUG) case FUNC_TEST: diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 80401403f..1ec1b2474 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -184,6 +184,7 @@ inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) } } +#if defined(PXX2) inline bool isRacingModeAllowed() { return isModulePXX2(INTERNAL_MODULE) && g_model.moduleData[INTERNAL_MODULE].getChannelsCount() == 8; @@ -204,6 +205,7 @@ inline uint8_t IF_ALLOW_RACING_MODE(int moduleIdx) } return HIDDEN_ROW; } +#endif #if defined(MULTIMODULE) inline uint8_t MULTI_DISABLE_CHAN_MAP_ROW(uint8_t moduleIdx) From d418f687cf3928f3af6e5d2f144761a54766bd00 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 2 Feb 2021 10:08:17 +0100 Subject: [PATCH 08/70] Compilation fixes --- radio/src/gui/gui_common.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 1ec1b2474..0d43a65c9 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -205,6 +205,11 @@ inline uint8_t IF_ALLOW_RACING_MODE(int moduleIdx) } return HIDDEN_ROW; } +#else +inline uint8_t IF_ALLOW_RACING_MODE(int) +{ + return HIDDEN_ROW; +} #endif #if defined(MULTIMODULE) From 5b931d3812f230853ef274c2a3e112145c985304 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 2 Feb 2021 13:06:59 +0100 Subject: [PATCH 09/70] Compilation fixes --- radio/src/gui/480x272/model_setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 562d943f3..5cc428906 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1255,7 +1255,7 @@ bool menuModelSetup(event_t event) { ModuleData & moduleData = g_model.moduleData[moduleIdx]; lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RACING_MODE); - moduleData.pxx2.racingMode = editCheckBox(moduleData.pxx2.racingMode, MODEL_SETUP_2ND_COLUMN, y, "", attr, event); + moduleData.pxx2.racingMode = editCheckBox(moduleData.pxx2.racingMode, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; } #endif From 6299c358447ee522d7943d1540dba3dd5754bb28 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 8 Feb 2021 22:46:11 +0100 Subject: [PATCH 10/70] [Companion] Racing mode support added --- companion/src/firmwares/moduledata.cpp | 13 ---------- companion/src/firmwares/moduledata.h | 2 +- .../src/firmwares/opentx/opentxeeprom.cpp | 7 +++--- companion/src/modeledit/setup.cpp | 24 +++++++++++++++---- companion/src/modeledit/setup.h | 1 + companion/src/modeledit/setup_module.ui | 23 +++++++++++------- 6 files changed, 40 insertions(+), 30 deletions(-) diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index b36d88e04..49a079d79 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -45,19 +45,6 @@ bool ModuleData::isPxx2Module() const } } -bool ModuleData::isPxx1Module() const -{ - switch(protocol){ - case PULSES_PXX_XJT_X16: - case PULSES_PXX_R9M: - case PULSES_PXX_R9M_LITE: - case PULSES_PXX_R9M_LITE_PRO: - return true; - default: - return false; - } -} - bool ModuleData::supportRxNum() const { switch (protocol) { diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index 119f44eb8..8acec18b0 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -215,12 +215,12 @@ class ModuleData { struct Access { unsigned int receivers; char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME+1]; + unsigned int racingMode; } access; void clear() { memset(this, 0, sizeof(ModuleData)); } void convert(RadioDataConversionState & cstate); bool isPxx2Module() const; - bool isPxx1Module() const; bool supportRxNum() const; QString polarityToString() const { return ppm.pulsePol ? tr("Positive") : tr("Negative"); } QString rfProtocolToString() const; diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index f9fc8c8f5..59caa99dd 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2158,15 +2158,16 @@ class ModuleUnionField: public UnionField { module(module) { internalField.Append(new UnsignedField<3>(this, module.access.receivers)); - internalField.Append(new SpareBitsField<5>(this)); + internalField.Append(new SpareBitsField<4>(this)); + internalField.Append(new UnsignedField<1>(this, module.access.racingMode)); - for (int i=0; i(this, receiverName[i])); memset(receiverName, 0, sizeof(receiverName)); } - bool select(const unsigned int& attr) const override + bool select(const unsigned int & attr) const override { return attr >= PULSES_ACCESS_ISRM && attr <= PULSES_ACCESS_R9M_LITE_PRO; } diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index d1756aa48..ae8635f09 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -226,6 +226,7 @@ void TimerPanel::onItemModelUpdateComplete() #define MASK_ACCESS (1<<13) #define MASK_RX_FREQ (1<<14) #define MASK_RF_POWER (1<<15) +#define MASK_RF_RACING_MODE (1<<16) quint8 ModulePanel::failsafesValueDisplayType = ModulePanel::FAILSAFE_DISPLAY_PERCENT; @@ -415,9 +416,9 @@ void ModulePanel::setupFailsafes() void ModulePanel::update() { - const PulsesProtocol protocol = (PulsesProtocol)module.protocol; - const Board::Type board = firmware->getBoard(); - const Multiprotocols::MultiProtocolDefinition & pdef = multiProtocols.getProtocol(module.multi.rfProtocol); + const auto protocol = (PulsesProtocol)module.protocol; + const auto board = firmware->getBoard(); + const auto & pdef = multiProtocols.getProtocol(module.multi.rfProtocol); unsigned int mask = 0; unsigned int max_rx_num = 63; @@ -450,6 +451,8 @@ void ModulePanel::update() mask |= MASK_RX_NUMBER | MASK_ACCESS; if (moduleIdx == 0 && HAS_EXTERNAL_ANTENNA(board) && generalSettings.antennaMode == 0 /* per model */) mask |= MASK_ANTENNA; + if (protocol == PULSES_ACCESS_ISRM && module.channelsCount == 8) + mask |= MASK_RF_RACING_MODE; break; case PULSES_LP45: case PULSES_DSM2: @@ -491,8 +494,6 @@ void ModulePanel::update() mask |= MASK_CHANNELS_RANGE| MASK_CHANNELS_COUNT | MASK_FAILSAFES; mask |= MASK_SUBTYPES | MASK_RX_FREQ | MASK_RF_POWER; break; - case PULSES_OFF: - break; default: break; } @@ -556,6 +557,14 @@ void ModulePanel::update() ui->antennaMode->hide(); } + if (mask & MASK_RF_RACING_MODE) { + ui->racingMode->show(); + ui->racingMode->setChecked(module.access.racingMode); + } + else { + ui->racingMode->hide(); + } + // R9M options ui->r9mPower->setVisible(mask & MASK_RF_POWER); ui->label_r9mPower->setVisible(mask & MASK_RF_POWER); @@ -845,6 +854,11 @@ void ModulePanel::on_disableChMap_stateChanged(int state) module.multi.disableMapping = (state == Qt::Checked); } +void ModulePanel::on_racingMode_stateChanged(int state) +{ + module.access.racingMode = (state == Qt::Checked); +} + void ModulePanel::on_autoBind_stateChanged(int state) { module.multi.autoBindMode = (state == Qt::Checked); diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index 7a5cddba9..692f26ea5 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -98,6 +98,7 @@ class ModulePanel : public ModelPanel void onSubTypeChanged(); void on_autoBind_stateChanged(int state); void on_disableChMap_stateChanged(int state); + void on_racingMode_stateChanged(int state); void on_disableTelem_stateChanged(int state); void on_lowPower_stateChanged(int state); void on_r9mPower_currentIndexChanged(int index); diff --git a/companion/src/modeledit/setup_module.ui b/companion/src/modeledit/setup_module.ui index 654af2a54..652975acd 100644 --- a/companion/src/modeledit/setup_module.ui +++ b/companion/src/modeledit/setup_module.ui @@ -1077,7 +1077,21 @@ - + + + + Disable Telemetry + + + + + + + Racing Mode + + + + Qt::Horizontal @@ -1090,13 +1104,6 @@ - - - - Disable Telemetry - - - From ffa14fc85d5e1783deca27926310c28162ca4334 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 11 Feb 2021 17:15:10 +0100 Subject: [PATCH 11/70] PXX2 period wrong for external modules! --- radio/src/pulses/pulses.cpp | 2 +- radio/src/pulses/pxx.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 3adb49818..8f58f2b55 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -451,7 +451,7 @@ bool setupPulsesInternalModule(uint8_t protocol) } else { #if defined(INTMODULE_HEARTBEAT) - scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD + 1 /* backup */); + scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD + 2 /* backup */); #else scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD); #endif diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h index 70a5ae8c8..5d0bfaf05 100644 --- a/radio/src/pulses/pxx.h +++ b/radio/src/pulses/pxx.h @@ -29,7 +29,7 @@ #define PXX2_LOWSPEED_BAUDRATE 230400 #define PXX2_HIGHSPEED_BAUDRATE 450000 -#define PXX2_PERIOD 50 // 4ms +#define PXX2_PERIOD 4 // 4ms #define PXX2_TOOLS_PERIOD 1 // 1ms #define PXX2_FRAME_MAXLENGTH 64 From c171047e25306e04dc1efdfe6de9aacfd0baceb2 Mon Sep 17 00:00:00 2001 From: elecpower Date: Sat, 6 Mar 2021 08:51:15 +1100 Subject: [PATCH 12/70] Remove use of palette and fix macos text with commentary --- companion/src/modeledit/curves.cpp | 45 +++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index 7f8b80219..9f0a71ae5 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -148,17 +148,47 @@ CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & // The edit curve button QPushButton * edit = new QPushButton(this); edit->setProperty("index", i); - QPalette palette; - palette.setBrush(QPalette::Active, QPalette::Button, QBrush(colors[i])); - palette.setBrush(QPalette::Active, QPalette::ButtonText, QBrush(Qt::white)); + /* + From https://doc.qt.io/qt-5/qwidget.html#palette-prop + + The current style, which is used to render the content of all standard Qt widgets, is free to choose colors and brushes + from the widget palette, or in some cases, to ignore the palette (partially, or completely). + In particular, certain styles like GTK style, Mac style, and Windows Vista style, depend on third party APIs to render + the content of widgets, and these styles typically do not follow the palette. Because of this, assigning roles to a widget's palette + is not guaranteed to change the appearance of the widget. Instead, you may choose to apply a styleSheet. + + Warning: Do not use this function in conjunction with Qt Style Sheets. + When using style sheets, the palette of a widget can be customized using the "color", "background-color", + "selection-color", "selection-background-color" and "alternate-background-color". + */ + + // can only assume there have been some OS version specific display issues so the stylesheet was added + // to ensure control remove use of QPalette + //QPalette palette; + //palette.setBrush(QPalette::Active, QPalette::Button, QBrush(colors[i])); + //palette.setBrush(QPalette::Active, QPalette::ButtonText, QBrush(Qt::white)); + +/* rework see below #ifdef __APPLE__ - edit->setStyleSheet(QString("color: %1;").arg(colors[i].name())); + // this sets text color to background color !!!! + //edit->setStyleSheet(QString("color: %1;").arg(colors[i].name())); #elif defined WIN32 || !defined __GNUC__ edit->setStyleSheet(QString("background-color: %1; color: white;").arg(colors[i].name())); #else - edit->setStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; border-radius: 2px; border-color: inherit;").arg(colors[i].name())); + // creates more compact buttons + edit->setStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; + border-radius: 2px; border-color: inherit;").arg(colors[i].name())); #endif - edit->setPalette(palette); +*/ + +#ifdef __GNUC__ + // creates more compact and likely consistent buttons across OS flavors + edit->setStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; border-radius: 2px; border-color: inherit;").arg(colors[i].name())); +#else + edit->setStyleSheet(QString("background-color: %1; color: white;").arg(colors[i].name())); +#endif + + //edit->setPalette(palette); edit->setText(tr("Curve %1").arg(i + 1)); edit->setContextMenuPolicy(Qt::CustomContextMenu); edit->setToolTip(tr("Popup menu available")); @@ -173,7 +203,8 @@ CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & // The curve plot checkbox QCheckBox * plot = new QCheckBox(this); plot->setProperty("index", i); - plot->setPalette(palette); + // this has no effect on the checkbox so remove + //plot->setPalette(palette); connect(plot, SIGNAL(toggled(bool)), this, SLOT(plotCurve(bool))); if (i < limit) { ui->curvesLayout->addWidget(plot, i, 2, 1, 1); From 1a8502e2840d42eec97853befa556fa47fbb25ba Mon Sep 17 00:00:00 2001 From: elecpower Date: Fri, 16 Apr 2021 06:59:21 +1000 Subject: [PATCH 13/70] Refactor setup hardware, trainer and calibration --- companion/src/firmwares/boards.cpp | 111 +- companion/src/firmwares/boards.h | 37 +- companion/src/firmwares/eeprominterface.h | 9 +- companion/src/firmwares/generalsettings.cpp | 273 +++- companion/src/firmwares/generalsettings.h | 208 ++- .../src/firmwares/opentx/opentxeeprom.cpp | 2 +- .../src/firmwares/opentx/opentxinterface.cpp | 15 +- companion/src/generaledit/CMakeLists.txt | 6 +- companion/src/generaledit/calibration.cpp | 104 +- companion/src/generaledit/calibration.h | 21 +- companion/src/generaledit/generaledit.cpp | 27 +- companion/src/generaledit/generaledit.h | 9 +- companion/src/generaledit/hardware.cpp | 502 ++++--- companion/src/generaledit/hardware.h | 51 +- companion/src/generaledit/hardware.ui | 1160 ----------------- companion/src/generaledit/trainer.cpp | 171 +-- companion/src/generaledit/trainer.h | 31 +- companion/src/generaledit/trainer.ui | 475 ------- companion/src/helpers.cpp | 24 +- companion/src/helpers.h | 2 + companion/src/shared/CMakeLists.txt | 1 + companion/src/shared/autocheckbox.h | 22 +- companion/src/shared/autodoublespinbox.h | 16 +- companion/src/shared/autospinbox.h | 81 ++ companion/src/shared/genericpanel.h | 1 + 25 files changed, 1081 insertions(+), 2278 deletions(-) delete mode 100644 companion/src/generaledit/hardware.ui delete mode 100644 companion/src/generaledit/trainer.ui create mode 100644 companion/src/shared/autospinbox.h diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index a201d50ed..5a44d246e 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -20,6 +20,7 @@ #include "boards.h" #include "macros.h" +#include "compounditemmodels.h" // TODO remove all those constants // Update: These are now all only used within this class. @@ -374,7 +375,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) case MultiposPotsPositions: return IS_HORUS_OR_TARANIS(board) ? 6 : 0; - case Switches: + case Board::Switches: if (IS_TARANIS_X9E(board)) return 18; else if (board == Board::BOARD_TARANIS_X9LITE) @@ -410,11 +411,11 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) else if (IS_HORUS_X12S(board)) return 8; else - return getCapability(board, Switches); + return getCapability(board, Board::Switches); case SwitchPositions: if (IS_HORUS_OR_TARANIS(board)) - return getCapability(board, Switches) * 3; + return getCapability(board, Board::Switches) * 3; else return 9; @@ -425,10 +426,14 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 4; case NumTrimSwitches: - return getCapability(board, NumTrims) * 2; - } + return getCapability(board, Board::NumTrims) * 2; - return 0; + case HasRTC: + return IS_STM32(board) ? true : false; + + default: + return 0; + } } QString Boards::getAxisName(int index) @@ -444,7 +449,7 @@ QString Boards::getAxisName(int index) if (index < (int)DIM(axes)) return axes[index]; else - return tr("Unknown"); + return CPN_STR_UNKNOWN_ITEM; } QString Boards::getAnalogInputName(Board::Type board, int index) @@ -595,6 +600,96 @@ QString Boards::getBoardName(Board::Type board) case BOARD_RADIOMASTER_T8: return "Radiomaster T8"; default: - return tr("Unknown"); + return CPN_STR_UNKNOWN_ITEM; } } + +// static +QString Boards::potTypeToString(int value) +{ + switch(value) { + case POT_NONE: + return tr("None"); + case POT_WITH_DETENT: + return tr("Pot with detent"); + case POT_MULTIPOS_SWITCH: + return tr("Multi pos switch"); + case POT_WITHOUT_DETENT: + return tr("Pot without detent"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + + +// static +QString Boards::sliderTypeToString(int value) +{ + switch(value) { + case SLIDER_NONE: + return tr("None"); + case SLIDER_WITH_DETENT: + return tr("Slider with detent"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString Boards::switchTypeToString(int value) +{ + switch(value) { + case SWITCH_NOT_AVAILABLE: + return tr("None"); + case SWITCH_TOGGLE: + return tr("2 Positions Toggle"); + case SWITCH_2POS: + return tr("2 Positions"); + case SWITCH_3POS: + return tr("3 Positions"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +AbstractStaticItemModel * Boards::potTypeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_BOARDS_POT_TYPE); + + for (int i = 0; i < POT_TYPE_COUNT; i++) { + mdl->appendToItemList(potTypeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * Boards::sliderTypeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_BOARDS_SLIDER_TYPE); + + for (int i = 0; i < SLIDER_TYPE_COUNT; i++) { + mdl->appendToItemList(sliderTypeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * Boards::switchTypeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_BOARDS_SWITCH_TYPE); + + for (int i = 0; i < SWITCH_TYPE_COUNT; i++) { + mdl->appendToItemList(switchTypeToString(i), i, true, 0, (i < SWITCH_3POS ? SwitchTypeFlag2Pos : SwitchTypeFlag3Pos)); + } + + mdl->loadItemList(); + return mdl; +} diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index e55aeae37..33ac887d9 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -18,13 +18,19 @@ * GNU General Public License for more details. */ -#ifndef _BOARDS_H_ -#define _BOARDS_H_ +#pragma once #include #include #include +class AbstractStaticItemModel; + +// identiying names of static abstract item models +constexpr char AIM_BOARDS_POT_TYPE[] {"boards.pottype"}; +constexpr char AIM_BOARDS_SLIDER_TYPE[] {"boards.slidertype"}; +constexpr char AIM_BOARDS_SWITCH_TYPE[] {"boards.switchtype"}; + // TODO create a Board class with all these functions namespace Board { @@ -64,13 +70,15 @@ namespace Board { POT_NONE, POT_WITH_DETENT, POT_MULTIPOS_SWITCH, - POT_WITHOUT_DETENT + POT_WITHOUT_DETENT, + POT_TYPE_COUNT }; enum SliderType { SLIDER_NONE, - SLIDER_WITH_DETENT + SLIDER_WITH_DETENT, + SLIDER_TYPE_COUNT }; enum SwitchType @@ -78,7 +86,8 @@ namespace Board { SWITCH_NOT_AVAILABLE, SWITCH_TOGGLE, SWITCH_2POS, - SWITCH_3POS + SWITCH_3POS, + SWITCH_TYPE_COUNT }; enum StickAxes { @@ -130,7 +139,8 @@ namespace Board { SwitchPositions, FactoryInstalledSwitches, NumTrims, - NumTrimSwitches + NumTrimSwitches, + HasRTC }; struct SwitchInfo @@ -149,6 +159,13 @@ namespace Board { unsigned int position; }; + enum SwitchTypeMasks { + SwitchTypeFlag2Pos = 0x01, + SwitchTypeFlag3Pos = 0x02, + SwitchTypeContext2Pos = SwitchTypeFlag2Pos, + SwitchTypeContext3Pos = SwitchTypeFlag2Pos | SwitchTypeFlag3Pos + }; + } class Boards @@ -182,6 +199,12 @@ class Boards static QString getAnalogInputName(Board::Type board, int index); static bool isBoardCompatible(Board::Type board1, Board::Type board2); static QString getBoardName(Board::Type board); + static QString potTypeToString(int value); + static QString sliderTypeToString(int value); + static QString switchTypeToString(int value); + static AbstractStaticItemModel * potTypeItemModel(); + static AbstractStaticItemModel * sliderTypeItemModel(); + static AbstractStaticItemModel * switchTypeItemModel(); protected: @@ -361,5 +384,3 @@ inline bool IS_ACCESS_RADIO(Board::Type board, const QString & id) return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == Board::BOARD_TARANIS_X9DP_2019 || board == Board::BOARD_X10_EXPRESS || IS_TARANIS_X7_ACCESS(board) || (IS_FAMILY_HORUS_OR_T16(board) && id.contains("internalaccess"))); } - -#endif // _BOARDS_H_ diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h index 6cd62f287..00980339c 100644 --- a/companion/src/firmwares/eeprominterface.h +++ b/companion/src/firmwares/eeprominterface.h @@ -134,7 +134,6 @@ enum Capability { VirtualInputs, InputsLength, TrainerInputs, - RtcTime, SportTelemetry, LuaScripts, LuaInputsPerScript, @@ -153,7 +152,13 @@ enum Capability { HasSwitchableJack, HasSportConnector, PwrButtonPress, - Sensors + Sensors, + HasAuxSerialMode, + HasAux2SerialMode, + HasBluetooth, + HasAntennaChoice, + HasADCJitterFilter, + HasTelemetryBaudrate }; class EEPROMInterface diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index f9df851b2..d1575d3e2 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -23,6 +23,7 @@ #include "appdata.h" #include "eeprominterface.h" #include "radiodataconversionstate.h" +#include "compounditemmodels.h" const uint8_t chout_ar[] = { // First number is 0..23 -> template setup, Second is relevant channel out 1,2,3,4 , 1,2,4,3 , 1,3,2,4 , 1,3,4,2 , 1,4,2,3 , 1,4,3,2, @@ -36,7 +37,7 @@ bool GeneralSettings::switchPositionAllowedTaranis(int index) const if (index == 0) return true; - div_t qr = div(abs(index)-1, 3); + div_t qr = div(abs(index) - 1, 3); if (index < 0 && switchConfig[qr.quot] != Board::SWITCH_3POS) return false; @@ -53,14 +54,14 @@ bool GeneralSettings::switchSourceAllowedTaranis(int index) const bool GeneralSettings::isPotAvailable(int index) const { - if (index < 0 || index > getBoardCapability(getCurrentBoard(), Board::Pots)) + if (index < 0 || index > Boards::getCapability(getCurrentBoard(), Board::Pots)) return false; return potConfig[index] != Board::POT_NONE; } bool GeneralSettings::isSliderAvailable(int index) const { - if (index < 0 || index > getBoardCapability(getCurrentBoard(), Board::Sliders)) + if (index < 0 || index > Boards::getCapability(getCurrentBoard(), Board::Sliders)) return false; return sliderConfig[index] != Board::SLIDER_NONE; } @@ -71,7 +72,7 @@ GeneralSettings::GeneralSettings() contrast = 25; - for (int i=0; i < CPN_MAX_ANALOGS; ++i) { + for (int i = 0; i < CPN_MAX_ANALOGS; ++i) { calibMid[i] = 0x200; calibSpanNeg[i] = 0x180; calibSpanPos[i] = 0x180; @@ -128,7 +129,7 @@ GeneralSettings::GeneralSettings() } for (uint8_t i = 0; i < 4; i++) { - trainer.mix[i].mode = 2; // replace (:=) + trainer.mix[i].mode = TrainerMix::TRN_MIX_MODE_SUBST; trainer.mix[i].src = i; trainer.mix[i].weight = 100; } @@ -387,3 +388,265 @@ void GeneralSettings::convert(RadioDataConversionState & cstate) } } + +QString GeneralSettings::antennaModeToString() const +{ + return antennaModeToString(antennaMode); +} + +QString GeneralSettings::bluetoothModeToString() const +{ + return bluetoothModeToString(bluetoothMode); +} + +QString GeneralSettings::auxSerialModeToString() const +{ + return auxSerialModeToString(auxSerialMode); +} + +QString GeneralSettings::telemetryBaudrateToString() const +{ + return telemetryBaudrateToString(telemetryBaudrate); +} + +// static +QString GeneralSettings::antennaModeToString(int value) +{ + Board::Type board = getCurrentBoard(); + + switch(value) { + case ANTENNA_MODE_INTERNAL: + return tr("Internal"); + case ANTENNA_MODE_ASK: + return tr("Ask"); + case ANTENNA_MODE_PER_MODEL: + return tr("Per model"); + case ANTENNA_MODE_EXTERNAL: + // case ANTENNA_MODE_INTERNAL_EXTERNAL: + return IS_HORUS_X12S(board) ? tr("Internal + External") : tr("External"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString GeneralSettings::bluetoothModeToString(int value) +{ + Board::Type board = getCurrentBoard(); + + switch(value) { + case BLUETOOTH_MODE_OFF: + return tr("OFF"); + case BLUETOOTH_MODE_ENABLED: + // case BLUETOOTH_MODE_TELEMETRY: + return IS_TARANIS_X9E(board) ? tr("Enabled") : tr("Telemetry"); + case BLUETOOTH_MODE_TRAINER: + return tr("Trainer"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString GeneralSettings::auxSerialModeToString(int value) +{ + switch(value) { + case AUX_SERIAL_OFF: + return tr("OFF"); + case AUX_SERIAL_TELE_MIRROR: + return tr("Telemetry Mirror"); + case AUX_SERIAL_TELE_IN: + return tr("Telemetry In"); + case AUX_SERIAL_SBUS_TRAINER: + return tr("SBUS Trainer"); + case AUX_SERIAL_LUA: + return tr("LUA"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString GeneralSettings::telemetryBaudrateToString(int value) +{ + switch(value) { + case 0: + return "400000"; + case 1: + return "115200"; + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +FieldRange GeneralSettings::getPPM_MultiplierRange() +{ + FieldRange result; + + result.min = 0; + result.max = 5; + result.decimals = 1; + result.step = 0.1; + result.offset = 10; + + return result; +} + +// static +FieldRange GeneralSettings::getTxVoltageCalibrationRange() +{ + FieldRange result; + + result.decimals = 1; + result.max = 9.9; + result.min = -result.max; + result.step = 0.1; + result.unit = tr("v"); + + return result; +} + +// static +FieldRange GeneralSettings::getTxCurrentCalibration() +{ + FieldRange result; + + result.max = 49; + result.min = -result.max; + result.unit = tr("mA"); + + return result; +} + +// static +AbstractStaticItemModel * GeneralSettings::antennaModeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GS_ANTENNAMODE); + + for (int i = ANTENNA_MODE_FIRST; i <= ANTENNA_MODE_LAST; i++) { + mdl->appendToItemList(antennaModeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * GeneralSettings::bluetoothModeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GS_BLUETOOTHMODE); + + for (int i = 0; i < BLUETOOTH_MODE_COUNT; i++) { + mdl->appendToItemList(bluetoothModeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * GeneralSettings::auxSerialModeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GS_AUXSERIALMODE); + + for (int i = 0; i < AUX_SERIAL_COUNT; i++) { + mdl->appendToItemList(auxSerialModeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * GeneralSettings::telemetryBaudrateItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_GS_TELEMETRYBAUDRATE); + + for (int i = 0; i <= 1; i++) { + mdl->appendToItemList(telemetryBaudrateToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +/* + TrainerMix +*/ + +QString TrainerMix::modeToString() const +{ + return modeToString(mode); +} + +QString TrainerMix::srcToString() const +{ + return srcToString(src); +} + +// static +FieldRange TrainerMix::getWeightRange() +{ + FieldRange result; + + result.decimals = 0; + result.max = 125; + result.min = -result.max; + result.step = 1; + + return result; +} + +// static +QString TrainerMix::modeToString(int value) +{ + switch(value) { + case TRN_MIX_MODE_OFF: + return tr("OFF"); + case TRN_MIX_MODE_ADD: + return tr("+= (Sum)"); + case TRN_MIX_MODE_SUBST: + return tr(":= (Replace)"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString TrainerMix::srcToString(int value) +{ + return tr("CH%1").arg(value + 1); +} + +// static +AbstractStaticItemModel * TrainerMix::modeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_TRAINERMIX_MODE); + + for (int i = 0; i < TRN_MIX_MODE_COUNT; i++) { + mdl->appendToItemList(modeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * TrainerMix::srcItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName(AIM_TRAINERMIX_SRC); + + for (int i = 0; i < Boards::getCapability(getCurrentBoard(), Board::Sticks); i++) { + mdl->appendToItemList(srcToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index f7b28931d..466d630af 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -18,13 +18,13 @@ * GNU General Public License for more details. */ -#ifndef GENERALSETTINGS_H -#define GENERALSETTINGS_H +#pragma once #include "boards.h" #include "constants.h" #include "customfunctiondata.h" #include "rawsource.h" +#include "datahelpers.h" #include @@ -32,6 +32,15 @@ class Firmware; class ModelData; class GeneralSettings; class RadioDataConversionState; +class AbstractStaticItemModel; + +// identiying names of static abstract item models +constexpr char AIM_GS_ANTENNAMODE[] {"gs.antennamode"}; +constexpr char AIM_GS_BLUETOOTHMODE[] {"gs.bluetoothmode"}; +constexpr char AIM_GS_AUXSERIALMODE[] {"gs.auxserialmode"}; +constexpr char AIM_GS_TELEMETRYBAUDRATE[] {"gs.telemetrybaudrate"}; +constexpr char AIM_TRAINERMIX_MODE[] {"trainermix.mode"}; +constexpr char AIM_TRAINERMIX_SRC[] {"trainermix.src"}; enum UartModes { UART_MODE_NONE, @@ -42,23 +51,52 @@ enum UartModes { }; class TrainerMix { + Q_DECLARE_TR_FUNCTIONS(TrainerMix) + public: + enum TrainerMixModes { + TRN_MIX_MODE_OFF, + TRN_MIX_MODE_ADD, + TRN_MIX_MODE_SUBST, + TRN_MIX_MODE_COUNT + }; + TrainerMix() { clear(); } + unsigned int src; // 0-7 = ch1-8 RawSwitch swtch; int weight; unsigned int mode; // off, add-mode, subst-mode + void clear() { memset(reinterpret_cast(this), 0, sizeof(TrainerMix)); } + QString modeToString() const; + QString srcToString() const; + + static FieldRange getWeightRange(); + static QString modeToString(int value); + static QString srcToString(int value); + static AbstractStaticItemModel * modeItemModel(); + static AbstractStaticItemModel * srcItemModel(); }; class TrainerData { public: TrainerData() { clear(); } - int calib[4]; - TrainerMix mix[4]; + + int calib[4]; + TrainerMix mix[4]; + void clear() { memset(reinterpret_cast(this), 0, sizeof(TrainerData)); } }; +constexpr int CURR_MODEL_FILENAME_LEN {16}; +constexpr int OWNER_NAME_LEN {10}; +constexpr int BLUETOOTH_NAME_LEN {10}; +constexpr int TTS_LANGUAGE_LEN {2}; +constexpr int HARDWARE_NAME_LEN {3}; +constexpr int THEME_NAME_LEN {8}; +constexpr int REGISTRATION_ID_LEN {8}; + class GeneralSettings { Q_DECLARE_TR_FUNCTIONS(GeneralSettings) @@ -71,6 +109,36 @@ class GeneralSettings { BEEPER_ALL = 1 }; + enum BluetoothMode { + BLUETOOTH_MODE_OFF, + BLUETOOTH_MODE_ENABLED, + BLUETOOTH_MODE_TELEMETRY = BLUETOOTH_MODE_ENABLED, + BLUETOOTH_MODE_TRAINER, + BLUETOOTH_MODE_COUNT + }; + + enum AntennaMode { + ANTENNA_MODE_INTERNAL = -2, + ANTENNA_MODE_FIRST = ANTENNA_MODE_INTERNAL, + ANTENNA_MODE_ASK, + ANTENNA_MODE_PER_MODEL, + ANTENNA_MODE_EXTERNAL, + ANTENNA_MODE_INTERNAL_EXTERNAL = ANTENNA_MODE_EXTERNAL, + ANTENNA_MODE_LAST = ANTENNA_MODE_INTERNAL_EXTERNAL + }; + + enum AuxSerialMode { + AUX_SERIAL_OFF, + AUX_SERIAL_TELE_MIRROR, + AUX_SERIAL_TELE_IN, + AUX_SERIAL_SBUS_TRAINER, + AUX_SERIAL_LUA, + AUX_SERIAL_COUNT + }; + + enum TelemetryBaudrate { + }; + GeneralSettings(); void convert(RadioDataConversionState & cstate); @@ -81,61 +149,61 @@ class GeneralSettings { unsigned int version; unsigned int variant; - int calibMid[CPN_MAX_ANALOGS]; - int calibSpanNeg[CPN_MAX_ANALOGS]; - int calibSpanPos[CPN_MAX_ANALOGS]; - unsigned int currModelIndex; - char currModelFilename[16+1]; - unsigned int contrast; - unsigned int vBatWarn; - int txVoltageCalibration; - int txCurrentCalibration; - int vBatMin; - int vBatMax; - int backlightMode; + int calibMid[CPN_MAX_ANALOGS]; + int calibSpanNeg[CPN_MAX_ANALOGS]; + int calibSpanPos[CPN_MAX_ANALOGS]; + unsigned int currModelIndex; + char currModelFilename[CURR_MODEL_FILENAME_LEN + 1]; + unsigned int contrast; + unsigned int vBatWarn; + int txVoltageCalibration; + int txCurrentCalibration; + int vBatMin; + int vBatMax; + int backlightMode; TrainerData trainer; - unsigned int view; // main screen view // TODO enum - bool disableThrottleWarning; - bool fai; - bool disableMemoryWarning; + unsigned int view; // main screen view // TODO enum + bool disableThrottleWarning; + bool fai; + bool disableMemoryWarning; BeeperMode beeperMode; - bool disableAlarmWarning; - bool disableRssiPoweroffAlarm; - unsigned int usbMode; - unsigned int jackMode; - bool sportPower; + bool disableAlarmWarning; + bool disableRssiPoweroffAlarm; + unsigned int usbMode; + unsigned int jackMode; + bool sportPower; BeeperMode hapticMode; - unsigned int stickMode; // TODO enum - int timezone; - bool adjustRTC; - bool optrexDisplay; - unsigned int inactivityTimer; - unsigned int telemetryBaudrate; - bool minuteBeep; - bool preBeep; - bool flashBeep; - unsigned int splashMode; + unsigned int stickMode; // TODO enum + int timezone; + bool adjustRTC; + bool optrexDisplay; + unsigned int inactivityTimer; + unsigned int telemetryBaudrate; + bool minuteBeep; + bool preBeep; + bool flashBeep; + unsigned int splashMode; int splashDuration; - unsigned int backlightDelay; - unsigned int templateSetup; //RETA order according to chout_ar array - int PPM_Multiplier; - int hapticLength; - unsigned int reNavigation; + unsigned int backlightDelay; + unsigned int templateSetup; //RETA order according to chout_ar array + int PPM_Multiplier; + int hapticLength; + unsigned int reNavigation; unsigned int stickReverse; - unsigned int speakerPitch; - int hapticStrength; - unsigned int speakerMode; - char ownerName[10+1]; - int beeperLength; - unsigned int gpsFormat; - int speakerVolume; - unsigned int backlightBright; - unsigned int backlightOffBright; + unsigned int speakerPitch; + int hapticStrength; + unsigned int speakerMode; + char ownerName[OWNER_NAME_LEN + 1]; + int beeperLength; + unsigned int gpsFormat; + int speakerVolume; + unsigned int backlightBright; + unsigned int backlightOffBright; int switchesDelay; unsigned int mAhWarn; unsigned int mAhUsed; unsigned int globalTimer; - char bluetoothName[10+1]; + char bluetoothName[BLUETOOTH_NAME_LEN + 1]; unsigned int bluetoothBaudrate; unsigned int bluetoothMode; unsigned int sticksGain; @@ -145,7 +213,7 @@ class GeneralSettings { bool rtcCheckDisable; bool keysBacklight; unsigned int imperial; - char ttsLanguage[2+1]; + char ttsLanguage[TTS_LANGUAGE_LEN + 1]; int beepVolume; int wavVolume; int varioVolume; @@ -156,33 +224,47 @@ class GeneralSettings { unsigned int mavbaud; unsigned int switchUnlockStates; unsigned int auxSerialMode; + unsigned int aux2SerialMode; int antennaMode; unsigned int backlightColor; CustomFunctionData customFn[CPN_MAX_SPECIAL_FUNCTIONS]; - char switchName[CPN_MAX_SWITCHES][3+1]; + char switchName[CPN_MAX_SWITCHES][HARDWARE_NAME_LEN + 1]; unsigned int switchConfig[CPN_MAX_SWITCHES]; - char stickName[CPN_MAX_STICKS][3+1]; - char potName[CPN_MAX_KNOBS][3+1]; + char stickName[CPN_MAX_STICKS][HARDWARE_NAME_LEN + 1]; + char potName[CPN_MAX_KNOBS][HARDWARE_NAME_LEN + 1]; unsigned int potConfig[CPN_MAX_KNOBS]; - char sliderName[CPN_MAX_SLIDERS][3+1]; + char sliderName[CPN_MAX_SLIDERS][HARDWARE_NAME_LEN + 1]; unsigned int sliderConfig[CPN_MAX_SLIDERS]; - char themeName[8+1]; - typedef uint8_t ThemeOptionData[8+1]; + char themeName[THEME_NAME_LEN + 1]; + typedef uint8_t ThemeOptionData[8 + 1]; ThemeOptionData themeOptionValue[5]; - - char registrationId[8+1]; + + char registrationId[REGISTRATION_ID_LEN + 1]; int gyroMax; int gyroOffset; int pwrOnSpeed; int pwrOffSpeed; - + bool switchPositionAllowedTaranis(int index) const; bool switchSourceAllowedTaranis(int index) const; bool isPotAvailable(int index) const; bool isSliderAvailable(int index) const; + QString antennaModeToString() const; + QString bluetoothModeToString() const; + QString auxSerialModeToString() const; + QString telemetryBaudrateToString() const; + + static QString antennaModeToString(int value); + static QString bluetoothModeToString(int value); + static QString auxSerialModeToString(int value); + static QString telemetryBaudrateToString(int value); + static FieldRange getPPM_MultiplierRange(); + static FieldRange getTxVoltageCalibrationRange(); + static FieldRange getTxCurrentCalibration(); + static AbstractStaticItemModel * antennaModeItemModel(); + static AbstractStaticItemModel * bluetoothModeItemModel(); + static AbstractStaticItemModel * auxSerialModeItemModel(); + static AbstractStaticItemModel * telemetryBaudrateItemModel(); }; - - -#endif // GENERALSETTINGS_H diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index f9fc8c8f5..0304bc72d 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2759,7 +2759,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type if (version >= 218) { internalField.Append(new UnsignedField<4>(this, generalData.auxSerialMode)); if (IS_FAMILY_HORUS_OR_T16(board) && version >= 219) { - internalField.Append(new SpareBitsField<4>(this)); + internalField.Append(new UnsignedField<4>(this, generalData.aux2SerialMode)); } else { for (uint8_t i=0; i -#include -#include #include "calibration.h" - +#include "autospinbox.h" +#include "helpers.h" CalibrationPanel::CalibrationPanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware): GeneralPanel(parent, generalSettings, firmware) { + int rows = Boards::getCapability(getCurrentBoard(), Board::MaxAnalogs); - tableWidget = new QTableWidget(); - QVBoxLayout * layout = new QVBoxLayout(); - layout->addWidget(tableWidget); - layout->setContentsMargins(0, 0, 0, 0); - this->setLayout(layout); - - tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); - tableWidget->setColumnCount(3); - tableWidget->setShowGrid(false); - tableWidget->setSelectionMode(QAbstractItemView::NoSelection); - tableWidget->setFrameStyle(QFrame::NoFrame | QFrame::Plain); - tableWidget->setStyleSheet("QTableWidget {background-color: transparent;}"); QStringList headerLabels; - headerLabels << tr("Negative span") << tr("Mid value") << tr("Positive span"); - tableWidget->setHorizontalHeaderLabels(headerLabels); + headerLabels << "" << tr("Negative span") << tr("Mid value") << tr("Positive span"); - int rows = getBoardCapability(getCurrentBoard(), Board::MaxAnalogs); - tableWidget->setRowCount(rows); + TableLayout * tableLayout = new TableLayout(this, rows, headerLabels); - for(int i = 0; i < rows; ++i) { + for (int i = 0; i < rows; i++) { + int col = 0; + QLabel * label = new QLabel(this); + label->setText(firmware->getAnalogInputName(i)); + tableLayout->addWidget(i, col++, label); - QTableWidgetItem *newItem = new QTableWidgetItem(firmware->getAnalogInputName(i)); - newItem->setTextAlignment(Qt::AlignLeft); - tableWidget->setVerticalHeaderItem(i, newItem); + QLineEdit * leNeg = new QLineEdit(this); + leNeg->setText(QString("%1").arg(generalSettings.calibSpanNeg[i])); + leNeg->setReadOnly(true); + tableLayout->addWidget(i, col++, leNeg); - for(int j = 0; j < 3; ++j) { - QSpinBox * newItem = new QSpinBox(); - newItem->setMinimum(-9999); - newItem->setMaximum(9999); - newItem->setSingleStep(1); - newItem->setValue(getCalibrationValue(i, j)); - newItem->setProperty("row", i); - newItem->setProperty("column", j); - tableWidget->setCellWidget(i, j, newItem); - connect(newItem, SIGNAL(valueChanged(int)), this, SLOT(onCellChanged(int))); - } + QLineEdit * leMid = new QLineEdit(this); + leMid->setText(QString("%1").arg(generalSettings.calibMid[i])); + leMid->setReadOnly(true); + tableLayout->addWidget(i, col++, leMid); + + QLineEdit * lePos = new QLineEdit(this); + lePos->setText(QString("%1").arg(generalSettings.calibSpanPos[i])); + lePos->setReadOnly(true); + tableLayout->addWidget(i, col++, lePos); } + disableMouseScrolling(); -} - -void CalibrationPanel::onCellChanged(int value) -{ - QSpinBox * sb = qobject_cast(sender()); - int row = sb->property("row").toInt(); - int column = sb->property("column").toInt(); - - if (value != getCalibrationValue(row, column)) { - setCalibrationValue(row,column, value); - qDebug() << "CalibrationPanel::onCellChanged" << row << column << "to" << value; - emit modified(); - } -} - -int CalibrationPanel::getCalibrationValue(int row, int column) -{ - switch(column) { - case 0: - return generalSettings.calibSpanNeg[row]; - case 1: - return generalSettings.calibMid[row]; - case 2: - return generalSettings.calibSpanPos[row]; - } - return 0; -} - -void CalibrationPanel::setCalibrationValue(int row, int column, int value) -{ - switch(column) { - case 0: - generalSettings.calibSpanNeg[row] = value; - break; - case 1: - generalSettings.calibMid[row] = value; - break; - case 2: - generalSettings.calibSpanPos[row] = value; - break; - } + tableLayout->resizeColumnsToContents(); + tableLayout->setColumnWidth(0, QString(15, ' ')); + tableLayout->pushColumnsLeft(headerLabels.count()); + tableLayout->pushRowsUp(rows + 1); } diff --git a/companion/src/generaledit/calibration.h b/companion/src/generaledit/calibration.h index fd28e492b..279b7cf80 100644 --- a/companion/src/generaledit/calibration.h +++ b/companion/src/generaledit/calibration.h @@ -18,20 +18,10 @@ * GNU General Public License for more details. */ -#ifndef _CALIBRATION_H_ -#define _CALIBRATION_H_ +#pragma once -#include #include "generaledit.h" -namespace Ui { - class Calibration; -} - -class QLabel; -class AutoLineEdit; -class AutoComboBox; - class CalibrationPanel : public GeneralPanel { Q_OBJECT @@ -40,14 +30,5 @@ class CalibrationPanel : public GeneralPanel CalibrationPanel(QWidget *parent, GeneralSettings & generalSettings, Firmware * firmware); virtual ~CalibrationPanel() {}; - private slots: - void onCellChanged(int value); - private: - QTableWidget * tableWidget; - - int getCalibrationValue(int row, int column); - void setCalibrationValue(int row, int column, int value); }; - -#endif // _CALIBRATION_H_ diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp index e80038f9f..99884ed43 100644 --- a/companion/src/generaledit/generaledit.cpp +++ b/companion/src/generaledit/generaledit.cpp @@ -46,26 +46,27 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir } ui->profile_CB->clear(); - for (int i=0; iprofile_CB->addItem(name, i); - if (i==g.id()) { - ui->profile_CB->setCurrentIndex(ui->profile_CB->count()-1); + if (i == g.id()) { + ui->profile_CB->setCurrentIndex(ui->profile_CB->count() - 1); } } } - sharedItemModels = new CompoundItemModelFactory(&generalSettings, nullptr); - sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource); - sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch); - sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction); - sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam); + editorItemModels = new CompoundItemModelFactory(&generalSettings, nullptr); + // tabs created below expect these item models to be pre-registered + editorItemModels->addItemModel(AbstractItemModel::IMID_RawSource); + editorItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch); + editorItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction); + editorItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam); addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); - addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, sharedItemModels), tr("Global Functions")); - addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer")); - addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware")); + addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, editorItemModels), tr("Global Functions")); + addTab(new TrainerPanel(this, generalSettings, firmware, editorItemModels), tr("Trainer")); + addTab(new HardwarePanel(this, generalSettings, firmware, editorItemModels), tr("Hardware")); addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration")); ui->tabWidget->setCurrentIndex( g.generalEditTab() ); @@ -74,7 +75,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir GeneralEdit::~GeneralEdit() { delete ui; - delete sharedItemModels; + delete editorItemModels; // cleans up item models registered by the tabs } void GeneralEdit::closeEvent(QCloseEvent *event) @@ -90,7 +91,7 @@ void GeneralEdit::addTab(GenericPanel *panel, QString text) VerticalScrollArea * area = new VerticalScrollArea(widget, panel); baseLayout->addWidget(area); ui->tabWidget->addTab(widget, text); - connect(panel, SIGNAL(modified()), this, SLOT(onTabModified())); + connect(panel, &GenericPanel::modified, this, &GeneralEdit::onTabModified); } void GeneralEdit::onTabModified() diff --git a/companion/src/generaledit/generaledit.h b/companion/src/generaledit/generaledit.h index b2e6caa82..2ad27cb1c 100644 --- a/companion/src/generaledit/generaledit.h +++ b/companion/src/generaledit/generaledit.h @@ -18,8 +18,7 @@ * GNU General Public License for more details. */ -#ifndef _GENERALEDIT_H_ -#define _GENERALEDIT_H_ +#pragma once #include #include "eeprominterface.h" @@ -35,7 +34,7 @@ class GeneralPanel : public GenericPanel { public: GeneralPanel(QWidget *parent, GeneralSettings & generalSettings, Firmware * firmware): - GenericPanel(parent, NULL, generalSettings, firmware) + GenericPanel(parent, nullptr, generalSettings, firmware) { } }; @@ -73,7 +72,5 @@ class GeneralEdit : public QDialog QVector panels; void addTab(GenericPanel *panel, QString text); void closeEvent(QCloseEvent *event); - CompoundItemModelFactory *sharedItemModels; + CompoundItemModelFactory *editorItemModels; }; - -#endif // _GENERALEDIT_H_ diff --git a/companion/src/generaledit/hardware.cpp b/companion/src/generaledit/hardware.cpp index 9d2e8e452..4f7e52a7a 100644 --- a/companion/src/generaledit/hardware.cpp +++ b/companion/src/generaledit/hardware.cpp @@ -19,326 +19,268 @@ */ #include "hardware.h" -#include "ui_hardware.h" +#include "compounditemmodels.h" +#include "filtereditemmodels.h" +#include "autolineedit.h" +#include "autocombobox.h" +#include "autocheckbox.h" +#include "autospinbox.h" +#include "autodoublespinbox.h" -void HardwarePanel::setupSwitchType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type, bool threePos) -{ - Board::Type board = getCurrentBoard(); - if (IS_STM32(board) && index < getBoardCapability(board, Board::Switches)) { - type->addItem(tr("None"), Board::SWITCH_NOT_AVAILABLE); - type->addItem(tr("2 Positions Toggle"), Board::SWITCH_TOGGLE); - type->addItem(tr("2 Positions"), Board::SWITCH_2POS); - if (threePos) { - type->addItem(tr("3 Positions"), Board::SWITCH_3POS); - } - name->setField(generalSettings.switchName[index], 3, this); - type->setField(generalSettings.switchConfig[index], this); - if (IS_TARANIS_X7(board)) { - if (index == 4) { - label->setText("SF"); - } - else if (index == 5) { - label->setText("SH"); - } - if (index == 6) { - label->setText("SI"); - } - else if (index == 7) { - label->setText("SJ"); - } - } - else if (IS_RADIOMASTER_TX12(board)) { - if (index == 6) { - label->setText("SI"); - } - else if (index == 7) { - label->setText("SJ"); - } - } - else if (IS_FAMILY_T12(board)) { - if (index == 4) { - label->setText("SG"); - } - else if (index == 5) { - label->setText("SH"); - } - } - } - else { - label->hide(); - name->hide(); - type->hide(); - } -} +#include +#include +#include -void HardwarePanel::setupPotType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type) -{ - Board::Type board = firmware->getBoard(); +constexpr char FIM_SWITCHTYPE2POS[] {"Switch Type 2 Pos"}; +constexpr char FIM_SWITCHTYPE3POS[] {"Switch Type 3 Pos"}; - if (IS_STM32(board) && index < getBoardCapability(board, Board::Pots)) { - label->setText(RawSource(SOURCE_TYPE_STICK, CPN_MAX_STICKS+index).toString()); - type->addItem(tr("None"), Board::POT_NONE); - type->addItem(tr("Pot with detent"), Board::POT_WITH_DETENT); - type->addItem(tr("Multipos switch"), Board::POT_MULTIPOS_SWITCH); - type->addItem(tr("Pot without detent"), Board::POT_WITHOUT_DETENT); - name->setField(generalSettings.potName[index], 3, this); - type->setField(generalSettings.potConfig[index], this); - } - else { - label->hide(); - name->hide(); - type->hide(); - } -} - -void HardwarePanel::setupSliderType(int index, QLabel *label, AutoLineEdit *name, AutoComboBox *type) -{ - Board::Type board = firmware->getBoard(); - - if (IS_STM32(board) && index < getBoardCapability(board, Board::Sliders)) { - label->setText(RawSource(SOURCE_TYPE_STICK, CPN_MAX_STICKS+getBoardCapability(board, Board::Pots)+index).toString()); - type->addItem(tr("None"), Board::SLIDER_NONE); - type->addItem(tr("Slider with detent"), Board::SLIDER_WITH_DETENT); - name->setField(generalSettings.sliderName[index], 3, this); - type->setField(generalSettings.sliderConfig[index], this); - } - else { - label->hide(); - name->hide(); - type->hide(); - } -} - -bool HardwarePanel::isSwitch3Pos(int idx) -{ - Board::Type board = firmware->getBoard(); - Board::SwitchInfo switchInfo = Boards::getSwitchInfo(board, idx); - - switchInfo.config = Board::SwitchType(generalSettings.switchConfig[idx]); - return switchInfo.config == Board::SWITCH_3POS; -}; - -HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware): +HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): GeneralPanel(parent, generalSettings, firmware), - ui(new Ui::Hardware) + board(firmware->getBoard()), + editorItemModels(sharedItemModels) { - ui->setupUi(this); + editorItemModels->registerItemModel(Boards::potTypeItemModel()); + editorItemModels->registerItemModel(Boards::sliderTypeItemModel()); + int id = editorItemModels->registerItemModel(Boards::switchTypeItemModel()); - Board::Type board = firmware->getBoard(); + tabFilteredModels = new FilteredItemModelFactory(); + tabFilteredModels->registerItemModel(new FilteredItemModel(editorItemModels->getItemModel(id), Board::SwitchTypeContext2Pos), FIM_SWITCHTYPE2POS); + tabFilteredModels->registerItemModel(new FilteredItemModel(editorItemModels->getItemModel(id), Board::SwitchTypeContext3Pos), FIM_SWITCHTYPE3POS); - if (IS_STM32(board)) { - ui->rudName->setField(generalSettings.stickName[0], 3, this); - ui->eleName->setField(generalSettings.stickName[1], 3, this); - ui->thrName->setField(generalSettings.stickName[2], 3, this); - ui->ailName->setField(generalSettings.stickName[3], 3, this); + int antmodelid = editorItemModels->registerItemModel(GeneralSettings::antennaModeItemModel()); + int btmodelid = editorItemModels->registerItemModel(GeneralSettings::bluetoothModeItemModel()); + int auxmodelid = editorItemModels->registerItemModel(GeneralSettings::auxSerialModeItemModel()); + int baudmodelid = editorItemModels->registerItemModel(GeneralSettings::telemetryBaudrateItemModel()); + + grid = new QGridLayout(this); + int count; + int row = 0; + + count = Boards::getCapability(board, Board::Sticks); + if (count) { + for (int i = 0; i < count; i++) { + addStick(i, row); + } } - else { - ui->rudLabel->hide(); - ui->rudName->hide(); - ui->eleLabel->hide(); - ui->eleName->hide(); - ui->thrLabel->hide(); - ui->thrName->hide(); - ui->ailLabel->hide(); - ui->ailName->hide(); - ui->potsTypeSeparator_1->hide(); - ui->potsTypeSeparator_2->hide(); + + count = Boards::getCapability(board, Board::Pots); + if (count) { + for (int i = 0; i < count; i++) { + addPot(i, row); + } } - + + count = Boards::getCapability(board, Board::Sliders); + if (count) { + for (int i = 0; i < count; i++) { + addSlider(i, row); + } + addLine(row); + } + + count = Boards::getCapability(board, Board::Switches); + if (count) { + for (int i = 0; i < count; i++) { + addSwitch(i, row); + } + addLine(row); + } + + addLabel(tr("Battery Offset"), row, 0); + AutoDoubleSpinBox *txVoltageCalibration = new AutoDoubleSpinBox(this); + FieldRange txVCRng = GeneralSettings::getTxVoltageCalibrationRange(); + txVoltageCalibration->setDecimals(txVCRng.decimals); + txVoltageCalibration->setSingleStep(txVCRng.step); + txVoltageCalibration->setSuffix(txVCRng.unit); + txVoltageCalibration->setField(generalSettings.txVoltageCalibration); + addParams(row, txVoltageCalibration); + + if (Boards::getCapability(board, Board::HasRTC)) { + addLabel(tr("RTC Battery Check"), row, 0); + AutoCheckBox *rtcCheckDisable = new AutoCheckBox(this); + rtcCheckDisable->setField(generalSettings.rtcCheckDisable, this, true); + addParams(row, rtcCheckDisable); + } + + if (firmware->getCapability(HasBluetooth)) { + addLabel(tr("Bluetooth"), row, 0); + + QGridLayout *btlayout = new QGridLayout(); + + AutoComboBox *bluetoothMode = new AutoComboBox(this); + bluetoothMode->setModel(editorItemModels->getItemModel(btmodelid)); + bluetoothMode->setField(generalSettings.bluetoothMode, this); + btlayout->addWidget(bluetoothMode, 0, 0); + + QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum ); + btlayout->addItem(spacer, 0, 1); + + QLabel *btnamelabel = new QLabel(this); + btnamelabel->setText(tr("Device Name:")); + btlayout->addWidget(btnamelabel, 0, 2); + + AutoLineEdit *bluetoothName = new AutoLineEdit(this); + bluetoothName->setField(generalSettings.bluetoothName, BLUETOOTH_NAME_LEN, this); + btlayout->addWidget(bluetoothName, 0, 3); + + grid->addLayout(btlayout, row, 1); + row++; + } + + if (firmware->getCapability(HasAntennaChoice)) { + addLabel(tr("Antenna"), row, 0); + AutoComboBox *antennaMode = new AutoComboBox(this); + antennaMode->setModel(editorItemModels->getItemModel(antmodelid)); + antennaMode->setField(generalSettings.antennaMode, this); + addParams(row, antennaMode); + } + + if (firmware->getCapability(HasAuxSerialMode)) { + QString lbl = "Serial Port"; + if (IS_RADIOMASTER_TX16S(board)) + lbl.append(" (TTL)"); + addLabel(tr("%1").arg(lbl), row, 0); + AutoComboBox *serialPortMode = new AutoComboBox(this); + serialPortMode->setModel(editorItemModels->getItemModel(auxmodelid)); + serialPortMode->setField(generalSettings.auxSerialMode); + addParams(row, serialPortMode); + } + + if (firmware->getCapability(HasAux2SerialMode)) { + QString lbl = "Serial Port 2"; + if (IS_RADIOMASTER_TX16S(board)) + lbl.append(" (TTL)"); + addLabel(tr("%1").arg(lbl), row, 0); + AutoComboBox *serialPort2Mode = new AutoComboBox(this); + serialPort2Mode->setModel(editorItemModels->getItemModel(auxmodelid)); + serialPort2Mode->setField(generalSettings.aux2SerialMode); + addParams(row, serialPort2Mode); + } + + if (firmware->getCapability(HasADCJitterFilter)) { + addLabel(tr("ADC Filter"), row, 0); + AutoCheckBox *filterEnable = new AutoCheckBox(this); + filterEnable->setField(generalSettings.jitterFilter, this, true); + addParams(row, filterEnable); + } + if (firmware->getCapability(HasSportConnector)) { - ui->sportPower->setChecked(generalSettings.sportPower); - } - else { - ui->sportPower->hide(); - ui->sportPowerLabel->hide(); + addLabel(tr("S.Port Power"), row, 0); + AutoCheckBox *sportPower = new AutoCheckBox(this); + sportPower->setField(generalSettings.sportPower, this); + addParams(row, sportPower); } - setupPotType(0, ui->pot1Label, ui->pot1Name, ui->pot1Type); - setupPotType(1, ui->pot2Label, ui->pot2Name, ui->pot2Type); - setupPotType(2, ui->pot3Label, ui->pot3Name, ui->pot3Type); - setupPotType(3, ui->pot4Label, ui->pot4Name, ui->pot4Type); - setupPotType(4, ui->pot5Label, ui->pot5Name, ui->pot5Type); - - setupSliderType(0, ui->lsLabel, ui->lsName, ui->lsType); - setupSliderType(1, ui->rsLabel, ui->rsName, ui->rsType); - setupSliderType(2, ui->ls2Label, ui->ls2Name, ui->ls2Type); - setupSliderType(3, ui->rs2Label, ui->rs2Name, ui->rs2Type); - - setupSwitchType(0, ui->saLabel, ui->saName, ui->saType, isSwitch3Pos(0)); - setupSwitchType(1, ui->sbLabel, ui->sbName, ui->sbType, isSwitch3Pos(1)); - setupSwitchType(2, ui->scLabel, ui->scName, ui->scType, isSwitch3Pos(2)); - setupSwitchType(3, ui->sdLabel, ui->sdName, ui->sdType, isSwitch3Pos(3)); - setupSwitchType(4, ui->seLabel, ui->seName, ui->seType, isSwitch3Pos(4)); - setupSwitchType(5, ui->sfLabel, ui->sfName, ui->sfType, isSwitch3Pos(5)); - setupSwitchType(6, ui->sgLabel, ui->sgName, ui->sgType, isSwitch3Pos(6)); - setupSwitchType(7, ui->shLabel, ui->shName, ui->shType, isSwitch3Pos(7)); - setupSwitchType(8, ui->siLabel, ui->siName, ui->siType, isSwitch3Pos(8)); - setupSwitchType(9, ui->sjLabel, ui->sjName, ui->sjType, isSwitch3Pos(9)); - setupSwitchType(10, ui->skLabel, ui->skName, ui->skType); // Here starts X9E, only 3 switches - setupSwitchType(11, ui->slLabel, ui->slName, ui->slType); - setupSwitchType(12, ui->smLabel, ui->smName, ui->smType); - setupSwitchType(13, ui->snLabel, ui->snName, ui->snType); - setupSwitchType(14, ui->soLabel, ui->soName, ui->soType); - setupSwitchType(15, ui->spLabel, ui->spName, ui->spType); - setupSwitchType(16, ui->sqLabel, ui->sqName, ui->sqType); - setupSwitchType(17, ui->srLabel, ui->srName, ui->srType); - - if (IS_TARANIS(board) && !IS_TARANIS_SMALL(board)) { - ui->serialPortMode->setCurrentIndex(generalSettings.auxSerialMode); - } - else { - ui->serialPortMode->setCurrentIndex(0); - ui->serialPortMode->hide(); - ui->serialPortLabel->hide(); + if (firmware->getCapability(HasTelemetryBaudrate)) { + addLabel(tr("Maximum Baud"), row, 0); + AutoComboBox *maxBaudRate = new AutoComboBox(this); + maxBaudRate->setModel(editorItemModels->getItemModel(baudmodelid)); + maxBaudRate->setField(generalSettings.telemetryBaudrate, this); + addParams(row, maxBaudRate); } - if (!IS_SKY9X(board)) { - ui->txCurrentCalibration->hide(); - ui->txCurrentCalibrationLabel->hide(); - } - - if (IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board)|| IS_TARANIS_X9E(board) || IS_TARANIS_X9DP_2019(board) || IS_FAMILY_HORUS_OR_T16(board)) { - ui->bluetoothMode->addItem(tr("OFF"), 0); - if (IS_TARANIS_X9E(board)) { - ui->bluetoothMode->addItem(tr("Enabled"), 1); - } - else { - ui->bluetoothMode->addItem(tr("Telemetry"), 1); - ui->bluetoothMode->addItem(tr("Trainer"), 2); - } - ui->bluetoothMode->setField(generalSettings.bluetoothMode, this); - ui->bluetoothName->setField(generalSettings.bluetoothName, 10, this); - } - else { - ui->bluetoothLabel->hide(); - ui->bluetoothWidget->hide(); - } - - if ((IS_FAMILY_HORUS_OR_T16(board) && board != Board::BOARD_X10_EXPRESS) || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))) { - ui->antennaMode->addItem(tr("Internal"), -2); - ui->antennaMode->addItem(tr("Ask"), -1); - ui->antennaMode->addItem(tr("Per model"), 0); - ui->antennaMode->addItem(IS_HORUS_X12S(board) ? tr("Internal + External") : tr("External"), 1); - ui->antennaMode->setField(generalSettings.antennaMode, this); - } - else { - ui->antennaLabel->hide(); - ui->antennaMode->hide(); - } - - if (IS_HORUS_OR_TARANIS(board)) { - ui->filterEnable->setChecked(!generalSettings.jitterFilter); - } - else { - ui->filterEnable->hide(); - ui->filterLabel->hide(); - } - - if (IS_STM32(board)) { - ui->rtcCheckDisable->setChecked(!generalSettings.rtcCheckDisable); - } - else { - ui->rtcCheckDisable->hide(); - ui->rtcCheckLabel->hide(); + if (firmware->getCapability(HastxCurrentCalibration)) { + addLabel(tr("Current Offset"), row, 0); + AutoSpinBox *txCurrentCalibration = new AutoSpinBox(this); + FieldRange txCCRng = GeneralSettings::getTxCurrentCalibration(); + txCurrentCalibration->setSuffix(txVCRng.unit); + txCurrentCalibration->setField(generalSettings.txCurrentCalibration); + addParams(row, txCurrentCalibration); } + addVSpring(grid, 0, grid->rowCount()); + addHSpring(grid, grid->columnCount(), 0); disableMouseScrolling(); - - setValues(); } HardwarePanel::~HardwarePanel() { - delete ui; + delete tabFilteredModels; } -void HardwarePanel::on_filterEnable_stateChanged() +void HardwarePanel::addStick(int index, int & row) { - generalSettings.jitterFilter = !ui->filterEnable->isChecked(); + int col = 0; + addLabel(Boards::getAnalogInputName(board, index), row, col++); + + AutoLineEdit *name = new AutoLineEdit(this); + name->setField(generalSettings.stickName[index], HARDWARE_NAME_LEN, this); + + addParams(row, name); } -void HardwarePanel::on_sportPower_stateChanged() +void HardwarePanel::addPot(int index, int & row) { - generalSettings.sportPower = ui->sportPower->isChecked(); + addLabel(Boards::getAnalogInputName(board, Boards::getCapability(board, Board::Sticks) + index), row, 0); + + AutoLineEdit *name = new AutoLineEdit(this); + name->setField(generalSettings.potName[index], HARDWARE_NAME_LEN, this); + + AutoComboBox *type = new AutoComboBox(this); + type->setModel(editorItemModels->getItemModel(AIM_BOARDS_POT_TYPE)); + type->setField(generalSettings.potConfig[index], this); + + addParams(row, name, type); } -void HardwarePanel::on_rtcCheckDisable_stateChanged() +void HardwarePanel::addSlider(int index, int & row) { - generalSettings.rtcCheckDisable = !ui->rtcCheckDisable->isChecked(); + addLabel(Boards::getAnalogInputName(board, Boards::getCapability(board, Board::Sticks) + + Boards::getCapability(board, Board::Pots) + index), row, 0); + + AutoLineEdit *name = new AutoLineEdit(this); + name->setField(generalSettings.sliderName[index], HARDWARE_NAME_LEN, this); + + AutoComboBox *type = new AutoComboBox(this); + type->setModel(editorItemModels->getItemModel(AIM_BOARDS_SLIDER_TYPE)); + type->setField(generalSettings.sliderConfig[index], this); + + addParams(row, name, type); } -void HardwarePanel::on_PPM_MultiplierDSB_editingFinished() +void HardwarePanel::addSwitch(int index, int & row) { - int val = (int)(ui->PPM_MultiplierDSB->value()*10)-10; - if (generalSettings.PPM_Multiplier != val) { - generalSettings.PPM_Multiplier = val; - emit modified(); - } + addLabel(Boards::getSwitchInfo(board, index).name, row, 0); + + AutoLineEdit *name = new AutoLineEdit(this); + name->setField(generalSettings.switchName[index], HARDWARE_NAME_LEN, this); + + AutoComboBox *type = new AutoComboBox(this); + Board::SwitchInfo switchInfo = Boards::getSwitchInfo(board, index); + type->setModel(switchInfo.config < Board::SWITCH_3POS ? tabFilteredModels->getItemModel(FIM_SWITCHTYPE2POS) : + tabFilteredModels->getItemModel(FIM_SWITCHTYPE3POS)); + type->setField(generalSettings.switchConfig[index], this); + + addParams(row, name, type); } -void HardwarePanel::on_PPM1_editingFinished() +void HardwarePanel::addLabel(QString text, int row, int col) { - if (generalSettings.trainer.calib[0] != ui->PPM1->value()) { - generalSettings.trainer.calib[0] = ui->PPM1->value(); - emit modified(); - } + QLabel *label = new QLabel(this); + label->setText(text); + grid->addWidget(label, row, col); } -void HardwarePanel::on_PPM2_editingFinished() +void HardwarePanel::addLine(int & row) { - if (generalSettings.trainer.calib[1] != ui->PPM2->value()) { - generalSettings.trainer.calib[1] = ui->PPM2->value(); - emit modified(); - } + QFrame *line = new QFrame(this); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + line->setLineWidth(1); + line->setMidLineWidth(0); + grid->addWidget(line, row, 0, 1, grid->columnCount()); + row++; } -void HardwarePanel::on_PPM3_editingFinished() +void HardwarePanel::addParams(int & row, QWidget * widget1, QWidget * widget2) { - if (generalSettings.trainer.calib[2] != ui->PPM3->value()) { - generalSettings.trainer.calib[2] = ui->PPM3->value(); - emit modified(); - } -} - -void HardwarePanel::on_PPM4_editingFinished() -{ - if (generalSettings.trainer.calib[3] != ui->PPM4->value()) { - generalSettings.trainer.calib[3] = ui->PPM4->value(); - emit modified(); - } -} - - -void HardwarePanel::on_txCurrentCalibration_editingFinished() -{ - if (generalSettings.txCurrentCalibration != ui->txCurrentCalibration->value()) { - generalSettings.txCurrentCalibration = ui->txCurrentCalibration->value(); - emit modified(); - } -} - -void HardwarePanel::setValues() -{ - ui->txVoltageCalibration->setValue((double)generalSettings.txVoltageCalibration/10); - ui->txCurrentCalibration->setValue((double)generalSettings.txCurrentCalibration); - - ui->PPM1->setValue(generalSettings.trainer.calib[0]); - ui->PPM2->setValue(generalSettings.trainer.calib[1]); - ui->PPM3->setValue(generalSettings.trainer.calib[2]); - ui->PPM4->setValue(generalSettings.trainer.calib[3]); - ui->PPM_MultiplierDSB->setValue((qreal)(generalSettings.PPM_Multiplier+10)/10); -} - -void HardwarePanel::on_txVoltageCalibration_editingFinished() -{ - if (generalSettings.txVoltageCalibration != ui->txVoltageCalibration->value()*10) { - generalSettings.txVoltageCalibration = ui->txVoltageCalibration->value()*10; - emit modified(); - } -} - -void HardwarePanel::on_serialPortMode_currentIndexChanged(int index) -{ - generalSettings.auxSerialMode = index; - emit modified(); + QGridLayout *subgrid = new QGridLayout(); + subgrid->addWidget(widget1, 0, 0); + if (widget2) + subgrid->addWidget(widget2, 0, 1); + else + addHSpring(subgrid, 1, 0); + addHSpring(subgrid, 2, 0); + grid->addLayout(subgrid, row, 1); + row++; } diff --git a/companion/src/generaledit/hardware.h b/companion/src/generaledit/hardware.h index 3b63a1d77..71636a2cc 100644 --- a/companion/src/generaledit/hardware.h +++ b/companion/src/generaledit/hardware.h @@ -18,52 +18,33 @@ * GNU General Public License for more details. */ -#ifndef _HARDWARE_H_ -#define _HARDWARE_H_ +#pragma once #include "generaledit.h" -namespace Ui { - class Hardware; -} - -class QLabel; -class AutoLineEdit; -class AutoComboBox; +class CompoundItemModelFactory; +class FilteredItemModelFactory; +class QGridLayout; class HardwarePanel : public GeneralPanel { Q_OBJECT public: - HardwarePanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware); + HardwarePanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * editorItemModels); virtual ~HardwarePanel(); - private slots: - void on_PPM1_editingFinished(); - void on_PPM2_editingFinished(); - void on_PPM3_editingFinished(); - void on_PPM4_editingFinished(); - void on_PPM_MultiplierDSB_editingFinished(); - - void on_txCurrentCalibration_editingFinished(); - void on_txVoltageCalibration_editingFinished(); - void on_filterEnable_stateChanged(); - void on_rtcCheckDisable_stateChanged(); - void on_sportPower_stateChanged(); - - void on_serialPortMode_currentIndexChanged(int index); - - protected: - void setupPotType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type); - void setupSliderType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type); - void setupSwitchType(int index, QLabel * label, AutoLineEdit * name, AutoComboBox * type, bool threePos = true); - private: - Ui::Hardware *ui; + Board::Type board; + CompoundItemModelFactory *editorItemModels; + FilteredItemModelFactory *tabFilteredModels; + QGridLayout *grid; - void setValues(); - bool isSwitch3Pos(int idx); + void addStick(int index, int & row); + void addPot(int index, int & row); + void addSlider(int index, int & row); + void addSwitch(int index, int & row); + void addLabel(QString text, int row, int col); + void addLine(int & row); + void addParams(int & row, QWidget * widget1, QWidget * widget2 = nullptr); }; - -#endif // _HARDWARE_H_ diff --git a/companion/src/generaledit/hardware.ui b/companion/src/generaledit/hardware.ui deleted file mode 100644 index 5224ed785..000000000 --- a/companion/src/generaledit/hardware.ui +++ /dev/null @@ -1,1160 +0,0 @@ - - - Hardware - - - - 0 - 0 - 470 - 1618 - - - - - 0 - 0 - - - - Form - - - - 6 - - - - - - - - - - - - - - - - - - - OFF - - - - - S-Port Mirror - - - - - Telemetry - - - - - SBUS Trainer - - - - - Debug - - - - - - - - - - - - - - - - - - - - - Thr - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - 3 - - - - - - - SD - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 10 - - - - Qt::Horizontal - - - - - - - SO - - - - - - - -49 - - - 49 - - - - - - - 3 - - - - - - - RS - - - - - - - 3 - - - - - - - Ail - - - - - - - S4 - - - - - - - - - - - - - - - - -9999 - - - 9999 - - - - - - - LS2 - - - - - - - Antenna - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - PPM 1 - - - - - - - LS - - - - - - - Rud - - - - - - - Serial Port - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - SP - - - - - - - 3 - - - - - - - RS2 - - - - - - - - - - - - - - - - - SH - - - - - - - - - - - - - - - - - SM - - - - - - - SE - - - - - - - - - - - - - - - - - - - - 1 - - - 5.000000000000000 - - - 1.000000000000000 - - - - - - - S2 - - - - - - - 3 - - - - - - - - - - - - - - - - -9999 - - - 9999 - - - - - - - SJ - - - - - - - PPM 2 - - - - - - - 3 - - - - - - - SG - - - - - - - S5 - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - 10 - - - - Qt::Horizontal - - - - - - - Current Offset - - - - - - - SK - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - - - - - - - - ADC Filter - - - - - - - 3 - - - - - - - 3 - - - - - - - SF - - - - - - - - - - - - - - - - - - - - - - - - - - - S3 - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - SB - - - - - - - - - - - - - - - - - - - - SI - - - - - - - SQ - - - - - - - Ele - - - - - - - 3 - - - - - - - 3 - - - - - - - - - - - - - - - - - 3 - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - 3 - - - - - - - - - - SA - - - - - - - 3 - - - - - - - - - - - - - - SR - - - - - - - 3 - - - - - - - PPM Multiplier - - - - - - - S1 - - - - - - - - 0 - 0 - - - - Bluetooth - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - PPM 4 - - - - - - - - - - - - - - - - - v - - - 1 - - - -9.900000000000000 - - - 9.900000000000000 - - - 0.100000000000000 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - 3 - - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - Device Name: - - - - - - - 10 - - - - - - - - - - PPM 3 - - - - - - - RTC Batt Check - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - SL - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - 3 - - - - - - - - - - - - - - - - -9999 - - - 9999 - - - - - - - 3 - - - - - - - SC - - - - - - - 3 - - - - - - - - - - - - - - - - -9999 - - - 9999 - - - - - - - - 0 - 10 - - - - Qt::Horizontal - - - - - - - - - - - - - - - - - - - - 3 - - - - - - - SN - - - - - - - Battery Offset - - - - - - - 3 - - - - - - - 3 - - - - - - - S.Port Power - - - - - - - - - - - - - - - AutoComboBox - QComboBox -
autocombobox.h
-
- - AutoLineEdit - QLineEdit -
autolineedit.h
-
-
- - -
diff --git a/companion/src/generaledit/trainer.cpp b/companion/src/generaledit/trainer.cpp index 721e2d60a..997f5f456 100644 --- a/companion/src/generaledit/trainer.cpp +++ b/companion/src/generaledit/trainer.cpp @@ -19,103 +19,106 @@ */ #include "trainer.h" -#include "ui_trainer.h" +#include "compounditemmodels.h" +#include "autocombobox.h" +#include "autolineedit.h" +#include "autospinbox.h" +#include "autodoublespinbox.h" -TrainerPanel::TrainerPanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware): - GeneralPanel(parent, generalSettings, firmware), - ui(new Ui::Trainer) +#include +#include +#include + +TrainerPanel::TrainerPanel(QWidget * parent, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * editorItemModels): + GeneralPanel(parent, generalSettings, firmware) { - ui->setupUi(this); + int modeid = editorItemModels->registerItemModel(TrainerMix::modeItemModel()); + int srcid = editorItemModels->registerItemModel(TrainerMix::srcItemModel()); + Board::Type board = getCurrentBoard(); + const int stickcnt = Boards::getCapability(board, Board::Sticks); - ui->trnMode_1->setCurrentIndex(generalSettings.trainer.mix[0].mode); - ui->trnChn_1->setCurrentIndex(generalSettings.trainer.mix[0].src); - ui->trnWeight_1->setValue(generalSettings.trainer.mix[0].weight); - ui->trnMode_2->setCurrentIndex(generalSettings.trainer.mix[1].mode); - ui->trnChn_2->setCurrentIndex(generalSettings.trainer.mix[1].src); - ui->trnWeight_2->setValue(generalSettings.trainer.mix[1].weight); - ui->trnMode_3->setCurrentIndex(generalSettings.trainer.mix[2].mode); - ui->trnChn_3->setCurrentIndex(generalSettings.trainer.mix[2].src); - ui->trnWeight_3->setValue(generalSettings.trainer.mix[2].weight); - ui->trnMode_4->setCurrentIndex(generalSettings.trainer.mix[3].mode); - ui->trnChn_4->setCurrentIndex(generalSettings.trainer.mix[3].src); - ui->trnWeight_4->setValue(generalSettings.trainer.mix[3].weight); + const FieldRange weightrng = TrainerMix::getWeightRange(); + grid = new QGridLayout(this); + + int col = 0; + int row = 0; + + if (stickcnt) { + addLabel(tr("Mode"), row, 1); + addLabel(tr("Weight"), row, 2); + addLabel(tr("Source"), row++, 3); + + for (int i = 0; i < 4; i++, row++) { // TODO constant + col = 0; + addLabel(Boards::getAnalogInputName(board, i), row, col++); + + AutoComboBox *mode = new AutoComboBox(this); + mode->setModel(editorItemModels->getItemModel(modeid)); + mode->setField(generalSettings.trainer.mix[i].mode, this); + grid->addWidget(mode, row, col++); + + AutoSpinBox *weight = new AutoSpinBox(this); + weight->setRange(weightrng.min, weightrng.max); + weight->setField(generalSettings.trainer.mix[i].weight, this); + grid->addWidget(weight, row, col++); + + AutoComboBox *src = new AutoComboBox(this); + src->setModel(editorItemModels->getItemModel(srcid)); + src->setField(generalSettings.trainer.mix[i].src, this); + grid->addWidget(src, row, col++); + } + + addLine(row++, 0, grid->columnCount()); + } + + col = 0; + addLabel(tr("Multiplier"), row, col++); + + const FieldRange ppmmrng = GeneralSettings::getPPM_MultiplierRange(); + + AutoDoubleSpinBox *multi = new AutoDoubleSpinBox(this); + multi->setDecimals(ppmmrng.decimals); + multi->setOffset(ppmmrng.offset); + multi->setSingleStep(ppmmrng.step); + multi->setRange(ppmmrng.min, ppmmrng.max); + multi->setField(generalSettings.PPM_Multiplier, this); + grid->addWidget(multi, row++, col); + + col = 0; + + addLabel(tr("Calibration"), row, col++); + + for (int i = 0; i < stickcnt; i++, col++) { + AutoLineEdit *calib = new AutoLineEdit(this); + calib->setText(QString("%1").arg(generalSettings.trainer.calib[i])); + calib->setReadOnly(true); + grid->addWidget(calib, row, col); + } + + addHSpring(grid, grid->columnCount(), 0); + addVSpring(grid, 0, grid->rowCount()); + disableMouseScrolling(); } TrainerPanel::~TrainerPanel() { - delete ui; } -void TrainerPanel::on_trnMode_1_currentIndexChanged(int index) +void TrainerPanel::addLabel(QString text, int row, int col) { - generalSettings.trainer.mix[0].mode = index; - emit modified(); + QLabel *label = new QLabel(this); + label->setText(text); + grid->addWidget(label, row, col); } -void TrainerPanel::on_trnChn_1_currentIndexChanged(int index) +void TrainerPanel::addLine(int row, int col, int colspan) { - generalSettings.trainer.mix[0].src = index; - emit modified(); -} - -void TrainerPanel::on_trnWeight_1_editingFinished() -{ - generalSettings.trainer.mix[0].weight = ui->trnWeight_1->value(); - emit modified(); -} - -void TrainerPanel::on_trnMode_2_currentIndexChanged(int index) -{ - generalSettings.trainer.mix[1].mode = index; - emit modified(); -} - -void TrainerPanel::on_trnChn_2_currentIndexChanged(int index) -{ - generalSettings.trainer.mix[1].src = index; - emit modified(); -} - -void TrainerPanel::on_trnWeight_2_editingFinished() -{ - generalSettings.trainer.mix[1].weight = ui->trnWeight_2->value(); - emit modified(); -} - -void TrainerPanel::on_trnMode_3_currentIndexChanged(int index) -{ - generalSettings.trainer.mix[2].mode = index; - emit modified(); -} - -void TrainerPanel::on_trnChn_3_currentIndexChanged(int index) -{ - generalSettings.trainer.mix[2].src = index; - emit modified(); -} - -void TrainerPanel::on_trnWeight_3_editingFinished() -{ - generalSettings.trainer.mix[2].weight = ui->trnWeight_3->value(); - emit modified(); -} - -void TrainerPanel::on_trnMode_4_currentIndexChanged(int index) -{ - generalSettings.trainer.mix[3].mode = index; - emit modified(); -} - -void TrainerPanel::on_trnChn_4_currentIndexChanged(int index) -{ - generalSettings.trainer.mix[3].src = index; - emit modified(); -} - -void TrainerPanel::on_trnWeight_4_editingFinished() -{ - generalSettings.trainer.mix[3].weight = ui->trnWeight_4->value(); - emit modified(); + QFrame *line = new QFrame(this); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + line->setLineWidth(1); + line->setMidLineWidth(0); + grid->addWidget(line, row, col, 1, colspan); } diff --git a/companion/src/generaledit/trainer.h b/companion/src/generaledit/trainer.h index 56442dc8b..e0c777af4 100644 --- a/companion/src/generaledit/trainer.h +++ b/companion/src/generaledit/trainer.h @@ -18,42 +18,23 @@ * GNU General Public License for more details. */ -#ifndef _TRAINER_H_ -#define _TRAINER_H_ +#pragma once #include "generaledit.h" #include "eeprominterface.h" -namespace Ui { - class Trainer; -} +class CompoundItemModelFactory; class TrainerPanel : public GeneralPanel { Q_OBJECT public: - TrainerPanel(QWidget *parent, GeneralSettings & generalSettings, Firmware * firmware); + TrainerPanel(QWidget *parent, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * editorItemModels); virtual ~TrainerPanel(); - private slots: - void on_trnMode_1_currentIndexChanged(int index); - void on_trnChn_1_currentIndexChanged(int index); - void on_trnWeight_1_editingFinished(); - void on_trnMode_2_currentIndexChanged(int index); - void on_trnChn_2_currentIndexChanged(int index); - void on_trnWeight_2_editingFinished(); - void on_trnMode_3_currentIndexChanged(int index); - void on_trnChn_3_currentIndexChanged(int index); - void on_trnWeight_3_editingFinished(); - void on_trnMode_4_currentIndexChanged(int index); - void on_trnChn_4_currentIndexChanged(int index); - void on_trnWeight_4_editingFinished(); - private: - Ui::Trainer *ui; - - void setValues(); + QGridLayout * grid; + void addLabel(QString text, int row, int col); + void addLine(int row, int col, int colspan); }; - -#endif // _TRAINER_H_ diff --git a/companion/src/generaledit/trainer.ui b/companion/src/generaledit/trainer.ui deleted file mode 100644 index 312999a0d..000000000 --- a/companion/src/generaledit/trainer.ui +++ /dev/null @@ -1,475 +0,0 @@ - - - Trainer - - - - 0 - 0 - 400 - 300 - - - - Form - - - - - - - - - - - - - - - -125 - - - 125 - - - - - - - Mode - - - - - - - Input - - - - - - - Weight - - - - - - - - 0 - 0 - - - - Rud - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - Off - - - - - += (Sum) - - - - - := (Replace) - - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - chn1 - - - - - chn2 - - - - - chn3 - - - - - chn4 - - - - - - - - - - - - - - - - - -125 - - - 125 - - - - - - - - 0 - 0 - - - - Ele - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - Off - - - - - += (Sum) - - - - - := (Replace) - - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - chn1 - - - - - chn2 - - - - - chn3 - - - - - chn4 - - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - chn1 - - - - - chn2 - - - - - chn3 - - - - - chn4 - - - - - - - - - - - - - - - - - -125 - - - 125 - - - - - - - - 0 - 0 - - - - Thr - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - Off - - - - - += (Sum) - - - - - := (Replace) - - - - - - - - - 0 - 0 - - - - Ail - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - Off - - - - - += (Sum) - - - - - := (Replace) - - - - - - - - - - - - - - Beeper volume - -0 - Quiet. No beeps at all. -1 - No Keys. Normal beeps but menu keys do not beep. -2 - Normal. -3 - Loud. -4 - Extra loud. - - - - chn1 - - - - - chn2 - - - - - chn3 - - - - - chn4 - - - - - - - - - - - - - - - - - -125 - - - 125 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index c1cd7de79..5f749fa33 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -620,6 +620,17 @@ void TableLayout::setColumnWidth(int col, int width) #if defined(TABLE_LAYOUT) tableWidget->setColumnWidth(col, width); #else + gridWidget->setColumnMinimumWidth(col, width); +#endif +} + +void TableLayout::setColumnWidth(int col, QString str) +{ +#if defined(TABLE_LAYOUT) +#else + QFontMetrics *f = new QFontMetrics(QFont()); + QSize sz = f->size(Qt::TextSingleLine, str); + setColumnWidth(col, sz.width()); #endif } @@ -628,12 +639,19 @@ void TableLayout::pushRowsUp(int row) #if defined(TABLE_LAYOUT) #else // Push the rows up - QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ); + QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); gridWidget->addItem(spacer, row, 0); #endif - // Push rows upward - // addDoubleSpring(gridLayout, 5, num_fsw+1); +} +void TableLayout::pushColumnsLeft(int col) +{ +#if defined(TABLE_LAYOUT) +#else + // Push the columns to the left + QSpacerItem * spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); + gridWidget->addItem(spacer, 0, col); +#endif } QString Helpers::getChecklistsPath() diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 8bb1cc6b8..98783439b 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -191,7 +191,9 @@ public: void resizeColumnsToContents(); void setColumnWidth(int col, int width); + void setColumnWidth(int col, QString str); void pushRowsUp(int row); + void pushColumnsLeft(int col); private: #if defined(TABLE_LAYOUT) diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index ffd5942bf..9085d7632 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -17,6 +17,7 @@ set(shared_HDRS hexspinbox.h autoprecisioncombobox.h autotimeedit.h + autospinbox.h ) qt5_wrap_cpp(shared_SRCS ${shared_HDRS}) diff --git a/companion/src/shared/autocheckbox.h b/companion/src/shared/autocheckbox.h index 1c1a7207c..6355b6c53 100644 --- a/companion/src/shared/autocheckbox.h +++ b/companion/src/shared/autocheckbox.h @@ -32,15 +32,17 @@ class AutoCheckBox: public QCheckBox QCheckBox(parent), field(nullptr), panel(nullptr), - lock(false) + lock(false), + invert(false) { - connect(this, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool))); + connect(this, &AutoCheckBox::toggled, this, &AutoCheckBox::onToggled); } - void setField(bool & field, GenericPanel * panel = nullptr) + void setField(bool & field, GenericPanel * panel = nullptr, bool invert = false) { this->field = &field; this->panel = panel; + this->invert = invert; updateValue(); } @@ -49,11 +51,17 @@ class AutoCheckBox: public QCheckBox QCheckBox::setEnabled(enabled); } + void setInvert(bool invert) + { + this->invert = invert; + updateValue(); + } + void updateValue() { if (field) { lock = true; - setChecked(*field); + setChecked(invert ? !(*field) : *field); lock = false; } } @@ -67,8 +75,9 @@ class AutoCheckBox: public QCheckBox if (panel && panel->lock) return; if (field && !lock) { - *field = checked; - emit currentDataChanged(checked); + const bool val = invert ? !checked : checked; + *field = val; + emit currentDataChanged(val); if (panel) emit panel->modified(); } @@ -78,4 +87,5 @@ class AutoCheckBox: public QCheckBox bool *field = nullptr; GenericPanel *panel = nullptr; bool lock = false; + bool invert = false; }; diff --git a/companion/src/shared/autodoublespinbox.h b/companion/src/shared/autodoublespinbox.h index a6466269e..f9614d882 100644 --- a/companion/src/shared/autodoublespinbox.h +++ b/companion/src/shared/autodoublespinbox.h @@ -35,7 +35,8 @@ class AutoDoubleSpinBox: public QDoubleSpinBox QDoubleSpinBox(parent), field(nullptr), panel(nullptr), - lock(false) + lock(false), + offset(0) { connect(this, SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double))); } @@ -58,7 +59,7 @@ class AutoDoubleSpinBox: public QDoubleSpinBox { if (field) { lock = true; - setValue(float(*field) / multiplier()); + setValue(float(*field + offset) / multiplier()); lock = false; } } @@ -69,6 +70,12 @@ class AutoDoubleSpinBox: public QDoubleSpinBox updateValue(); } + void setOffset(int offset) + { + this->offset = offset; + updateValue(); + } + protected: int multiplier() { @@ -91,8 +98,8 @@ class AutoDoubleSpinBox: public QDoubleSpinBox if (panel && panel->lock) return; if (field && !lock) { - *field = round(value * multiplier()); - emit currentDataChanged(value); + *field = round(value * multiplier() - offset); + emit currentDataChanged(*field); if (panel) { emit panel->modified(); } @@ -103,4 +110,5 @@ class AutoDoubleSpinBox: public QDoubleSpinBox int * field = nullptr; GenericPanel * panel = nullptr; bool lock = false; + int offset = 0; }; diff --git a/companion/src/shared/autospinbox.h b/companion/src/shared/autospinbox.h new file mode 100644 index 000000000..65b49c0f3 --- /dev/null +++ b/companion/src/shared/autospinbox.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include + +#include "genericpanel.h" + +class AutoSpinBox : public QSpinBox +{ + Q_OBJECT + + public: + explicit AutoSpinBox(QWidget * parent = nullptr): + QSpinBox(parent), + field(nullptr), + panel(nullptr), + lock(false) + { + connect(this, QOverload::of(&AutoSpinBox::valueChanged), this, &AutoSpinBox::onValueChanged); + } + + void setField(int & field, GenericPanel * panel = nullptr) + { + this->field = &field; + this->panel = panel; + updateValue(); + } + + void setField(unsigned int & field, GenericPanel * panel = nullptr) + { + this->field = (int *)&field; + this->panel = panel; + updateValue(); + } + + void updateValue() + { + lock = true; + if (field) { + setValue(*field); + } + lock = false; + } + + protected slots: + void onValueChanged(int value) + { + if (panel && panel->lock) + return; + if (field && !lock) { + *field = value; + if (panel) { + emit panel->modified(); + } + } + } + + protected: + int * field; + GenericPanel * panel; + bool lock; +}; diff --git a/companion/src/shared/genericpanel.h b/companion/src/shared/genericpanel.h index 88c7f841b..6d51fe767 100644 --- a/companion/src/shared/genericpanel.h +++ b/companion/src/shared/genericpanel.h @@ -41,6 +41,7 @@ class GenericPanel : public QWidget friend class AutoPrecisionComboBox; friend class AutoBitsetCheckBox; friend class AutoTimeEdit; + friend class AutoSpinBox; public: GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware); From 6e322e1f401dd55ba0e71a0a6fb766b18efae74e Mon Sep 17 00:00:00 2001 From: elecpower Date: Sat, 17 Apr 2021 07:15:52 +1000 Subject: [PATCH 14/70] New autoslider widget --- companion/src/shared/CMakeLists.txt | 1 + companion/src/shared/autoslider.h | 104 ++++++++++++++++++++++++++++ companion/src/shared/genericpanel.h | 1 + 3 files changed, 106 insertions(+) create mode 100644 companion/src/shared/autoslider.h diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index 9085d7632..e54116b3c 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -18,6 +18,7 @@ set(shared_HDRS autoprecisioncombobox.h autotimeedit.h autospinbox.h + autoslider.h ) qt5_wrap_cpp(shared_SRCS ${shared_HDRS}) diff --git a/companion/src/shared/autoslider.h b/companion/src/shared/autoslider.h new file mode 100644 index 000000000..e81ea66b4 --- /dev/null +++ b/companion/src/shared/autoslider.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "genericpanel.h" + +#include + +class AutoSlider : public QSlider +{ + Q_OBJECT + + public: + explicit AutoSlider(QWidget * parent = nullptr): + QSlider(parent) + { + init(); + } + + explicit AutoSlider(Qt::Orientation orientation, QWidget * parent = nullptr): + QSlider(orientation, parent) + { + init(); + } + + void setField(int & field, int min, int max, GenericPanel * panel = nullptr) + { + this->field = &field; + setFieldInit(min, max, panel); + } + + void setField(unsigned int & field, int min, int max, GenericPanel * panel = nullptr) + { + this->field = reinterpret_cast(&field); + setFieldInit(min, max, panel); + } + + void setTick(int interval, QSlider::TickPosition position) + { + setTickInterval(interval); + setTickPosition(position); + } + + void updateValue() + { + if (field) { + lock = true; + setValue(*field); + lock = false; + } + } + + signals: + void currentDataChanged(int value); + + protected slots: + void init() + { + connect(this, &AutoSlider::valueChanged, this, &AutoSlider::onValueChanged); + } + + void onValueChanged(int value) + { + if (panel && panel->lock) + return; + if (field && !lock) { + *field = value; + emit currentDataChanged(value); + if (panel) { + emit panel->modified(); + } + } + } + + protected: + void setFieldInit(int min, int max, GenericPanel * panel) + { + this->panel = panel; + setRange(min, max); + updateValue(); + } + + int *field = nullptr; + GenericPanel *panel = nullptr; + bool lock = false; +}; diff --git a/companion/src/shared/genericpanel.h b/companion/src/shared/genericpanel.h index 6d51fe767..e55a54371 100644 --- a/companion/src/shared/genericpanel.h +++ b/companion/src/shared/genericpanel.h @@ -42,6 +42,7 @@ class GenericPanel : public QWidget friend class AutoBitsetCheckBox; friend class AutoTimeEdit; friend class AutoSpinBox; + friend class AutoSlider; public: GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware); From 3d5f8b2b2c1f65a04016bbcd811903f3762d1619 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 17 Apr 2021 16:58:02 +0200 Subject: [PATCH 15/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 3b31f5604..f4f2c3cb9 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2237,3 +2237,4 @@ Glenn Noonan Michael Jakob Dean Berg David Hankins +Gary Cripps From aa61e1ba196e8e69f9268583c27f4762729eacf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Charpentier?= Date: Mon, 19 Apr 2021 15:19:59 +0200 Subject: [PATCH 16/70] Updated French Translation (#8458) * Updated French Translation. --- companion/src/translations/companion_fr.ts | 113 +++++++++++---------- 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index 2a6eea996..d94e9785d 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -2233,7 +2233,7 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import OpenTX ne supporte pas cette fonction sur cette carte - + OpenTX doesn't accept this radio protocol OpenTX ne supporte pas ce protocole radio @@ -8975,28 +8975,33 @@ Mixage actif par défaut si non-renseigné. Maître/Multi - + Disable Telemetry Désactiver la télémétrie - + + Racing Mode + Mode Course/Racing + + + Disable Ch. Map Désactiver "Mapping" des VOIES - + Show values in: Afficher les valeurs en: - + % abbreviation for percent - + μs abbreviation for microseconds @@ -9084,7 +9089,7 @@ Mixage actif par défaut si non-renseigné. ID d'enregistrement - + Failsafe Positions Positions Failsafe @@ -9137,100 +9142,100 @@ Mixage actif par défaut si non-renseigné. Négative - + Trainer Port Port écolage - + Internal Radio System Module HF interne - + External Radio Module Module HF externe - + Extra Radio System Module HF supplémentaire - + Radio System Module HF - + 10mW - 16CH 10mW - 16 VOIES - - + + 100mW - 16CH 100mW - 16 VOIES - + 500mW - 16CH 500mW - 16 VOIES - + Auto <= 1W - 16CH Auto <= 1W - 16 VOIES - - + + 25mW - 8CH 25mW - 8 VOIES - - + + 25mW - 16CH 25mW - 16 VOIES - + 200mW - 16CH (no telemetry) 200mW - 16 VOIES (pas de télémétrie) - + 500mW - 16CH (no telemetry) 500mW - 16 VOIES (pas de télémétrie) - + 100mW - 16CH (no telemetry) 100mW - 16 VOIES (pas de télémétrie) - + 25 mW - + 100 mW - + 500 mW - + 1 W - + 2 W @@ -9238,42 +9243,42 @@ Mixage actif par défaut si non-renseigné. ModulePanel - + Value Valeur - + Hold Maintien - + No Pulse Pas d'impulsion - + Ask Demander - + Internal Interne - + Internal + External Interne + Externe - + External Externe - + Bind on channel Bind avec VOIE @@ -11031,87 +11036,87 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo SetupPanel - + Popup menu available Menu contextuel disponible - + Timer %1 Chrono %1 - + Profile Settings Paramètres du profil - + SD structure path not specified or invalid Chemin de la structure SD non spécifié ou invalide - + Copy Copier - + Cut Couper - + Paste Coller - + Clear Effacer - + Insert Insérer - + Delete Supprimer - + Move Up Monter - + Move Down Descendre - + Clear All Effacer Tout - + Clear Timer. Are you sure? Effacer le Chrono. Êtes-vous sûr? - + Clear all Timers. Are you sure? Effacer tous les Chronos. Êtes-vous sûr? - + Cut Timer. Are you sure? Couper le Chrono. Êtes-vous sûr? - + Delete Timer. Are you sure? Supprimer le Chrono. Êtes-vous sûr? From 8a978b5b0761411b9a135767d9f0ce35fd8f5b0d Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Mon, 19 Apr 2021 15:24:05 -0400 Subject: [PATCH 17/70] Update ModuleSyncStatus::update signature with proper types Also updates getRefreshString to use the signed types, and display correctly scaled values. --- radio/src/telemetry/telemetry.cpp | 15 +++++++-------- radio/src/telemetry/telemetry.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 700bf535a..d83765ce8 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -398,7 +398,7 @@ ModuleSyncStatus::ModuleSyncStatus() memset(this, 0, sizeof(ModuleSyncStatus)); } -void ModuleSyncStatus::update(uint16_t newRefreshRate, uint16_t newInputLag) +void ModuleSyncStatus::update(uint16_t newRefreshRate, int16_t newInputLag) { if (!newRefreshRate) return; @@ -449,13 +449,12 @@ void ModuleSyncStatus::getRefreshString(char * statusText) char * tmp = statusText; #if defined(DEBUG) *tmp++ = 'L'; - tmp = strAppendUnsigned(tmp, inputLag, 5); - tmp = strAppend(tmp, "us R "); - tmp = strAppendUnsigned(tmp, (uint32_t) (refreshRate / 1000), 5); - tmp = strAppend(tmp, "us"); + tmp = strAppendSigned(tmp, inputLag, 5); + tmp = strAppend(tmp, "R"); + tmp = strAppendUnsigned(tmp, refreshRate, 5); #else - tmp = strAppend(tmp, "Sync at "); - tmp = strAppendUnsigned(tmp, (uint32_t) (refreshRate / 1000000)); - tmp = strAppend(tmp, " ms"); + tmp = strAppend(tmp, "Sync "); + tmp = strAppendUnsigned(tmp, refreshRate); #endif + tmp = strAppend(tmp, "us"); } diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index c70cc5fb9..1189443ba 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -306,7 +306,7 @@ struct ModuleSyncStatus } // Set feedback from RF module - void update(uint16_t newRefreshRate, uint16_t newInputLag); + void update(uint16_t newRefreshRate, int16_t newInputLag); // Get computed settings for scheduler uint16_t getAdjustedRefreshRate(); From 30f72a869577e0f7903ee45fe088416ff417331e Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 20 Apr 2021 09:03:07 +0200 Subject: [PATCH 18/70] Update CREDITS.txt --- CREDITS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index f4f2c3cb9..88516b482 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2238,3 +2238,6 @@ Michael Jakob Dean Berg David Hankins Gary Cripps +Devin Crumb +Daniel Naude +James Miller From d67d1aa0c09d2f485c3ef7ca8c4fb1e9214a2ee7 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 20 Apr 2021 11:09:43 +0200 Subject: [PATCH 19/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 88516b482..227bb3c99 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2241,3 +2241,4 @@ Gary Cripps Devin Crumb Daniel Naude James Miller +Pascal Cayol From 5f59bb58d7cc21e7a7c9272f0147736f780a4521 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 21 Apr 2021 12:58:13 +0200 Subject: [PATCH 20/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 227bb3c99..2029edbb0 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2242,3 +2242,4 @@ Devin Crumb Daniel Naude James Miller Pascal Cayol +eDefine From a626d57d79cf485492bd900e6af8a4242e8a0a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Charpentier?= Date: Wed, 21 Apr 2021 13:24:01 +0200 Subject: [PATCH 21/70] Updated French translation. (#8461) --- companion/src/translations/companion_fr.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index d94e9785d..0ece144ea 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -1631,7 +1631,7 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Trainer Sticks - Manches Écolage + Écolage Manches @@ -1656,7 +1656,7 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Trainer Channels - Écolage Channels + Écolage Canaux @@ -8982,7 +8982,7 @@ Mixage actif par défaut si non-renseigné. Racing Mode - Mode Course/Racing + Mode Course/Racing From 77f1840af6d709eed975fba24a9648f3ed37ca58 Mon Sep 17 00:00:00 2001 From: Neil Horne Date: Fri, 23 Apr 2021 15:06:27 +1000 Subject: [PATCH 22/70] Fix 8463 (#8464) --- companion/src/firmwares/rawsource.cpp | 2 +- companion/src/firmwares/sensordata.cpp | 10 +++++----- companion/src/firmwares/sensordata.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index 898c0ca4a..dfd8ae4d4 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -60,7 +60,7 @@ RawSourceRange RawSource::getRange(const ModelData * model, const GeneralSetting result.min = -30000 * result.step; result.max = +30000 * result.step; result.decimals = sensor.prec; - result.unit = SensorData::unitToString(qr.quot); + result.unit = sensor.unitToString(); break; } diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index ae602bd0d..9a26a6d82 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -75,9 +75,9 @@ QString SensorData::cellIndexToString() const return cellIndexToString(index); } -QString SensorData::unitToString() const +QString SensorData::unitToString(bool hideRaw) const { - return unitToString(unit); + return unitToString(unit, hideRaw); } QString SensorData::precToString() const @@ -342,11 +342,11 @@ QString SensorData::sourceToString(const ModelData * model, const int index, con } // static -QString SensorData::unitToString(const int value) +QString SensorData::unitToString(const int value, bool hideRaw) { switch (value) { case UNIT_RAW: - return tr("Raw (-)"); + return hideRaw ? QString() : tr("Raw (-)"); case UNIT_VOLTS: return tr("V"); case UNIT_AMPS: @@ -496,7 +496,7 @@ AbstractStaticItemModel * SensorData::unitItemModel() mdl->setName("sensordata.unit"); for (int i = 0; i <= UNIT_MAX; i++) { - QString str = unitToString(i); + QString str = unitToString(i, false); if (str != CPN_STR_UNKNOWN_ITEM) mdl->appendToItemList(str, i); } diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index 8a032cec5..1581b444b 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -188,7 +188,7 @@ class SensorData { QString typeToString() const; QString formulaToString() const; QString cellIndexToString() const; - QString unitToString() const; + QString unitToString(bool hideRaw = true) const; QString precToString() const; int getMask() const; QString paramsToString(const ModelData * model) const; @@ -203,7 +203,7 @@ class SensorData { static QString typeToString(const int value); static QString formulaToString(const int value); static QString cellIndexToString(const int value); - static QString unitToString(const int value); + static QString unitToString(const int value, bool hideRaw = true); static QString precToString(const int value); static bool isRssiSensorAvailable(const ModelData * model, const int value); static QString rssiSensorToString(const ModelData * model, const int value); From 890888f3e3e87be75ebc1ea65b23232fe57511b9 Mon Sep 17 00:00:00 2001 From: Neil Horne Date: Sat, 24 Apr 2021 19:47:50 +1000 Subject: [PATCH 23/70] Stop Companion crash when conversion switch index out of range (#8469) --- companion/src/firmwares/rawswitch.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/companion/src/firmwares/rawswitch.cpp b/companion/src/firmwares/rawswitch.cpp index 7aef46922..f609e7942 100644 --- a/companion/src/firmwares/rawswitch.cpp +++ b/companion/src/firmwares/rawswitch.cpp @@ -191,7 +191,10 @@ RawSwitch RawSwitch::convert(RadioDataConversionState & cstate) QStringList fromSwitchList(getSwitchList(cstate.fromBoard)); QStringList toSwitchList(getSwitchList(cstate.toBoard)); // set to -1 if no match found - newIdx = toSwitchList.indexOf(fromSwitchList.at(swtch.quot)); + if (swtch.quot < fromSwitchList.count()) + newIdx = toSwitchList.indexOf(fromSwitchList.at(swtch.quot)); + else + newIdx = -1; // perform forced mapping if (newIdx < 0) { if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { From ddd033f03409d7ab2c04d3f48d09656d19c2f558 Mon Sep 17 00:00:00 2001 From: Neil Horne Date: Sat, 24 Apr 2021 20:59:21 +1000 Subject: [PATCH 24/70] Stop Companion crash when conversion source index out of range (#8470) --- companion/src/firmwares/rawsource.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index dfd8ae4d4..eaa651b6c 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -351,8 +351,11 @@ RawSource RawSource::convert(RadioDataConversionState & cstate) if (type == SOURCE_TYPE_SWITCH) { QStringList fromSwitchList(getSwitchList(cstate.fromBoard)); QStringList toSwitchList(getSwitchList(cstate.toBoard)); - index = toSwitchList.indexOf(fromSwitchList.at(oldData.id)); // index set to -1 if no match found + if (oldData.id < fromSwitchList.count()) + index = toSwitchList.indexOf(fromSwitchList.at(oldData.id)); + else + index = -1; // perform forced mapping if (index < 0) { if (IS_TARANIS_X7(cstate.toType) && (IS_TARANIS_X9(cstate.fromType) || IS_FAMILY_HORUS_OR_T16(cstate.fromType))) { From fe2bb8b07317fd281ca6bc3201ed15247703a953 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 26 Apr 2021 14:24:44 +0200 Subject: [PATCH 25/70] Update CREDITS.txt --- CREDITS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 2029edbb0..af5a6c0e7 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2243,3 +2243,6 @@ Daniel Naude James Miller Pascal Cayol eDefine +Mario Sette +Hans-Georg Böhm +Robert Oats From 466cd4889c5769810f4d66981e9ec64537179bcb Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 27 Apr 2021 13:04:11 +0200 Subject: [PATCH 26/70] run some task more frequently --- radio/src/tasks.cpp | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index f44e1cb16..4878535fd 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -110,6 +110,25 @@ void sendSynchronousPulses(uint8_t runMask) #endif } +constexpr uint8_t MIXER_FREQUENT_ACTIONS_PERIOD = 5 /*ms*/; +constexpr uint8_t MIXER_MAX_PERIOD = 30 /*ms*/; + +void execMixerFrequentActions() +{ +#if defined(SBUS_TRAINER) + // SBUS trainer + processSbusInput(); +#endif + +#if defined(GYRO) + gyro.wakeup(); +#endif + +#if defined(BLUETOOTH) + bluetooth.wakeup(); +#endif +} + uint32_t nextMixerTime[NUM_MODULES]; TASK_FUNCTION(mixerTask) @@ -122,21 +141,13 @@ TASK_FUNCTION(mixerTask) #endif while (true) { -#if defined(SBUS_TRAINER) - // SBUS trainer - processSbusInput(); -#endif - -#if defined(GYRO) - gyro.wakeup(); -#endif - -#if defined(BLUETOOTH) - bluetooth.wakeup(); -#endif - - // run mixer at least every 30ms - bool timeout = mixerSchedulerWaitForTrigger(30); + for (int timeout = 0; timeout < MIXER_MAX_PERIOD; timeout += MIXER_FREQUENT_ACTIONS_PERIOD) { + bool interruptedByTimeout = mixerSchedulerWaitForTrigger(MIXER_FREQUENT_ACTIONS_PERIOD); + execMixerFrequentActions(); + if (!interruptedByTimeout) { + break; + } + } #if defined(DEBUG_MIXER_SCHEDULER) GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); @@ -205,10 +216,6 @@ TASK_FUNCTION(mixerTask) // TODO: // - check the cause of timeouts when switching // between protocols with multi-proto RF -#if defined(DEBUG) - if (timeout) - serialPrint("mix sched timeout!"); -#endif } } } From 25c7392d43dd8aa63972686d1e414f84312b8cd8 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 27 Apr 2021 21:30:21 +0200 Subject: [PATCH 27/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index af5a6c0e7..6e1770037 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2246,3 +2246,4 @@ eDefine Mario Sette Hans-Georg Böhm Robert Oats +Helmut Suhrbier From 22f515580313c3e43cc78467ae3d7b87a1f0cbfc Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 28 Apr 2021 15:19:24 +0200 Subject: [PATCH 28/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 6e1770037..b6a2875e0 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2247,3 +2247,4 @@ Mario Sette Hans-Georg Böhm Robert Oats Helmut Suhrbier +Johannes Vorster From e6fbce0772dd5b8759acf509136c390e77e9cd38 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 28 Apr 2021 15:55:18 +0200 Subject: [PATCH 29/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index b6a2875e0..cca0aad20 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2248,3 +2248,4 @@ Hans-Georg Böhm Robert Oats Helmut Suhrbier Johannes Vorster +Deon du Rand From c8a2d279d53cc52aa34ae0f2bae39e23f13c7b5b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 30 Apr 2021 19:46:27 +0200 Subject: [PATCH 30/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index cca0aad20..592206e07 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2249,3 +2249,4 @@ Robert Oats Helmut Suhrbier Johannes Vorster Deon du Rand +Stephen Hill-Harriss From e14d54fd03836fe1b7aa6a07c199ceb0bdd69036 Mon Sep 17 00:00:00 2001 From: Richard Li Date: Mon, 3 May 2021 02:31:56 +0800 Subject: [PATCH 31/70] Fixed TX16S non-smooth sound play during power on. --- radio/src/audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index 04ff8a8b2..611d1757a 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -524,7 +524,7 @@ void audioTask(void * pdata) setSampleRate(AUDIO_SAMPLE_RATE); -#if defined(PCBX12S) +#if defined(PCBX12S) || defined(RADIO_TX16S) // The audio amp needs ~2s to start RTOS_WAIT_MS(1000); // 1s #endif From ff6afeabbf59a2b2babb512c02b7abda0baa8ef1 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 3 May 2021 08:31:12 +0200 Subject: [PATCH 32/70] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 592206e07..ac57c3e3a 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2250,3 +2250,5 @@ Helmut Suhrbier Johannes Vorster Deon du Rand Stephen Hill-Harriss +Regi Pradeeswaran +Gary Busler From 8ff09161942b1c1d39c47889ebbe7228eaef8af1 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 3 May 2021 08:31:54 +0200 Subject: [PATCH 33/70] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index ac57c3e3a..b60d74b96 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2252,3 +2252,5 @@ Deon du Rand Stephen Hill-Harriss Regi Pradeeswaran Gary Busler +Stefano Boggia + From 5253b97191bb5cc1b5229d3ba9be0c4a88ca5dde Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 5 May 2021 09:01:48 +0200 Subject: [PATCH 34/70] Update CREDITS.txt --- CREDITS.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CREDITS.txt b/CREDITS.txt index b60d74b96..bfffa5489 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2253,4 +2253,5 @@ Stephen Hill-Harriss Regi Pradeeswaran Gary Busler Stefano Boggia - +Vernon Martin +Alexander W Wilson Jr From de0a5f5d32e631522548792b6632959894fa99aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BE=E3=81=A3=E3=81=8F=20=E3=81=BE=E3=82=8B=E3=81=A1?= =?UTF-8?q?=E3=81=B7=E3=82=8D=E3=81=A8=E3=81=93=E3=82=8B?= <36994795+ToshihiroMakuuchi@users.noreply.github.com> Date: Wed, 5 May 2021 19:13:37 +0900 Subject: [PATCH 35/70] Update Japanese translation. (#8479) --- companion/src/translations/companion_ja.ts | 1590 ++++++++++---------- 1 file changed, 832 insertions(+), 758 deletions(-) diff --git a/companion/src/translations/companion_ja.ts b/companion/src/translations/companion_ja.ts index d423959d4..e276a2539 100644 --- a/companion/src/translations/companion_ja.ts +++ b/companion/src/translations/companion_ja.ts @@ -830,127 +830,127 @@ Mode 4: ChannelsPanel - + Name 名称 - + Subtrim サブトリム - + Min 最小 - + Max 最大 - + Direction 方向 - + Curve カーブ - + PPM Center PPM センター - + Linear Subtrim 線形サブトリム - + CH%1 CH%1 - + Popup menu available 利用可能なポップアップメニュー - + --- --- - + INV リバース - + Delete Channel. Are you sure? チャンネルを削除します。よろしいですか? - + Cut Channel. Are you sure? チャンネルを切り取ります。よろしいですか? - + Copy コピー - + Cut 切り取り - + Paste 貼り付け - + Clear 消去 - + Insert 挿入 - + Delete 削除 - + Move Up 上へ移動 - + Move Down 下へ移動 - + Clear All すべて消去 - + Clear Channel. Are you sure? チャンネルを消去します。よろしいですか? - + Clear all Channels. Are you sure? チャンネルをすべて消去します。よろしいですか? @@ -1090,37 +1090,37 @@ Mode 4: 送信機と機体モデルの設定 - + Select or create a file for exported Settings: エクスポートした設定ファイルを選択または作成します: - + Press the 'Retry' button to choose another file. 別のファイルを選択するには『再試行』ボタンを押してください。 - + Simulator for this firmware is not yet available このファームウェアのシミュレータはまだ利用できません - + Uknown error during Simulator startup. シミュレータ起動中に不明なエラーが発生しました。 - + Simulator Error シミュレータ エラー - + Data Load Error データロード エラー - + Error occurred while starting simulator. シミュレータ起動中にエラーが発生しました。 @@ -1370,7 +1370,7 @@ If you have a settings backup file, you may import that instead. CurveData - + CV CV @@ -1603,219 +1603,297 @@ If you have a settings backup file, you may import that instead. CustomFunctionData - + GF GF - + SF SF - + Override %1 上書き %1 - + Trainer Sticks トレーナー Sticks - + Trainer RUD トレーナー RUD - + Trainer ELE トレーナー ELE - + Trainer THR トレーナー THR - + Trainer AIL トレーナー AIL - + Trainer Channels トレーナー チャンネル - + Instant Trim トリム - + Play Sound サウンド 再生 - + Haptic - タッチパネル + バイブレーション - + Reset リセット - + Set %1 設定 %1 - + + Lua Script + Luaスクリプト + + + Set Failsafe フェイルセーフ設定 - + + Range Check Int. Module + 内部モジュール レンジチェック + + + + Range Check Ext. Module + 外部モジュール レンジチェック + + + + Beep 1 + ビープ 1 + + + + Beep 2 + ビープ 2 + + + + Beep 3 + ビープ 3 + + + + Warn 1 + 警告 1 + + + + Warn 2 + 警告 2 + + + + Cheep + チープ + + + + Ratata + ラッタッタ + + + + Tick + ティック + + + + Siren + サイレン + + + + Ring + リング + + + + Sci Fi + Sci Fi + + + + Robot + ロボット + + + + Chirp + + + + + Tada + Tada + + + + Cricket + クリケット + + + + Alarm Clock + アラームクロック + + + + Value + 値 + + + + Source + 選択元 + + + + Global Variable + グローバル変数 + + + + Inc/Decrement + 増/減 + + + Vario バリオ - + Play Track トラック 再生 - + Play Both 両方 実行 - + Play Value 値 実行 - - Play Script - スクリプト 実行 - - - + SD Logs SDログ - + Volume 音量 - + Backlight バックライト - + Screenshot 画面キャプチャ - + Background Music BGM - + Background Music Pause BGM一時停止 - + Adjust %1 調整 %1 - - RangeCheck Int. Module - レンジチェック 内部モジュール - - - - RangeCheck Ext. Module - レンジチェック 外部モジュール - - - + Bind Int. Module バインド 内部モジュール - + Bind Ext. Module バインド 外部モジュール - + + Played once, not during startup + 起動時以外 1回実行 + + + + No repeat + リピートなし + + + + Repeat %1s + リピート %1秒 + + + Flight フライト - + Telemetry テレメトリー - - Rotary Encoder - エンコーダ再生 - - - - REa - エンコーダ再生a - - - - REb - エンコーダ再生b - - - + s s - - - - <font color=red><b>Inconsistent parameter</b></font> - <font color=red><b>矛盾しているパラメータ</b></font> - - - - Value - 値 - - - - played once, not during startup - 起動時以外 1回実行 - - - - repeat(%1s) - リピート(%1s) - - - + DISABLED 無効 - + CFN CFN @@ -1823,142 +1901,122 @@ If you have a settings backup file, you may import that instead. CustomFunctionsPanel - + Switch スイッチ - + Action 実行 - + Parameters パラメータ - - Enable - 有効 - - - + Popup menu available 利用可能なポップアップメニュー - + SF%1 SF%1 - + GF%1 GF%1 - + + GV + GV + + + ON ON - + Error occurred while trying to play sound, possibly the file is already opened. (Err: %1 [%2]) サウンド再生中にエラーが発生しました。おそらくファイルは既に開かれています (Err: %1 [%2]) - + Unable to find or open sound file: %1 音源ファイルが見つからない、または開けません。 %1 - + Delete Function. Are you sure? ファンクションを削除します。よろしいですか? - + Cut Special Function. Are you sure? ファンクションを切り取ります。よろしいですか? - + Clear Function. Are you sure? ファンクションを消去します。よろしいですか? - + Clear all Functions. Are you sure? ファンクションをすべて消去します。よろしいですか? - + Copy コピー - + Cut 切り取り - + Paste 貼り付け - + Clear 消去 - + Insert 挿入 - + Delete 削除 - + Move Up 上へ移動 - + Move Down 下へ移動 - + Clear All すべて消去 - - - Value - 値 - - - - Source - 選択元 - - - - GVAR - GVAR - - - - Increment - 増加 - CustomizeSplashDialog @@ -2164,11 +2222,64 @@ If you have a settings backup file, you may import that instead. このボード上のOpenTXはこの機能を受け付けません - + OpenTX doesn't accept this radio protocol OpenTXはこの送信機プロトコルを受け付けません + + DataHelpers + + + Disabled + 無効 + + + + Enabled + 有効 + + + + OFF + OFF + + + + ON + ON + + + + False + False + + + + True + True + + + + N + N + + + + Y + Y + + + + No + いいえ + + + + Yes + はい + + DebugOutput @@ -2374,12 +2485,12 @@ To <b>remove a remembered entry</b> from the filter list, first cho ExpoData - + INP INP - + (@%1) (@%1) @@ -2501,22 +2612,22 @@ If blank then the input is considered to be "ON" all the time.編集 %1 - + Popup menu available 利用可能なポップアップメニュー - + Clear All すべて消去 - + Set All すべて設定 - + Invert All すべてリバース @@ -2605,129 +2716,129 @@ If blank then the input is considered to be "ON" all the time. FileSyncDialog - + Synchronize Files ファイルを同期する - + Are you sure you wish to abort the sync? 同期を中止してよろしいですか? - + Source Folder: 移動元フォルダ: - + Destination Folder: 移動先フォルダ: - + %1%2 Both directions, to destination folder first %1%2の両方を最初の移動先フォルダへ - + %1%2 Both directions, to source folder first %1%2の両方を最初の移動元フォルダへ - + %1 Only from source folder to destination folder %1 移動元フォルダから移動先フォルダのみ - + %1 Only from destination folder to source folder %1 移動先フォルダから移動元フォルダのみ - + How to handle overwriting files which already exist in the destination folder. コピー先フォルダに既に存在するファイルを上書きする方法となります。 - + Copy only if newer and different (compare contents) 新しい場合、または異なる場合のみコピー (内容を比較して) - + Copy only if newer (do not compare contents) 新しい場合のみコピー (内容を比較しない) - + Copy only if different (ignore file time stamps) 異なる場合のみコピー (ファイルのタイムスタンプを無視) - + Always copy (force overwite existing files) 常にコピー (既存のファイルを強制上書き) - + Any size 任意のサイズ - + Skip files larger than this size. Enter zero for unlimited. このサイズより大きいファイルをスキップします。無制限の場合はゼロを入力してください。 - + Minimum reporting level. Events of this type and of higher importance are shown. WARNING: High log rates may make the user interface temporarily unresponsive. 最小レポートレベル このような種類の重要度の高いイベントが表示されます。 警告: ログレベルが高いと、ユーザーインターフェースが一時的に応答しなくなる場合があります。 - + Skipped スキップ - + Created 作成 - + Updated 更新 - + Errors Only エラーのみ - + Test-run only テスト稼働のみ - + Run as normal but do not actually copy anything. Useful for verifying results before real sync. 通常通りに実行しますが、実際には何もコピーしません。実際の同期前に結果を検証するのに役立ちます。 - + Log Level: ログレベル: - + Filters: フィルター: - + The "Include" filter will only copy files which match the pattern(s). The "Exclude" filter will skip files matching the filter pattern(s). The Include filter is evaluated first. @@ -2736,148 +2847,148 @@ The Include filter is evaluated first. Includeフィルターが最初に設定されます。 - + One or more file pattern(s) to exclude, separated by commas. Blank means exclude none. ?, *, and [...] wildcards accepted. 除外する1つ以上のファイルパターンでカンマで区切ります。 空白は何も除外しないことを意味します。 ?, *, および [...] ワイルドカードを使用できます。 - + One or more file pattern(s) to include, separated by commas. Blank means include all. ?, *, and [...] wildcards accepted. 含める1つまたは複数のファイルパターン。カンマで区切ります。 空白は何も除外しないことを意味します。 ?, *, および [...] ワイルドカードを使用できます。 - + Include: - + Exclude: - + Case sensitive 敏感なケース - - + + Follow links フォローリンク - + Include hidden 非表示にする - + Recursive 回帰的 - + Skip empty 空をスキップ - + Apply filters フィルター実行 - + Filter Options: フィルターオプション: - + Folder Options: フォルダーオプション: - - + + Options オプション - + Show extra options 追加オプションを表示 - + Reset to defaults 初期値へリセット - + Close 閉じる - + Sync. Direction: 方向の同期: - + Existing Files: 既存のファイル: - + Max. File Size: 最大ファイルサイズ: - + MB MB - + KB KB - + Abort バージョン情報 - + Start スタート - + Total: <b>%1</b>; Created: <b>%2</b>; Updated: <b>%3</b>; Skipped: <b>%4</b>; Errors: <font color=%6><b>%5</b></font>; Total: <b>%1</b>; 作成: <b>%2</b>; アップデート: <b>%3</b>; スキップ: <b>%4</b>; エラー: <font color=%6><b>%5</b></font>; - + Current: <b>%1</b> of 現在: <b>%1</b> - + Source folder not found. 移動元フォルダが見つかりません。 - + Destination folder not found. 移動先フォルダが見つかりません。 - + Source and destination folders are the same. 移動元と移動先のフォルダは同じです。 @@ -2975,7 +3086,7 @@ Blank means include all. ?, *, and [...] wildcards accepted. Haptic module installed - タッチパネル対応モジュールをインストール + バイブレーション対応モジュールをインストール @@ -3660,7 +3771,7 @@ You are currently using: FlightModeData - + FM FM @@ -4131,12 +4242,12 @@ p, li { white-space: pre-wrap; } - + Own value 独自トリム - + Flight mode %1 value フライトモード %1 値 @@ -4625,7 +4736,7 @@ p, li { white-space: pre-wrap; } Haptic Mode - タッチパネルモード + バイブレーションモード @@ -4758,16 +4869,6 @@ p, li { white-space: pre-wrap; } Optrex オプトレックス(京セラ) - - - Battery warning voltage. -This is the threashhold where the battery warning sounds. - -Acceptable values are 5v..10v - バッテリー警告電圧 -これはバッテリー警告音のしきい値です。 -許容値は5~10vです - Only Alarms @@ -4781,7 +4882,7 @@ Acceptable values are 5v..10v Haptic Length - タッチパネル長押し + バイブレーション時間 @@ -4801,7 +4902,7 @@ Acceptable values are 5v..10v Haptic Strength - タッチパネル感度 + バイブレーション強度 @@ -5004,6 +5105,16 @@ Acceptable values are 5v..10v A T E R ↔AIL ↕THR ↕ELE ↔RUD [A T E R] + + + Battery warning voltage. +This is the threashhold where the battery warning sounds. + +Acceptable values are 3v..12v + バッテリー警告電圧 +これはバッテリー警告音がなる3つの電圧しきい値です。 +許容値は3~12vです + Power Off Delay @@ -5727,27 +5838,27 @@ Are you sure ? InputsPanel - - + + Move Up 上へ移動 - + Ctrl+Up - - + + Move Down 下へ移動 - + Ctrl+Down @@ -5772,131 +5883,131 @@ Are you sure ? 選択したInput行を切り取ります。よろしいですか? - + Lines 直線 - + &Add &追加 - + Ctrl+A - + &Edit &編集 - + Enter Enter - + &Delete &削除 - - + + Delete 削除 - + &Copy &コピー - + Ctrl+C - + &Cut &切り取り - + Ctrl+X - + &Paste &貼り付け - + Ctrl+V - + Du&plicate &複製 - + Ctrl+U - + Input 入力 - + Insert 挿入 - + Clear 消去 - + Clear All すべて消去 - + Clear all Input lines. Are you sure? すべてのInput行を消去します。よろしいですか? - - Clear all lines for the selected Inputs. Are you sure? + + Clear all lines for the selected Input. Are you sure? 選択したすべてのInput行を消去します。よろしいですか? - - Delete all lines for the selected Inputs. Are you sure? + + Delete all lines for the selected Input. Are you sure? 選択したすべてのInput行を削除します。よろしいですか? LimitData - + INV リバース - + NOR ノーマル - + CH CH @@ -5904,7 +6015,7 @@ Are you sure ? LimitsGroup - + GV @@ -7658,12 +7769,12 @@ Do you want to save your changes? MixData - + MIX ミックス - + (@%1) @@ -7880,22 +7991,22 @@ If blank then the mix is considered to be "ON" all the time. - + Click to access popup menu クリックしてポップアップメニューにアクセス - + Clear All すべて消去 - + Set All すべて設定 - + Invert All すべてリバース @@ -7927,25 +8038,25 @@ If blank then the mix is considered to be "ON" all the time. MixesPanel - + Move Up 上へ移動 - + Ctrl+Up - + Move Down 下へ移動 - + Ctrl+Down @@ -7970,92 +8081,92 @@ If blank then the mix is considered to be "ON" all the time. 選択したMix行を切り取ります。よろしいですか? - + &Add &追加 - + Ctrl+A - + &Edit &編集 - + Enter Enter - + &Toggle highlight &ハイライト切替 - + Ctrl+T - + &Delete &削除 - + Delete 削除 - + &Copy &コピー - + Ctrl+C - + C&ut &切り取り - + Ctrl+X - + &Paste &貼り付け - + Ctrl+V - + Du&plicate &複製 - + Ctrl+U - + Clear Mixes? ミキサーを消去しますか? - + Really clear all the mixes? すべてのミキサーを本当に消去しますか? @@ -8063,17 +8174,17 @@ If blank then the mix is considered to be "ON" all the time. ModelData - + Model: 機体モデル: - + Throttle Source スロットル値 - + THR THR @@ -8091,52 +8202,52 @@ If blank then the mix is considered to be "ON" all the time. シミュレート - + Setup セットアップ - + Heli ヘリ - + Flight Modes フライトモード - + Inputs 入力 - + Mixes ミキサー - + Outputs 出力 - + Curves カーブ - + Logical Switches 論理スイッチ - + Special Functions スペシャルファンクション - + Telemetry テレメトリー @@ -8190,9 +8301,8 @@ If blank then the mix is considered to be "ON" all the time. - - - + + OFF OFF @@ -8233,7 +8343,7 @@ If blank then the mix is considered to be "ON" all the time. - + Mode モード @@ -8267,13 +8377,13 @@ If blank then the mix is considered to be "ON" all the time. - + Delay 遅延 - + Receiver 受信機 @@ -8365,397 +8475,342 @@ If blank then the mix is considered to be "ON" all the time. - - - - + + + + None なし - - - Name - 名称 - - Countdown - カウントダウン - - - - Minute call - 音声時報 - - - - Persistent - 持続 - - - - - + + FM%1 - + FM%1%2 - + FM%1+%2 - - + + NoTrim トリムなし - - + + Offset(%1) オフセット(%1) - + MULT! 複数! - + No DR/Expo DR/Expoなし - - + + Weight(%1) ウェイト(%1) - - + + Switch(%1) スイッチ(%1) - + Delay(u%1:d%2) 遅延(u%1:d%2) - + Slow(u%1:d%2) 速度低下(u%1:d%2) - + Warn(%1) 警告(%1) - + Disabled in all flight modes すべてのフライトモードを無効 - + Flight modes フライトモード - + Flight mode フライトモード - + All すべて - + Edge Edge:端 - + instant 簡易 - + Sticky Sticky:追尾 - + Timer タイマー - + missing 間違い - + Duration 期間 - - + + Custom カスタム - + Standard 標準 - + Extended Limits 拡張制限 - + Display Checklist ディスプレイ チェックリスト - + Global Functions グローバルファンクション - + Manual 手動 - + Auto 自動 - + Failsafe Mode フェイルセーフモード - - + + Hold ホールド - + No Pulse パルスなし - + Not set セットなし - + No pulses パルスなし - - Silent - 消音 - - - - Beeps - ビープ - - - - Voice - 音声 - - - - Haptic - タッチパネル - - - - Flight - フライト - - - - Manual reset - 手動リセット - - - + Step ステップ - + Display ディスプレイ - + Extended 拡張 - + Never なし - + On Change 変更 - + Always 常に - - - + + + Source 選択元 - + Trim idle only トリムアイドルのみ - + Warning 警告 - + Reversed リバース - - Tmr - Tmr - - - + FrSky S.PORT - + FrSky D - + FrSky D (cable) - + Alti - + Alti+ - + VSpeed - - - + + + A1 - - - + + + A2 - - + + A3 - - + + A4 - - + + FAS - + Cells セル - + Min 最小 - + Max 最大 - + Numbers ナンバー - + Bars バー - + Script スクリプト - + Filename ファイル名 - + Error: Unable to open or read file! エラー: ファイルを開けないか、読み取れません! @@ -9018,33 +9073,38 @@ If blank then the mix is considered to be "ON" all the time. マスター/Multi - + Disable Telemetry テレメトリー無効 - + + Racing Mode + レーシングモード + + + Disable Ch. Map チャンネルマップ無効 - + Failsafe Positions フェイルセーフポジション - + Show values in: 値の表示: - + % abbreviation for percent - + μs abbreviation for microseconds @@ -9053,100 +9113,100 @@ If blank then the mix is considered to be "ON" all the time. ModuleData - + Trainer Port トレーナーポート - + Internal Radio System 内部送信システム - + External Radio Module 外部送信モジュール - + Extra Radio System 追加送信システム - + Radio System 送信システム - + 10mW - 16CH - - + + 100mW - 16CH - + 500mW - 16CH - + Auto <= 1W - 16CH - - + + 25mW - 8CH - - + + 25mW - 16CH - + 200mW - 16CH (no telemetry) 200mW - 16CH (テレメトリーなし) - + 500mW - 16CH (no telemetry) 500mW - 16CH (テレメトリーなし) - + 100mW - 16CH (no telemetry) 100mW - 16CH (テレメトリーなし) - + 25 mW 25 mW - + 100 mW 100 mW - + 500 mW 500 mW - + 1 W 1 W - + 2 W 2 W @@ -9164,42 +9224,42 @@ If blank then the mix is considered to be "ON" all the time. ModulePanel - + Value 値 - + Hold ホールド - + No Pulse パルスなし - + Ask 確認 - + Internal 内部 - + Internal + External 内部 + 外部 - + External 外部 - + Bind on channel チャンネルへバインド @@ -9213,8 +9273,8 @@ If blank then the mix is considered to be "ON" all the time. - - + + Name 名称 @@ -9270,7 +9330,7 @@ If blank then the mix is considered to be "ON" all the time. - + Switch スイッチ @@ -9290,313 +9350,318 @@ If blank then the mix is considered to be "ON" all the time. 持続 - + + Start + スタート + + + Modules モジュール - + Trainer port トレーナーポート - + Helicopter ヘリコプター - + Swash Swash - - + + Type タイプ - + Ring リング - + Input 入力 - + Weight ウェイト - + Long. cyc 長周期 - + Lateral cyc 側面周期 - + Collective コレクティブ - + Flight modes フライトモード - - + + Flight mode フライトモード - + F.In F.In - + F.Out F.Out - + Global vars グローバル変数 - - + + GV%1 GV%1 - + RE%1 RE%1 - + Unit ユニット - + Prec 精度 - - + + Min 最小 - - + + Max 最大 - + Popup ポップアップ - + Outputs 出力 - + Channel チャンネル - + Subtrim サブトリム - + Direct ダイレクト - + Curve カーブ - + PPM PPM - + Linear 線形 - + Global Variables グローバル変数 - + Inputs 入力 - + Mixers ミキサー - + Curves カーブ - + L%1 L%1 - + Logical Switches 論理スイッチ - + SF%1 SF%1 - + Special Functions スペシャルファンクション - + Telemetry テレメトリー - + Protocol プロトコル - + RSSI Alarms RSSIアラーム - + Low 低 - + Critical クリティカル - + Telemetry audio テレメトリー音源 - + Altimetry 高度計 - - + + Vario source バリオ 元値 - + Vario limits > バリオ リミット値 > - + Sink max Sink 最大 - + Sink min Sink 最小 - + Climb min クライム 最小 - + Climb max クライム 最大 - + Center silent センター サイレント - + Top Bar トップバー - + Volts source ボルト 元値 - + Altitude source 高度 元値 - + Parameters パラメータ - + Telemetry Sensors テレメトリーセンサー - + Telemetry Screens テレメトリースクリーン - + GF%1 GF%1 - + Global Functions グローバルファンクション - + Checklist チェックリスト @@ -9838,12 +9903,12 @@ If blank then the mix is considered to be "ON" all the time. QObject - + WARNING 警告 - + <p>Importing JumperTX data into OpenTX 2.3 is <b>not supported and dangerous.</b></p> <p>It is unfortunately not possible for us to differentiate JumperTX data from legitimate FrSky X10 data, but <b>You should only continue here if the file you opened comes from a real FrSky X10.</b></p> <p>Do you really want to continue?</p> <p>JumperTXデータをOpenTX 2.3にインポートすることは<b>サポート対象外となり危険な行為です。</b></p> <p>残念ながら、JumperTXデータを正当なFrSky X10データと区別することができませんが、<b>開いたファイルが実際のFrSky X10で生成されたものである場合にのみ、続行する事ができます。</b></p> <p>本当に続行しますか?</p> @@ -9851,7 +9916,7 @@ If blank then the mix is considered to be "ON" all the time. RadioData - + Models 機体モデル @@ -10418,24 +10483,6 @@ X OpenTX リリースノート - - RepeatComboBox - - - Played once, not during startup - 起動時以外 1回実行 - - - - No repeat - リピートなし - - - - %1s - %1秒 - - RudderPage @@ -10474,327 +10521,322 @@ X SensorData - + Formula 定式 - + Id ID - + Instance インスタンス - - + + Sensor センサー - + Sources 選択元 - + GPS GPS - + Alt 高度 - + Unit ユニット - + Precision 精度 - + Ratio レシオ - + Offset オフセット - + Auto Offset 自動オフセット - + Blades ブレード - + Multiplier 乗算 - + Filter フィルター - + Persist 持続 - + Positive ノーマル - + Log ログ - + Custom カスタム - + Calculated 計算値 - + Add 追加 - + Average 平均 - + Minimum 最低値 - + Maximum 最大値 - + Multiply 乗算 - + Totalize 合計 - + Cell セル - + Consumption 消費 - + Distance 距離 - + Lowest より低く - + Cell %1 セル %1 - + Highest より高く - + Delta 差分 - + Raw (-) Raw (-) - - + + V V - + A - + mA - + kts - + m/s - + km/h - + mph - + m - + f - + °C - + °F - + % - + mAh - + W - + mW - + dB - + rpms - + g - + ° - + Rad - + hours - + minutes - + seconds - + ml/minute - + Hertz - + mS - + uS - + + (default) + (初期値) + + + TELE - - - Y - Y - - - - N - N - Setup @@ -10976,92 +11018,87 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi SetupPanel - + Popup menu available 利用可能なポップアップメニュー - + Timer %1 タイマー %1 - - THR - - - - + Profile Settings プロファイル設定 - + SD structure path not specified or invalid SDカード保存先パスが指定されていないか無効です - + Copy コピー - + Cut 切り取り - + Paste 貼り付け - + Clear 消去 - + Insert 挿入 - + Delete 削除 - + Move Up 上へ移動 - + Move Down 下へ移動 - + Clear All すべて消去 - + Clear Timer. Are you sure? タイマーを消去します。よろしいですか? - + Clear all Timers. Are you sure? タイマーをすべて消去します。よろしいですか? - + Cut Timer. Are you sure? タイマーを切り取ります。よろしいですか? - + Delete Timer. Are you sure? タイマーを削除します。よろしいですか? @@ -12515,22 +12552,22 @@ Too many errors, giving up. 最大 - + None なし - + Numbers ナンバー - + Bars バー - + Script スクリプト @@ -12538,52 +12575,52 @@ Too many errors, giving up. TelemetryPanel - + Telemetry screen %1 テレメトリースクリーン %1 - + FrSky S.PORT - + FrSky D - + FrSky D (cable) - + Source 信号元 - + Low Alarm 低アラーム - + Critical Alarm クリティカルアラーム - + Winged Shadow How High Winged Shadow How High - + Winged Shadow How High (not supported) Winged Shadow How High (サポートなし) - + Delete Sensor. Are you sure? テレメトリーセンサーを削除します。よろしいですか? @@ -12701,72 +12738,72 @@ Too many errors, giving up. TelemetrySensorPanel - + TELE%1 - + Popup menu available 利用可能なポップアップメニュー - + Copy コピー - + Cut 切り取り - + Paste 貼り付け - + Clear 消去 - + Insert 挿入 - + Delete 削除 - + Move Up 上へ移動 - + Move Down 下へ移動 - + Clear All すべて消去 - + Cut Telemetry Sensor. Are you sure? テレメトリーセンサーを切り取ります。よろしいですか? - + Clear Telemetry Sensor. Are you sure? テレメトリーセンサーを消去します。よろしいですか? - + Clear all Telemetry Sensors. Are you sure? テレメトリーセンサーのすべてを消去します。よろしいですか? @@ -13140,7 +13177,12 @@ hh:mm:ss カウントダウン - + + Start + スタート + + + Minute Call 音声時報 @@ -13148,21 +13190,91 @@ hh:mm:ss TimerData - + TMR TMR - + Timer %1 タイマー %1 - + TMR as in Timer TMR + + + Silent + 消音 + + + + Beeps + ビープ + + + + Voice + 音声 + + + + Haptic + バイブレーション + + + + 5s + 5秒 + + + + 10s + 10秒 + + + + 20s + 20秒 + + + + 30s + 30秒 + + + + Not persistent + 持続なし + + + + NOT + なし + + + + Persistent (flight) + 持続 (フライト) + + + + Flight + フライト + + + + Persistent (manual reset) + 持続 (手動リセット) + + + + Manual reset + 手動リセット + TimerEdit @@ -13189,44 +13301,6 @@ CTRL+スクロールまたはPAGE UP/DOWNキーを押すと、大きなステ 秒 - - TimerPanel - - - Silent - 消音 - - - - Beeps - ビープ - - - - Voice - 音声 - - - - Haptic - タッチパネル - - - - Not persistent - 持続なし - - - - Persistent (flight) - 持続 (フライト) - - - - Persistent (manual reset) - 持続 (手動リセット) - - Trainer From c06b789f5c16f7bcb197003351fb1f68e30b12e1 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 5 May 2021 15:46:29 +0200 Subject: [PATCH 36/70] Multi module config support (#8438) * Multi module configuration Co-authored-by: Pascal Langer --- CMakeLists.txt | 2 +- .../sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt | 26 +- .../sdcard/horus/SCRIPTS/TOOLS/MultiLOLI.lua | 221 ++++++++ radio/sdcard/horus/THEMES/Flexi/ghost.png | Bin 0 -> 2504 bytes .../horus/UTILITIES/MultiConfigExternal.lua | 499 ++++++++++++++++++ .../horus/UTILITIES/MultiConfigInternal.lua | 499 ++++++++++++++++++ .../SxR Calibrate/SxR_Calibrate.lua | 0 .../SxR Calibrate/img/back.png | Bin .../SxR Calibrate/img/delta_b.png | Bin .../SxR Calibrate/img/done.bmp | Bin .../SxR Calibrate/img/down.png | Bin .../SxR Calibrate/img/forward.png | Bin .../SxR Calibrate/img/left.png | Bin .../SxR Calibrate/img/plane_b.png | Bin .../SxR Calibrate/img/planev_b.png | Bin .../SxR Calibrate/img/planev_s.png | Bin .../SxR Calibrate/img/right.png | Bin .../{ => UTILITIES}/SxR Calibrate/img/up.png | Bin .../SxR Calibrate/img/vert-r.png | Bin .../SxR Calibrate/img/vert.png | Bin .../taranis-x7/SCRIPTS/TOOLS/MultiChan.txt | 26 +- .../taranis-x7/SCRIPTS/TOOLS/MultiLOLI.lua | 221 ++++++++ .../UTILITIES/MultiConfigExternal.lua | 499 ++++++++++++++++++ .../UTILITIES/MultiConfigInternal.lua | 499 ++++++++++++++++++ .../SxR Calibrate/SxR_Calibrate.lua | 0 .../taranis-x9/SCRIPTS/TOOLS/MultiChan.txt | 26 +- .../taranis-x9/SCRIPTS/TOOLS/MultiLOLI.lua | 221 ++++++++ .../UTILITIES/MultiConfigExternal.lua | 499 ++++++++++++++++++ .../UTILITIES/MultiConfigInternal.lua | 499 ++++++++++++++++++ .../SxR Calibrate/SxR_Calibrate.lua | 0 .../SxR Calibrate/bmp/back.bmp | Bin .../SxR Calibrate/bmp/delta.bmp | Bin .../SxR Calibrate/bmp/done.bmp | Bin .../SxR Calibrate/bmp/down.bmp | Bin .../SxR Calibrate/bmp/forward.bmp | Bin .../SxR Calibrate/bmp/horz-r.bmp | Bin .../SxR Calibrate/bmp/horz.bmp | Bin .../SxR Calibrate/bmp/left.bmp | Bin .../SxR Calibrate/bmp/plane.bmp | Bin .../SxR Calibrate/bmp/right.bmp | Bin .../{ => UTILITIES}/SxR Calibrate/bmp/up.bmp | Bin .../SxR Calibrate/bmp/vert-r.bmp | Bin .../SxR Calibrate/bmp/vert.bmp | Bin .../SxR Calibrate/bmp/vtail.bmp | Bin radio/src/gui/480x272/radio_tools.cpp | 2 +- radio/src/lua/api_model.cpp | 28 +- radio/src/pulses/modules_constants.h | 11 +- radio/src/pulses/modules_helpers.h | 2 +- radio/src/pulses/multi.cpp | 73 ++- radio/src/pulses/multi.h | 1 + radio/src/telemetry/multi.cpp | 39 +- radio/src/telemetry/telemetry.h | 2 + radio/src/translations/untranslated.h | 2 +- 53 files changed, 3864 insertions(+), 33 deletions(-) create mode 100644 radio/sdcard/horus/SCRIPTS/TOOLS/MultiLOLI.lua create mode 100644 radio/sdcard/horus/THEMES/Flexi/ghost.png create mode 100755 radio/sdcard/horus/UTILITIES/MultiConfigExternal.lua create mode 100755 radio/sdcard/horus/UTILITIES/MultiConfigInternal.lua rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/SxR_Calibrate.lua (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/back.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/delta_b.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/done.bmp (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/down.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/forward.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/left.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/plane_b.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/planev_b.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/planev_s.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/right.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/up.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/vert-r.png (100%) rename radio/sdcard/horus/{ => UTILITIES}/SxR Calibrate/img/vert.png (100%) create mode 100644 radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiLOLI.lua create mode 100644 radio/sdcard/taranis-x7/UTILITIES/MultiConfigExternal.lua create mode 100644 radio/sdcard/taranis-x7/UTILITIES/MultiConfigInternal.lua rename radio/sdcard/taranis-x7/{ => UTILITIES}/SxR Calibrate/SxR_Calibrate.lua (100%) create mode 100644 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiLOLI.lua create mode 100644 radio/sdcard/taranis-x9/UTILITIES/MultiConfigExternal.lua create mode 100644 radio/sdcard/taranis-x9/UTILITIES/MultiConfigInternal.lua rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/SxR_Calibrate.lua (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/back.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/delta.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/done.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/down.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/forward.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/horz-r.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/horz.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/left.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/plane.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/right.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/up.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/vert-r.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/vert.bmp (100%) rename radio/sdcard/taranis-x9/{ => UTILITIES}/SxR Calibrate/bmp/vtail.bmp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d23900bc..abd605745 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(VERSION_REVISION "12") set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) -set(SDCARD_REVISION "0036") +set(SDCARD_REVISION "0037") set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION}) cmake_minimum_required(VERSION 2.8) diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt index b03b2c860..305451422 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiChan.txt @@ -6,6 +6,7 @@ 14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop 14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop 59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video +59,1,BayangRX,CPPM,1,AnAux1,AnAux2,Flip,RTH,Pict,Video 41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED 42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED 42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol @@ -34,9 +35,9 @@ 6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill 6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill 70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH 45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH -45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH 16,0,ESKY,Std,0,Gyro,Pitch 16,1,ESKY,ET4,0,Gyro,Pitch 35,0,ESKY150,4CH,0 @@ -54,6 +55,7 @@ 28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 +56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 53,0,Height,5ch,0,Gear 53,1,Height,8ch,0,Gear,Gyro,Flap,Light 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 @@ -79,6 +81,8 @@ 65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 55,1,FrSkyRX,CloneTX,0 +55,2,FrSkyRX,EraseTX,0 +55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 58,0,FX816,P38,1 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib @@ -99,13 +103,14 @@ 26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib -57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess 2,1,Hubsan,H301,0,RTH,Light,Stab,Video 2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes 22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -71,0,JJRC345,Std,1,Flip,HLess,RTH +71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3 +71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3 49,0,KF606,Std,1,Trim 9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim 9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim @@ -122,6 +127,8 @@ 17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess +17,5,MT99XX,A180,0,3D_6G +17,6,MT99XX,Dragon,0,Mode,RTH 44,0,NCC1701,Std,1,Warp 77,0,OMP,M2,0,THold,IdleUp,6G_3D 60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 @@ -138,10 +145,11 @@ 72,0,Q90C,Std,0,FMode,VTX+ 74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK 50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 -21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 +21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8 19,0,Shenqi,Cycle,1 68,0,Skyartec,Std,0,CH5,CH6,CH7 11,0,SLT,V1,0,Gear,Pitch @@ -174,3 +182,11 @@ 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess 52,0,ZSX,280,1,Light +78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +79,0,WFLY2,RF20x,0,CH5,CH6,CH7,CH8,CH9,CH10 +80,0,E016Hv2,E016Hv2,1,TakLan,EmStop,Flip,Calib,HLess,RTH +81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE +82,0,LOLI,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe +83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR +84,0,JOYSWAY,Std,0 +85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/MultiLOLI.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiLOLI.lua new file mode 100644 index 000000000..4d309e37e --- /dev/null +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/MultiLOLI.lua @@ -0,0 +1,221 @@ + +local toolName = "TNS|Multi LOLI RX config|TNE" + +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local loli_nok = false +local channels={ { 768, "PWM", 100, 102, "PPM", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH1 + { 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH2 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH3 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH4 + { 102, "SBUS", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH5 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH6 + { 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH7 + { -768, "Servo", 0, -2048, "Switch", -100 } } -- CH8 + +local sel = 1 +local edit = false + +local blink = 0 +local BLINK_SPEED = 15 + +local function drawScreenTitle(title) + if LCD_W == 480 then + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, title, MENU_TITLE_COLOR) + else + lcd.drawScreenTitle(title, 0, 0) + end +end + +local function LOLI_Draw_LCD(event) + local line = 0 + + lcd.clear() + + --Display settings + local lcd_opt = 0 + if LCD_W == 480 then + drawScreenTitle("Multi - LOLI RX configuration tool") + x_pos = 152 + x_inc = 90 + y_pos = 40 + y_inc = 20 + else + x_pos = 5 + x_inc = 30 + y_pos = 1 + y_inc = 8 + lcd_opt = SMLSIZE + end + + --Multi Module detection + if loli_nok then + if LCD_W == 480 then + lcd.drawText(10,50,"The LOLI protocol is not selected...", lcd_opt) + else + --Draw on LCD_W=128 + lcd.drawText(2,17,"LOLI protocol not selected...",SMLSIZE) + end + return + end + + --Display current config + if LCD_W == 480 then + line = line + 1 + lcd.drawText(x_pos, y_pos+y_inc*line -2, "Channel", lcd_opt) + lcd.drawText(x_pos+x_inc, y_pos+y_inc*line -2, "Function", lcd_opt) + lcd.drawRectangle(x_pos-4, y_pos+y_inc*line -4 , 2*x_inc +2, 188) + lcd.drawLine(x_pos-4, y_pos+y_inc*line +18, x_pos-4 +2*x_inc +1, y_pos+y_inc*line +18, SOLID, 0) + lcd.drawLine(x_pos+x_inc -5, y_pos+y_inc*line -4, x_pos+x_inc -5, y_pos+y_inc*line -5 +188, SOLID, 0) + line = line + 1 + end + + local out + for i = 1, 8 do + out = getValue("ch"..(i+8)) + lcd.drawText(x_pos, y_pos+y_inc*line, "CH"..i, lcd_opt) + for j = 1, #channels[i], 3 do + if out > channels[i][j] then + if sel == i then + invert = INVERS + if edit == true then + blink = blink + 1 + if blink > BLINK_SPEED then + invert = 0 + if blink > BLINK_SPEED * 2 then + blink = 0 + end + end + end + else + invert = 0 + end + lcd.drawText(x_pos+x_inc, y_pos+y_inc*line, channels[i][j+1], lcd_opt + invert) + break + end + end + line = line + 1 + end +end + +local function LOLI_Change_Value(dir) + local pos = 0 + local out + --look for the current position + out = getValue("ch"..(sel+8)) + for j = 1, #channels[sel], 3 do + if out > channels[sel][j] then + pos = j + break + end + end + + --decrement or increment + if dir < 0 and pos > 1 then + pos = pos - 3 + elseif dir > 0 and pos + 3 < #channels[sel] then + pos = pos + 3 + else + return + end + + --delete all mixers for the selected channel + local num_mix = model.getMixesCount(sel-1 +8) + for i = 1, num_mix do + model.deleteMix(sel-1 +8, 0); + end + + --create new mixer + local source_max = getFieldInfo("cyc1") + + local val = { name = channels[sel][pos+1], + source = source_max.id - 1, -- MAX=100 on TX16S + weight = channels[sel][pos+2], + offset = 0, + switch = 0, + multiplex = 0, + curveType = 0, + curveValue = 0, + flightModes = 0, + carryTrim = false, + mixWarn = 0, + delayUp = 0, + delayDown = 0, + speedUp = 0, + speedDown = 0 } + model.insertMix(sel-1 +8, 0, val) +end + +local function LOLI_Menu(event) + if event == EVT_VIRTUAL_NEXT then + if edit == false then + -- not changing a value + if sel < 8 then + sel = sel + 1 + end + else + -- need to inc the value + LOLI_Change_Value(1) + end + elseif event == EVT_VIRTUAL_PREV then + if edit == false then + -- not changing a value + if sel > 1 then + sel = sel - 1 + end + else + -- need to dec the value + LOLI_Change_Value(-1) + end + elseif event == EVT_VIRTUAL_ENTER then + if edit == false then + edit = true + blink = BLINK_SPEED + else + edit = false + end + end +end + +-- Init +local function LOLI_Init() + local module_conf = model.getModule(0) + if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then + module_conf = model.getModule(1) + if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then + loli_nok = true + end + end +end + +-- Main +local function LOLI_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + return 2 + else + LOLI_Menu(event) + LOLI_Draw_LCD(event) + return 0 + end +end + +return { init=LOLI_Init, run=LOLI_Run } diff --git a/radio/sdcard/horus/THEMES/Flexi/ghost.png b/radio/sdcard/horus/THEMES/Flexi/ghost.png new file mode 100644 index 0000000000000000000000000000000000000000..cfec1cb355351dde67384e0488dddd8e08b9bf33 GIT binary patch literal 2504 zcmV;(2{-nMP)I}t7RcN(u9xYNwsMJ2GQ%dC_)e5C=b&A8F zPOTNE>d>)Ti+}!><8f0ZssQz!6|KP?K)z#kEJeuf1vR`zqiGAV({^ z2^7I+ZIP3OSrCh`XG5O5ec0JO$vQwXe( zx}Tik^9dHj&DR$!E1z=Wx9S;x zQ{v7OB9e~CK3_c1$K%wW61!Ll{9RONn@m*Un?m>zU=HwUDgRM_M08w=L~aG16T?ju zDNj94(!*;l&u_!*LOO+)-QogNs>_bnRq572%gaDo)$a#w^lYY(T-Cg zqEujU3eP#1D}-#Z4F_MASoDZiHaO8vlO-}=7JrwD`+;%57GSg1*K$$U4YI&omFPIh z*vJszXpGfus(3}#USAMrprF=W!xQZ5>PE=hm-DK zkSGzg*t;X?-W3TO!mZ6<1tA=Ew^$;-lYu+MPEtamM5f4kDLHsdLbZp+A~_OX z!Zp#@2z zY&s(9=0b6deM!JeFkO@K`LK>3!YC@F@U2~VZf6v~o ziztU5fg&>gau7Lg2Rb1XB!AN@|1>RnY4 z$>XZ{aQq;iVddmKz7|i(U|JV^k8ss-jQsqb){%H&fG4(f_XD-2yGdW>tKKpUgFJr* zYtA+B{j&{y6H)kEX*sv$=F=GHaI4sA;J%29J=2KY+7uD0r>F!YzZim@sZ839eUh|@ z^7BPrKWkc=qDaIgGR!nNSXM!v;h`}Ubdz}(_((*ZR7_Fo;&#KAhUi zyk0MZJf=?OfNWC-3bRw`x6e58RC^2aPS@i1`h-k3^ejlau_RtDz;DEN9Q_8wr`nsD zugI7_@;xS2k7SgeA0z3WWH3WsLRFk+io~gOBQm04P@jrw>G(r?Gj}%B;4{6HWMom~ z^Hb!@pujYbdZ5hi+G9ItmHh2^N&g&kbvHp?!e~hc?Tj(xJ(6mTAjdH13aYA~g zHYc_A`mAN!k(al*y_spJ;~zt&6s>g3$j;^I!DVEbCQY4zK_0{SjvNh~jM4mR;4w8p zk=j;QeV!boPFGU1Y1ErH5maR55a2M|n zIm$gdNe9~|9JXi)hbLGt)_`ZjkQpc~vq3DLrD6fx&d4>FBP%)p($cpM*WzBEN%wcQk zaO{zlG?kCxMpwH$kB3|%$`6&usn_~sGLVTNCXqy;ra9c}i%1|rRLFShZ&a)o6c5uS z3#j76Z^g4H|No+V&EPg`R>jl!rk;p+g%+cE~*ZLYKdw$#Xx8IdLQL6=an|7(Y zHpcUh_eWy7)_9$qgS@SkxrwO1M`gdgN$&M%zgx=wEBP_if4!7BJHNSdzfXH^yOjN2 z?th?-w;S9+MarDLM5Q)(rPgk?lsRjTyX3xJ(xzFGCK{vJ z!zithLD+5hiK8|RSqLSJLXBC=L= zyi~+`NX{_&$(2SyEyqvG2^69-tHgo)TFM+l9wG!@1AYul1U?~k&f%yo#r5KZ`bCBK zamTop3K`wlSIhl#T4y&%Sy1yTrsmCTm#5RAh`QTUyMo`#@!W4LwHPje#u24sGsh** z^mRG(S2i?A4BRntubiVR>794k&j)3XqWb$+oKFKQBxw31=>8{0o6#ce>i$0SSg5(s zX(H0cv^O!juZOQBc*OO(#jO6mb)`-^p2x|SZ>J`U`c%o{aK~ky-~0Ig1n@sy)bpeU SdHS{h0000 0 and b > 0 do + if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits + result = result + bitval -- set the current bit + end + bitval = bitval * 2 -- shift left + a = math.floor(a/2) -- shift right + b = math.floor(b/2) + end + return result +end + +local function Config_Send(page, line, value) + local i + i = (page*16) + line + multiBuffer( 5, i ) + for i = 1 , 6 , 1 do + multiBuffer( 5+i, value[i] ) + end + multiBuffer( 4, 1 ) +end + +local function Config_Release() + Module.protocol = InitialProtocol + model.setModule(1, Module) + + local i + for i = 3 , 0 , -1 do + multiBuffer( i, 0 ) + end +end + +local function Config_Page( ) + Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 }) +end + +local function Config_Draw_Edit( event ) + local i + local text + + if Menu[Focus].field_type == 0xD0 then + -- Editable Hex value + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 1 + Blink = 0 + for i = 1, Menu[Focus].field_len, 1 do + Menu_value[i] = Menu[Focus].field_value[i] + end + end + if Edit == 0 then + -- Not editing value + if event == EVT_VIRTUAL_ENTER then + if Edit_pos > Menu[Focus].field_len then + -- Save or Cancel + Edit = -1 + if Edit_pos == Menu[Focus].field_len + 1 then + -- Save + Config_Send(Page, Focus, Menu_value) + end + return + else + -- Switch to edit mode + Edit = 1 + end + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Move cursor + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then + -- Move cursor + Edit_pos = Edit_pos + 1 + end + else + -- Editing value + if event == EVT_VIRTUAL_ENTER then + -- End edit + Edit = 0 + elseif event == EVT_VIRTUAL_PREV then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1 + elseif event == EVT_VIRTUAL_NEXT then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1 + end + --Blink + Blink = Blink + 1 + if Blink > 30 then + Blink = 0 + end + end + --Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + for i = 1, Menu[Focus].field_len, 1 do + if i==Edit_pos and (Edit ~= 1 or Blink > 15) then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib) + else + lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE) + end + end + if Edit_pos == Menu[Focus].field_len + 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Save", attrib) + else + lcd.drawText(17, 30, "Save", attrib + SMLSIZE) + end + if Edit_pos == Menu[Focus].field_len + 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "Cancel", attrib) + else + lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE) + end + + elseif Menu[Focus].field_type == 0x90 then + -- Action text + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 2 + end + if event == EVT_VIRTUAL_ENTER then + -- Exit + Edit = -1 + if Edit_pos == 1 then + -- Yes + Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } ) + end + return + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Switch to Yes + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then + -- Switch to No + Edit_pos = Edit_pos + 1 + end + -- Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + if LCD_W == 480 then + lcd.drawText(170, 110, Menu[Focus].field_text .. "?") + else + lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE) + end + if Edit_pos == 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Yes", attrib) + else + lcd.drawText(17, 30, "Yes", attrib + SMLSIZE) + end + if Edit_pos == 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "No", attrib) + else + lcd.drawText(77, 30, "No", attrib) + end + end +end + +local function Config_Next_Prev( event ) +-- Next Prev on main menu + local line + if event == EVT_VIRTUAL_PREV then + for line = Focus - 1, 1, -1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + elseif event == EVT_VIRTUAL_NEXT then + for line = Focus + 1, 7, 1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + end +end + +local function Config_Draw_Menu() +-- Main menu + local i + local value + local line + local length + local text + + lcd.clear() + + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR) + if multiBuffer(13) == 0x00 then + lcd.drawText(10,50,"No Config telemetry...", BLINK) + end + else + --Draw on LCD_W=128 + lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE) + if multiBuffer(13) == 0x00 then + lcd.drawText(2,17,"No Config telemetry...",SMLSIZE) + end + end + + if multiBuffer(13) ~= 0x00 then + if LCD_W == 480 then + --Draw firmware version and channels order + local ch_order = multiBuffer(17) + local channel_names = {} + channel_names[bitand(ch_order,3)+1] = "A" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "E" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "T" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "R" + lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16), MENU_TITLE_COLOR) + --lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR) + else + lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4]) + end + + --Draw Menu + for line = 1, 7, 1 do + --Clear line info + Menu[line].text = "" + Menu[line].field_type = 0 + Menu[line].field_len = 0 + for i = 1, 7, 1 do + Menu[line].field_value[i] = 0 + end + Menu[line].field_text = "" + length = 0 + --Read line from buffer + for i = 0, 20-1, 1 do + value=multiBuffer( line*20+13+i ) + if value == 0 then + break -- end of line + end + if value > 0x80 and Menu[line].field_type == 0 then + -- Read field type + Menu[line].field_type = bitand(value, 0xF0) + Menu[line].field_len = bitand(value, 0x0F) + length = Menu[line].field_len + if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then + -- First actionnable field if nothing was selected + Focus = line; + end + else + if Menu[line].field_type == 0 then + -- Text + Menu[line].text = Menu[line].text .. string.char(value) + else + -- Menu specific fields + length = length - 1 + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + Menu[line].field_text = Menu[line].field_text .. string.char(value) + else + Menu[line].field_value[Menu[line].field_len-length] = value + end + if length == 0 then + -- End of fields + break + end + end + end + end + -- Display menu text + if Menu[line].text ~= "" then + if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + Menu[line].text = Menu[line].text .. ":" + end + if LCD_W == 480 then + lcd.drawText(10,32+20*line,Menu[line].text ) + else + lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE) + end + end + -- Display specific fields + if line == Focus then + attrib = INVERS + else + attrib = 0 + end + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + -- Text + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then + -- Decimal value + value = 0 + for i = 1, Menu[line].field_len, 1 do + value = value*256 + value + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + -- Hex value + text="" + for i = 1, Menu[line].field_len, 1 do + text = text .. string.format('%02X ', Menu[line].field_value[i]) + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib) + end + end + end + end +end + +-- Init +local function Config_Init() + --get Module settings and set to config + Module = model.getModule(1) + InitialProtocol = Module.protocol + Module.protocol = 86 + model.setModule(1, Module) + for i = 0, 10, 1 do end + --Set protocol to talk to + multiBuffer( 0, string.byte('C') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('C') then + error("Not enough memory!") + return 2 + end + --Request init of the buffer + multiBuffer( 4, 0xFF ) + --Continue buffer init + multiBuffer( 1, string.byte('o') ) + multiBuffer( 2, string.byte('n') ) + multiBuffer( 3, string.byte('f') ) + + -- Test set + -- multiBuffer( 12, 0 ) + -- multiBuffer( 13, 1 ) + -- multiBuffer( 14, 3 ) + -- multiBuffer( 15, 2 ) + -- multiBuffer( 16, 62 ) + -- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64) + + -- multiBuffer( 33, string.byte('G') ) + -- multiBuffer( 34, string.byte('l') ) + -- multiBuffer( 35, string.byte('o') ) + -- multiBuffer( 36, string.byte('b') ) + -- multiBuffer( 37, string.byte('a') ) + -- multiBuffer( 38, string.byte('l') ) + -- multiBuffer( 39, string.byte(' ') ) + -- multiBuffer( 40, string.byte('I') ) + -- multiBuffer( 41, string.byte('D') ) + -- multiBuffer( 42, 0xD0 + 4 ) + -- multiBuffer( 43, 0x12 ) + -- multiBuffer( 44, 0x34 ) + -- multiBuffer( 45, 0x56 ) + -- multiBuffer( 46, 0x78 ) + -- multiBuffer( 47, 0x9A ) + -- multiBuffer( 48, 0xBC ) + + -- multiBuffer( 53, 0x90 + 9 ) + -- multiBuffer( 54, string.byte('R') ) + -- multiBuffer( 55, string.byte('e') ) + -- multiBuffer( 56, string.byte('s') ) + -- multiBuffer( 57, string.byte('e') ) + -- multiBuffer( 58, string.byte('t') ) + -- multiBuffer( 59, string.byte(' ') ) + -- multiBuffer( 60, string.byte('G') ) + -- multiBuffer( 61, string.byte('I') ) + -- multiBuffer( 62, string.byte('D') ) + -- multiBuffer( 63, 0x00 ) +end + +-- Main +local function Config_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + Config_Release() + return 2 + else + Config_Draw_Menu() + if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then + -- Not editing, ok to change page + if event == EVT_VIRTUAL_PREV_PAGE then + killEvents(event) + if Page > 0 then + --Page = Page - 1 + --Config_Page() + end + else + --Page = Page + 1 + --Config_Page() + end + end + if Focus > 0 then + -- At least one line has an action + if Edit >= 0 then + -- Currently editing + Config_Draw_Edit( event ) + elseif event == EVT_VIRTUAL_ENTER then + -- Switch to edit + Config_Draw_Edit( 0 ) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then + -- Main menu selection + Config_Next_Prev( event ) + end + end + return 0 + end +end + +return { init=Config_Init, run=Config_Run } diff --git a/radio/sdcard/horus/UTILITIES/MultiConfigInternal.lua b/radio/sdcard/horus/UTILITIES/MultiConfigInternal.lua new file mode 100755 index 000000000..29ced006c --- /dev/null +++ b/radio/sdcard/horus/UTILITIES/MultiConfigInternal.lua @@ -0,0 +1,499 @@ +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + + +--############################################################################### +-- Multi buffer for Config description +-- To start operation: +-- Write 0xFF at address 4 will request the buffer to be cleared +-- Write "Conf" at address 0..3 +-- Read +-- Read at address 12 gives the current config page +-- Read at address 13..172 gives the current data of the page = 8 lines * 20 caracters +-- Write +-- Write at address 5..11 the command +-- Write 0x01 at address 4 will send the command to the module +-- !! Before exiting the script must write 0 at address 0 for normal operation !! +--############################################################################### + +local Version = "v0.1" +local Focus = -1 +local Page = 0 +local Edit = -1 +local Edit_pos = 1 +local Menu = { {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""} } +local Menu_value = {} +local Blink = 0 +local Module = {} +local InitialProtocol = 0 + +function bitand(a, b) + local result = 0 + local bitval = 1 + while a > 0 and b > 0 do + if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits + result = result + bitval -- set the current bit + end + bitval = bitval * 2 -- shift left + a = math.floor(a/2) -- shift right + b = math.floor(b/2) + end + return result +end + +local function Config_Send(page, line, value) + local i + i = (page*16) + line + multiBuffer( 5, i ) + for i = 1 , 6 , 1 do + multiBuffer( 5+i, value[i] ) + end + multiBuffer( 4, 1 ) +end + +local function Config_Release() + Module.protocol = InitialProtocol + model.setModule(0, Module) + + local i + for i = 3 , 0 , -1 do + multiBuffer( i, 0 ) + end +end + +local function Config_Page( ) + Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 }) +end + +local function Config_Draw_Edit( event ) + local i + local text + + if Menu[Focus].field_type == 0xD0 then + -- Editable Hex value + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 1 + Blink = 0 + for i = 1, Menu[Focus].field_len, 1 do + Menu_value[i] = Menu[Focus].field_value[i] + end + end + if Edit == 0 then + -- Not editing value + if event == EVT_VIRTUAL_ENTER then + if Edit_pos > Menu[Focus].field_len then + -- Save or Cancel + Edit = -1 + if Edit_pos == Menu[Focus].field_len + 1 then + -- Save + Config_Send(Page, Focus, Menu_value) + end + return + else + -- Switch to edit mode + Edit = 1 + end + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Move cursor + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then + -- Move cursor + Edit_pos = Edit_pos + 1 + end + else + -- Editing value + if event == EVT_VIRTUAL_ENTER then + -- End edit + Edit = 0 + elseif event == EVT_VIRTUAL_PREV then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1 + elseif event == EVT_VIRTUAL_NEXT then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1 + end + --Blink + Blink = Blink + 1 + if Blink > 30 then + Blink = 0 + end + end + --Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + for i = 1, Menu[Focus].field_len, 1 do + if i==Edit_pos and (Edit ~= 1 or Blink > 15) then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib) + else + lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE) + end + end + if Edit_pos == Menu[Focus].field_len + 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Save", attrib) + else + lcd.drawText(17, 30, "Save", attrib + SMLSIZE) + end + if Edit_pos == Menu[Focus].field_len + 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "Cancel", attrib) + else + lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE) + end + + elseif Menu[Focus].field_type == 0x90 then + -- Action text + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 2 + end + if event == EVT_VIRTUAL_ENTER then + -- Exit + Edit = -1 + if Edit_pos == 1 then + -- Yes + Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } ) + end + return + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Switch to Yes + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then + -- Switch to No + Edit_pos = Edit_pos + 1 + end + -- Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + if LCD_W == 480 then + lcd.drawText(170, 110, Menu[Focus].field_text .. "?") + else + lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE) + end + if Edit_pos == 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Yes", attrib) + else + lcd.drawText(17, 30, "Yes", attrib + SMLSIZE) + end + if Edit_pos == 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "No", attrib) + else + lcd.drawText(77, 30, "No", attrib) + end + end +end + +local function Config_Next_Prev( event ) +-- Next Prev on main menu + local line + if event == EVT_VIRTUAL_PREV then + for line = Focus - 1, 1, -1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + elseif event == EVT_VIRTUAL_NEXT then + for line = Focus + 1, 7, 1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + end +end + +local function Config_Draw_Menu() +-- Main menu + local i + local value + local line + local length + local text + + lcd.clear() + + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR) + if multiBuffer(13) == 0x00 then + lcd.drawText(10,50,"No Config telemetry...", BLINK) + end + else + --Draw on LCD_W=128 + lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE) + if multiBuffer(13) == 0x00 then + lcd.drawText(2,17,"No Config telemetry...",SMLSIZE) + end + end + + if multiBuffer(13) ~= 0x00 then + if LCD_W == 480 then + --Draw firmware version and channels order + local ch_order = multiBuffer(17) + local channel_names = {} + channel_names[bitand(ch_order,3)+1] = "A" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "E" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "T" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "R" + lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16), MENU_TITLE_COLOR) + --lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR) + else + lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4]) + end + + --Draw Menu + for line = 1, 7, 1 do + --Clear line info + Menu[line].text = "" + Menu[line].field_type = 0 + Menu[line].field_len = 0 + for i = 1, 7, 1 do + Menu[line].field_value[i] = 0 + end + Menu[line].field_text = "" + length = 0 + --Read line from buffer + for i = 0, 20-1, 1 do + value=multiBuffer( line*20+13+i ) + if value == 0 then + break -- end of line + end + if value > 0x80 and Menu[line].field_type == 0 then + -- Read field type + Menu[line].field_type = bitand(value, 0xF0) + Menu[line].field_len = bitand(value, 0x0F) + length = Menu[line].field_len + if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then + -- First actionnable field if nothing was selected + Focus = line; + end + else + if Menu[line].field_type == 0 then + -- Text + Menu[line].text = Menu[line].text .. string.char(value) + else + -- Menu specific fields + length = length - 1 + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + Menu[line].field_text = Menu[line].field_text .. string.char(value) + else + Menu[line].field_value[Menu[line].field_len-length] = value + end + if length == 0 then + -- End of fields + break + end + end + end + end + -- Display menu text + if Menu[line].text ~= "" then + if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + Menu[line].text = Menu[line].text .. ":" + end + if LCD_W == 480 then + lcd.drawText(10,32+20*line,Menu[line].text ) + else + lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE) + end + end + -- Display specific fields + if line == Focus then + attrib = INVERS + else + attrib = 0 + end + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + -- Text + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then + -- Decimal value + value = 0 + for i = 1, Menu[line].field_len, 1 do + value = value*256 + value + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + -- Hex value + text="" + for i = 1, Menu[line].field_len, 1 do + text = text .. string.format('%02X ', Menu[line].field_value[i]) + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib) + end + end + end + end +end + +-- Init +local function Config_Init() + --get Module settings and set to config + Module = model.getModule(0) + InitialProtocol = Module.protocol + Module.protocol = 86 + model.setModule(0, Module) + for i = 0, 10, 1 do end + --Set protocol to talk to + multiBuffer( 0, string.byte('C') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('C') then + error("Not enough memory!") + return 2 + end + --Request init of the buffer + multiBuffer( 4, 0xFF ) + --Continue buffer init + multiBuffer( 1, string.byte('o') ) + multiBuffer( 2, string.byte('n') ) + multiBuffer( 3, string.byte('f') ) + + -- Test set + -- multiBuffer( 12, 0 ) + -- multiBuffer( 13, 1 ) + -- multiBuffer( 14, 3 ) + -- multiBuffer( 15, 2 ) + -- multiBuffer( 16, 62 ) + -- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64) + + -- multiBuffer( 33, string.byte('G') ) + -- multiBuffer( 34, string.byte('l') ) + -- multiBuffer( 35, string.byte('o') ) + -- multiBuffer( 36, string.byte('b') ) + -- multiBuffer( 37, string.byte('a') ) + -- multiBuffer( 38, string.byte('l') ) + -- multiBuffer( 39, string.byte(' ') ) + -- multiBuffer( 40, string.byte('I') ) + -- multiBuffer( 41, string.byte('D') ) + -- multiBuffer( 42, 0xD0 + 4 ) + -- multiBuffer( 43, 0x12 ) + -- multiBuffer( 44, 0x34 ) + -- multiBuffer( 45, 0x56 ) + -- multiBuffer( 46, 0x78 ) + -- multiBuffer( 47, 0x9A ) + -- multiBuffer( 48, 0xBC ) + + -- multiBuffer( 53, 0x90 + 9 ) + -- multiBuffer( 54, string.byte('R') ) + -- multiBuffer( 55, string.byte('e') ) + -- multiBuffer( 56, string.byte('s') ) + -- multiBuffer( 57, string.byte('e') ) + -- multiBuffer( 58, string.byte('t') ) + -- multiBuffer( 59, string.byte(' ') ) + -- multiBuffer( 60, string.byte('G') ) + -- multiBuffer( 61, string.byte('I') ) + -- multiBuffer( 62, string.byte('D') ) + -- multiBuffer( 63, 0x00 ) +end + +-- Main +local function Config_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + Config_Release() + return 2 + else + Config_Draw_Menu() + if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then + -- Not editing, ok to change page + if event == EVT_VIRTUAL_PREV_PAGE then + killEvents(event) + if Page > 0 then + --Page = Page - 1 + --Config_Page() + end + else + --Page = Page + 1 + --Config_Page() + end + end + if Focus > 0 then + -- At least one line has an action + if Edit >= 0 then + -- Currently editing + Config_Draw_Edit( event ) + elseif event == EVT_VIRTUAL_ENTER then + -- Switch to edit + Config_Draw_Edit( 0 ) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then + -- Main menu selection + Config_Next_Prev( event ) + end + end + return 0 + end +end + +return { init=Config_Init, run=Config_Run } diff --git a/radio/sdcard/horus/SxR Calibrate/SxR_Calibrate.lua b/radio/sdcard/horus/UTILITIES/SxR Calibrate/SxR_Calibrate.lua similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/SxR_Calibrate.lua rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/SxR_Calibrate.lua diff --git a/radio/sdcard/horus/SxR Calibrate/img/back.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/back.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/back.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/back.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/delta_b.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/delta_b.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/delta_b.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/delta_b.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/done.bmp b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/done.bmp similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/done.bmp rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/done.bmp diff --git a/radio/sdcard/horus/SxR Calibrate/img/down.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/down.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/down.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/down.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/forward.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/forward.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/forward.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/forward.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/left.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/left.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/left.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/left.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/plane_b.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/plane_b.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/plane_b.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/plane_b.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/planev_b.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/planev_b.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/planev_b.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/planev_b.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/planev_s.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/planev_s.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/planev_s.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/planev_s.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/right.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/right.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/right.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/right.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/up.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/up.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/up.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/up.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/vert-r.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/vert-r.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/vert-r.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/vert-r.png diff --git a/radio/sdcard/horus/SxR Calibrate/img/vert.png b/radio/sdcard/horus/UTILITIES/SxR Calibrate/img/vert.png similarity index 100% rename from radio/sdcard/horus/SxR Calibrate/img/vert.png rename to radio/sdcard/horus/UTILITIES/SxR Calibrate/img/vert.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt index b03b2c860..305451422 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiChan.txt @@ -6,6 +6,7 @@ 14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop 14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop 59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video +59,1,BayangRX,CPPM,1,AnAux1,AnAux2,Flip,RTH,Pict,Video 41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED 42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED 42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol @@ -34,9 +35,9 @@ 6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill 6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill 70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH 45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH -45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH 16,0,ESKY,Std,0,Gyro,Pitch 16,1,ESKY,ET4,0,Gyro,Pitch 35,0,ESKY150,4CH,0 @@ -54,6 +55,7 @@ 28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 +56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 53,0,Height,5ch,0,Gear 53,1,Height,8ch,0,Gear,Gyro,Flap,Light 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 @@ -79,6 +81,8 @@ 65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 55,1,FrSkyRX,CloneTX,0 +55,2,FrSkyRX,EraseTX,0 +55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 58,0,FX816,P38,1 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib @@ -99,13 +103,14 @@ 26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib -57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess 2,1,Hubsan,H301,0,RTH,Light,Stab,Video 2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes 22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -71,0,JJRC345,Std,1,Flip,HLess,RTH +71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3 +71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3 49,0,KF606,Std,1,Trim 9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim 9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim @@ -122,6 +127,8 @@ 17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess +17,5,MT99XX,A180,0,3D_6G +17,6,MT99XX,Dragon,0,Mode,RTH 44,0,NCC1701,Std,1,Warp 77,0,OMP,M2,0,THold,IdleUp,6G_3D 60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 @@ -138,10 +145,11 @@ 72,0,Q90C,Std,0,FMode,VTX+ 74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK 50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 -21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 +21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8 19,0,Shenqi,Cycle,1 68,0,Skyartec,Std,0,CH5,CH6,CH7 11,0,SLT,V1,0,Gear,Pitch @@ -174,3 +182,11 @@ 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess 52,0,ZSX,280,1,Light +78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +79,0,WFLY2,RF20x,0,CH5,CH6,CH7,CH8,CH9,CH10 +80,0,E016Hv2,E016Hv2,1,TakLan,EmStop,Flip,Calib,HLess,RTH +81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE +82,0,LOLI,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe +83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR +84,0,JOYSWAY,Std,0 +85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiLOLI.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiLOLI.lua new file mode 100644 index 000000000..4d309e37e --- /dev/null +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/MultiLOLI.lua @@ -0,0 +1,221 @@ + +local toolName = "TNS|Multi LOLI RX config|TNE" + +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local loli_nok = false +local channels={ { 768, "PWM", 100, 102, "PPM", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH1 + { 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH2 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH3 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH4 + { 102, "SBUS", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH5 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH6 + { 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH7 + { -768, "Servo", 0, -2048, "Switch", -100 } } -- CH8 + +local sel = 1 +local edit = false + +local blink = 0 +local BLINK_SPEED = 15 + +local function drawScreenTitle(title) + if LCD_W == 480 then + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, title, MENU_TITLE_COLOR) + else + lcd.drawScreenTitle(title, 0, 0) + end +end + +local function LOLI_Draw_LCD(event) + local line = 0 + + lcd.clear() + + --Display settings + local lcd_opt = 0 + if LCD_W == 480 then + drawScreenTitle("Multi - LOLI RX configuration tool") + x_pos = 152 + x_inc = 90 + y_pos = 40 + y_inc = 20 + else + x_pos = 5 + x_inc = 30 + y_pos = 1 + y_inc = 8 + lcd_opt = SMLSIZE + end + + --Multi Module detection + if loli_nok then + if LCD_W == 480 then + lcd.drawText(10,50,"The LOLI protocol is not selected...", lcd_opt) + else + --Draw on LCD_W=128 + lcd.drawText(2,17,"LOLI protocol not selected...",SMLSIZE) + end + return + end + + --Display current config + if LCD_W == 480 then + line = line + 1 + lcd.drawText(x_pos, y_pos+y_inc*line -2, "Channel", lcd_opt) + lcd.drawText(x_pos+x_inc, y_pos+y_inc*line -2, "Function", lcd_opt) + lcd.drawRectangle(x_pos-4, y_pos+y_inc*line -4 , 2*x_inc +2, 188) + lcd.drawLine(x_pos-4, y_pos+y_inc*line +18, x_pos-4 +2*x_inc +1, y_pos+y_inc*line +18, SOLID, 0) + lcd.drawLine(x_pos+x_inc -5, y_pos+y_inc*line -4, x_pos+x_inc -5, y_pos+y_inc*line -5 +188, SOLID, 0) + line = line + 1 + end + + local out + for i = 1, 8 do + out = getValue("ch"..(i+8)) + lcd.drawText(x_pos, y_pos+y_inc*line, "CH"..i, lcd_opt) + for j = 1, #channels[i], 3 do + if out > channels[i][j] then + if sel == i then + invert = INVERS + if edit == true then + blink = blink + 1 + if blink > BLINK_SPEED then + invert = 0 + if blink > BLINK_SPEED * 2 then + blink = 0 + end + end + end + else + invert = 0 + end + lcd.drawText(x_pos+x_inc, y_pos+y_inc*line, channels[i][j+1], lcd_opt + invert) + break + end + end + line = line + 1 + end +end + +local function LOLI_Change_Value(dir) + local pos = 0 + local out + --look for the current position + out = getValue("ch"..(sel+8)) + for j = 1, #channels[sel], 3 do + if out > channels[sel][j] then + pos = j + break + end + end + + --decrement or increment + if dir < 0 and pos > 1 then + pos = pos - 3 + elseif dir > 0 and pos + 3 < #channels[sel] then + pos = pos + 3 + else + return + end + + --delete all mixers for the selected channel + local num_mix = model.getMixesCount(sel-1 +8) + for i = 1, num_mix do + model.deleteMix(sel-1 +8, 0); + end + + --create new mixer + local source_max = getFieldInfo("cyc1") + + local val = { name = channels[sel][pos+1], + source = source_max.id - 1, -- MAX=100 on TX16S + weight = channels[sel][pos+2], + offset = 0, + switch = 0, + multiplex = 0, + curveType = 0, + curveValue = 0, + flightModes = 0, + carryTrim = false, + mixWarn = 0, + delayUp = 0, + delayDown = 0, + speedUp = 0, + speedDown = 0 } + model.insertMix(sel-1 +8, 0, val) +end + +local function LOLI_Menu(event) + if event == EVT_VIRTUAL_NEXT then + if edit == false then + -- not changing a value + if sel < 8 then + sel = sel + 1 + end + else + -- need to inc the value + LOLI_Change_Value(1) + end + elseif event == EVT_VIRTUAL_PREV then + if edit == false then + -- not changing a value + if sel > 1 then + sel = sel - 1 + end + else + -- need to dec the value + LOLI_Change_Value(-1) + end + elseif event == EVT_VIRTUAL_ENTER then + if edit == false then + edit = true + blink = BLINK_SPEED + else + edit = false + end + end +end + +-- Init +local function LOLI_Init() + local module_conf = model.getModule(0) + if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then + module_conf = model.getModule(1) + if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then + loli_nok = true + end + end +end + +-- Main +local function LOLI_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + return 2 + else + LOLI_Menu(event) + LOLI_Draw_LCD(event) + return 0 + end +end + +return { init=LOLI_Init, run=LOLI_Run } diff --git a/radio/sdcard/taranis-x7/UTILITIES/MultiConfigExternal.lua b/radio/sdcard/taranis-x7/UTILITIES/MultiConfigExternal.lua new file mode 100644 index 000000000..a8baf3d13 --- /dev/null +++ b/radio/sdcard/taranis-x7/UTILITIES/MultiConfigExternal.lua @@ -0,0 +1,499 @@ +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + + +--############################################################################### +-- Multi buffer for Config description +-- To start operation: +-- Write 0xFF at address 4 will request the buffer to be cleared +-- Write "Conf" at address 0..3 +-- Read +-- Read at address 12 gives the current config page +-- Read at address 13..172 gives the current data of the page = 8 lines * 20 caracters +-- Write +-- Write at address 5..11 the command +-- Write 0x01 at address 4 will send the command to the module +-- !! Before exiting the script must write 0 at address 0 for normal operation !! +--############################################################################### + +local Version = "v0.1" +local Focus = -1 +local Page = 0 +local Edit = -1 +local Edit_pos = 1 +local Menu = { {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""} } +local Menu_value = {} +local Blink = 0 +local Module = {} +local InitialProtocol = 0 + +function bitand(a, b) + local result = 0 + local bitval = 1 + while a > 0 and b > 0 do + if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits + result = result + bitval -- set the current bit + end + bitval = bitval * 2 -- shift left + a = math.floor(a/2) -- shift right + b = math.floor(b/2) + end + return result +end + +local function Config_Send(page, line, value) + local i + i = (page*16) + line + multiBuffer( 5, i ) + for i = 1 , 6 , 1 do + multiBuffer( 5+i, value[i] ) + end + multiBuffer( 4, 1 ) +end + +local function Config_Release() + Module.protocol = InitialProtocol + model.setModule(1, Module) + + local i + for i = 3 , 0 , -1 do + multiBuffer( i, 0 ) + end +end + +local function Config_Page( ) + Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 }) +end + +local function Config_Draw_Edit( event ) + local i + local text + + if Menu[Focus].field_type == 0xD0 then + -- Editable Hex value + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 1 + Blink = 0 + for i = 1, Menu[Focus].field_len, 1 do + Menu_value[i] = Menu[Focus].field_value[i] + end + end + if Edit == 0 then + -- Not editing value + if event == EVT_VIRTUAL_ENTER then + if Edit_pos > Menu[Focus].field_len then + -- Save or Cancel + Edit = -1 + if Edit_pos == Menu[Focus].field_len + 1 then + -- Save + Config_Send(Page, Focus, Menu_value) + end + return + else + -- Switch to edit mode + Edit = 1 + end + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Move cursor + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then + -- Move cursor + Edit_pos = Edit_pos + 1 + end + else + -- Editing value + if event == EVT_VIRTUAL_ENTER then + -- End edit + Edit = 0 + elseif event == EVT_VIRTUAL_PREV then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1 + elseif event == EVT_VIRTUAL_NEXT then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1 + end + --Blink + Blink = Blink + 1 + if Blink > 30 then + Blink = 0 + end + end + --Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + for i = 1, Menu[Focus].field_len, 1 do + if i==Edit_pos and (Edit ~= 1 or Blink > 15) then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib) + else + lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE) + end + end + if Edit_pos == Menu[Focus].field_len + 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Save", attrib) + else + lcd.drawText(17, 30, "Save", attrib + SMLSIZE) + end + if Edit_pos == Menu[Focus].field_len + 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "Cancel", attrib) + else + lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE) + end + + elseif Menu[Focus].field_type == 0x90 then + -- Action text + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 2 + end + if event == EVT_VIRTUAL_ENTER then + -- Exit + Edit = -1 + if Edit_pos == 1 then + -- Yes + Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } ) + end + return + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Switch to Yes + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then + -- Switch to No + Edit_pos = Edit_pos + 1 + end + -- Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + if LCD_W == 480 then + lcd.drawText(170, 110, Menu[Focus].field_text .. "?") + else + lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE) + end + if Edit_pos == 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Yes", attrib) + else + lcd.drawText(17, 30, "Yes", attrib + SMLSIZE) + end + if Edit_pos == 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "No", attrib) + else + lcd.drawText(77, 30, "No", attrib) + end + end +end + +local function Config_Next_Prev( event ) +-- Next Prev on main menu + local line + if event == EVT_VIRTUAL_PREV then + for line = Focus - 1, 1, -1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + elseif event == EVT_VIRTUAL_NEXT then + for line = Focus + 1, 7, 1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + end +end + +local function Config_Draw_Menu() +-- Main menu + local i + local value + local line + local length + local text + + lcd.clear() + + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR) + if multiBuffer(13) == 0x00 then + lcd.drawText(10,50,"No Config telemetry...", BLINK) + end + else + --Draw on LCD_W=128 + lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE) + if multiBuffer(13) == 0x00 then + lcd.drawText(2,17,"No Config telemetry...",SMLSIZE) + end + end + + if multiBuffer(13) ~= 0x00 then + if LCD_W == 480 then + --Draw firmware version and channels order + local ch_order = multiBuffer(17) + local channel_names = {} + channel_names[bitand(ch_order,3)+1] = "A" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "E" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "T" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "R" + lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16), MENU_TITLE_COLOR) + --lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR) + else + lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4]) + end + + --Draw Menu + for line = 1, 7, 1 do + --Clear line info + Menu[line].text = "" + Menu[line].field_type = 0 + Menu[line].field_len = 0 + for i = 1, 7, 1 do + Menu[line].field_value[i] = 0 + end + Menu[line].field_text = "" + length = 0 + --Read line from buffer + for i = 0, 20-1, 1 do + value=multiBuffer( line*20+13+i ) + if value == 0 then + break -- end of line + end + if value > 0x80 and Menu[line].field_type == 0 then + -- Read field type + Menu[line].field_type = bitand(value, 0xF0) + Menu[line].field_len = bitand(value, 0x0F) + length = Menu[line].field_len + if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then + -- First actionnable field if nothing was selected + Focus = line; + end + else + if Menu[line].field_type == 0 then + -- Text + Menu[line].text = Menu[line].text .. string.char(value) + else + -- Menu specific fields + length = length - 1 + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + Menu[line].field_text = Menu[line].field_text .. string.char(value) + else + Menu[line].field_value[Menu[line].field_len-length] = value + end + if length == 0 then + -- End of fields + break + end + end + end + end + -- Display menu text + if Menu[line].text ~= "" then + if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + Menu[line].text = Menu[line].text .. ":" + end + if LCD_W == 480 then + lcd.drawText(10,32+20*line,Menu[line].text ) + else + lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE) + end + end + -- Display specific fields + if line == Focus then + attrib = INVERS + else + attrib = 0 + end + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + -- Text + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then + -- Decimal value + value = 0 + for i = 1, Menu[line].field_len, 1 do + value = value*256 + value + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + -- Hex value + text="" + for i = 1, Menu[line].field_len, 1 do + text = text .. string.format('%02X ', Menu[line].field_value[i]) + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib) + end + end + end + end +end + +-- Init +local function Config_Init() + --get Module settings and set to config + Module = model.getModule(1) + InitialProtocol = Module.protocol + Module.protocol = 86 + model.setModule(1, Module) + for i = 0, 10, 1 do end + --Set protocol to talk to + multiBuffer( 0, string.byte('C') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('C') then + error("Not enough memory!") + return 2 + end + --Request init of the buffer + multiBuffer( 4, 0xFF ) + --Continue buffer init + multiBuffer( 1, string.byte('o') ) + multiBuffer( 2, string.byte('n') ) + multiBuffer( 3, string.byte('f') ) + + -- Test set + -- multiBuffer( 12, 0 ) + -- multiBuffer( 13, 1 ) + -- multiBuffer( 14, 3 ) + -- multiBuffer( 15, 2 ) + -- multiBuffer( 16, 62 ) + -- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64) + + -- multiBuffer( 33, string.byte('G') ) + -- multiBuffer( 34, string.byte('l') ) + -- multiBuffer( 35, string.byte('o') ) + -- multiBuffer( 36, string.byte('b') ) + -- multiBuffer( 37, string.byte('a') ) + -- multiBuffer( 38, string.byte('l') ) + -- multiBuffer( 39, string.byte(' ') ) + -- multiBuffer( 40, string.byte('I') ) + -- multiBuffer( 41, string.byte('D') ) + -- multiBuffer( 42, 0xD0 + 4 ) + -- multiBuffer( 43, 0x12 ) + -- multiBuffer( 44, 0x34 ) + -- multiBuffer( 45, 0x56 ) + -- multiBuffer( 46, 0x78 ) + -- multiBuffer( 47, 0x9A ) + -- multiBuffer( 48, 0xBC ) + + -- multiBuffer( 53, 0x90 + 9 ) + -- multiBuffer( 54, string.byte('R') ) + -- multiBuffer( 55, string.byte('e') ) + -- multiBuffer( 56, string.byte('s') ) + -- multiBuffer( 57, string.byte('e') ) + -- multiBuffer( 58, string.byte('t') ) + -- multiBuffer( 59, string.byte(' ') ) + -- multiBuffer( 60, string.byte('G') ) + -- multiBuffer( 61, string.byte('I') ) + -- multiBuffer( 62, string.byte('D') ) + -- multiBuffer( 63, 0x00 ) +end + +-- Main +local function Config_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + Config_Release() + return 2 + else + Config_Draw_Menu() + if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then + -- Not editing, ok to change page + if event == EVT_VIRTUAL_PREV_PAGE then + killEvents(event) + if Page > 0 then + --Page = Page - 1 + --Config_Page() + end + else + --Page = Page + 1 + --Config_Page() + end + end + if Focus > 0 then + -- At least one line has an action + if Edit >= 0 then + -- Currently editing + Config_Draw_Edit( event ) + elseif event == EVT_VIRTUAL_ENTER then + -- Switch to edit + Config_Draw_Edit( 0 ) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then + -- Main menu selection + Config_Next_Prev( event ) + end + end + return 0 + end +end + +return { init=Config_Init, run=Config_Run } diff --git a/radio/sdcard/taranis-x7/UTILITIES/MultiConfigInternal.lua b/radio/sdcard/taranis-x7/UTILITIES/MultiConfigInternal.lua new file mode 100644 index 000000000..29ced006c --- /dev/null +++ b/radio/sdcard/taranis-x7/UTILITIES/MultiConfigInternal.lua @@ -0,0 +1,499 @@ +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + + +--############################################################################### +-- Multi buffer for Config description +-- To start operation: +-- Write 0xFF at address 4 will request the buffer to be cleared +-- Write "Conf" at address 0..3 +-- Read +-- Read at address 12 gives the current config page +-- Read at address 13..172 gives the current data of the page = 8 lines * 20 caracters +-- Write +-- Write at address 5..11 the command +-- Write 0x01 at address 4 will send the command to the module +-- !! Before exiting the script must write 0 at address 0 for normal operation !! +--############################################################################### + +local Version = "v0.1" +local Focus = -1 +local Page = 0 +local Edit = -1 +local Edit_pos = 1 +local Menu = { {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""} } +local Menu_value = {} +local Blink = 0 +local Module = {} +local InitialProtocol = 0 + +function bitand(a, b) + local result = 0 + local bitval = 1 + while a > 0 and b > 0 do + if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits + result = result + bitval -- set the current bit + end + bitval = bitval * 2 -- shift left + a = math.floor(a/2) -- shift right + b = math.floor(b/2) + end + return result +end + +local function Config_Send(page, line, value) + local i + i = (page*16) + line + multiBuffer( 5, i ) + for i = 1 , 6 , 1 do + multiBuffer( 5+i, value[i] ) + end + multiBuffer( 4, 1 ) +end + +local function Config_Release() + Module.protocol = InitialProtocol + model.setModule(0, Module) + + local i + for i = 3 , 0 , -1 do + multiBuffer( i, 0 ) + end +end + +local function Config_Page( ) + Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 }) +end + +local function Config_Draw_Edit( event ) + local i + local text + + if Menu[Focus].field_type == 0xD0 then + -- Editable Hex value + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 1 + Blink = 0 + for i = 1, Menu[Focus].field_len, 1 do + Menu_value[i] = Menu[Focus].field_value[i] + end + end + if Edit == 0 then + -- Not editing value + if event == EVT_VIRTUAL_ENTER then + if Edit_pos > Menu[Focus].field_len then + -- Save or Cancel + Edit = -1 + if Edit_pos == Menu[Focus].field_len + 1 then + -- Save + Config_Send(Page, Focus, Menu_value) + end + return + else + -- Switch to edit mode + Edit = 1 + end + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Move cursor + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then + -- Move cursor + Edit_pos = Edit_pos + 1 + end + else + -- Editing value + if event == EVT_VIRTUAL_ENTER then + -- End edit + Edit = 0 + elseif event == EVT_VIRTUAL_PREV then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1 + elseif event == EVT_VIRTUAL_NEXT then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1 + end + --Blink + Blink = Blink + 1 + if Blink > 30 then + Blink = 0 + end + end + --Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + for i = 1, Menu[Focus].field_len, 1 do + if i==Edit_pos and (Edit ~= 1 or Blink > 15) then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib) + else + lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE) + end + end + if Edit_pos == Menu[Focus].field_len + 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Save", attrib) + else + lcd.drawText(17, 30, "Save", attrib + SMLSIZE) + end + if Edit_pos == Menu[Focus].field_len + 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "Cancel", attrib) + else + lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE) + end + + elseif Menu[Focus].field_type == 0x90 then + -- Action text + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 2 + end + if event == EVT_VIRTUAL_ENTER then + -- Exit + Edit = -1 + if Edit_pos == 1 then + -- Yes + Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } ) + end + return + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Switch to Yes + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then + -- Switch to No + Edit_pos = Edit_pos + 1 + end + -- Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + if LCD_W == 480 then + lcd.drawText(170, 110, Menu[Focus].field_text .. "?") + else + lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE) + end + if Edit_pos == 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Yes", attrib) + else + lcd.drawText(17, 30, "Yes", attrib + SMLSIZE) + end + if Edit_pos == 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "No", attrib) + else + lcd.drawText(77, 30, "No", attrib) + end + end +end + +local function Config_Next_Prev( event ) +-- Next Prev on main menu + local line + if event == EVT_VIRTUAL_PREV then + for line = Focus - 1, 1, -1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + elseif event == EVT_VIRTUAL_NEXT then + for line = Focus + 1, 7, 1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + end +end + +local function Config_Draw_Menu() +-- Main menu + local i + local value + local line + local length + local text + + lcd.clear() + + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR) + if multiBuffer(13) == 0x00 then + lcd.drawText(10,50,"No Config telemetry...", BLINK) + end + else + --Draw on LCD_W=128 + lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE) + if multiBuffer(13) == 0x00 then + lcd.drawText(2,17,"No Config telemetry...",SMLSIZE) + end + end + + if multiBuffer(13) ~= 0x00 then + if LCD_W == 480 then + --Draw firmware version and channels order + local ch_order = multiBuffer(17) + local channel_names = {} + channel_names[bitand(ch_order,3)+1] = "A" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "E" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "T" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "R" + lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16), MENU_TITLE_COLOR) + --lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR) + else + lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4]) + end + + --Draw Menu + for line = 1, 7, 1 do + --Clear line info + Menu[line].text = "" + Menu[line].field_type = 0 + Menu[line].field_len = 0 + for i = 1, 7, 1 do + Menu[line].field_value[i] = 0 + end + Menu[line].field_text = "" + length = 0 + --Read line from buffer + for i = 0, 20-1, 1 do + value=multiBuffer( line*20+13+i ) + if value == 0 then + break -- end of line + end + if value > 0x80 and Menu[line].field_type == 0 then + -- Read field type + Menu[line].field_type = bitand(value, 0xF0) + Menu[line].field_len = bitand(value, 0x0F) + length = Menu[line].field_len + if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then + -- First actionnable field if nothing was selected + Focus = line; + end + else + if Menu[line].field_type == 0 then + -- Text + Menu[line].text = Menu[line].text .. string.char(value) + else + -- Menu specific fields + length = length - 1 + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + Menu[line].field_text = Menu[line].field_text .. string.char(value) + else + Menu[line].field_value[Menu[line].field_len-length] = value + end + if length == 0 then + -- End of fields + break + end + end + end + end + -- Display menu text + if Menu[line].text ~= "" then + if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + Menu[line].text = Menu[line].text .. ":" + end + if LCD_W == 480 then + lcd.drawText(10,32+20*line,Menu[line].text ) + else + lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE) + end + end + -- Display specific fields + if line == Focus then + attrib = INVERS + else + attrib = 0 + end + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + -- Text + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then + -- Decimal value + value = 0 + for i = 1, Menu[line].field_len, 1 do + value = value*256 + value + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + -- Hex value + text="" + for i = 1, Menu[line].field_len, 1 do + text = text .. string.format('%02X ', Menu[line].field_value[i]) + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib) + end + end + end + end +end + +-- Init +local function Config_Init() + --get Module settings and set to config + Module = model.getModule(0) + InitialProtocol = Module.protocol + Module.protocol = 86 + model.setModule(0, Module) + for i = 0, 10, 1 do end + --Set protocol to talk to + multiBuffer( 0, string.byte('C') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('C') then + error("Not enough memory!") + return 2 + end + --Request init of the buffer + multiBuffer( 4, 0xFF ) + --Continue buffer init + multiBuffer( 1, string.byte('o') ) + multiBuffer( 2, string.byte('n') ) + multiBuffer( 3, string.byte('f') ) + + -- Test set + -- multiBuffer( 12, 0 ) + -- multiBuffer( 13, 1 ) + -- multiBuffer( 14, 3 ) + -- multiBuffer( 15, 2 ) + -- multiBuffer( 16, 62 ) + -- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64) + + -- multiBuffer( 33, string.byte('G') ) + -- multiBuffer( 34, string.byte('l') ) + -- multiBuffer( 35, string.byte('o') ) + -- multiBuffer( 36, string.byte('b') ) + -- multiBuffer( 37, string.byte('a') ) + -- multiBuffer( 38, string.byte('l') ) + -- multiBuffer( 39, string.byte(' ') ) + -- multiBuffer( 40, string.byte('I') ) + -- multiBuffer( 41, string.byte('D') ) + -- multiBuffer( 42, 0xD0 + 4 ) + -- multiBuffer( 43, 0x12 ) + -- multiBuffer( 44, 0x34 ) + -- multiBuffer( 45, 0x56 ) + -- multiBuffer( 46, 0x78 ) + -- multiBuffer( 47, 0x9A ) + -- multiBuffer( 48, 0xBC ) + + -- multiBuffer( 53, 0x90 + 9 ) + -- multiBuffer( 54, string.byte('R') ) + -- multiBuffer( 55, string.byte('e') ) + -- multiBuffer( 56, string.byte('s') ) + -- multiBuffer( 57, string.byte('e') ) + -- multiBuffer( 58, string.byte('t') ) + -- multiBuffer( 59, string.byte(' ') ) + -- multiBuffer( 60, string.byte('G') ) + -- multiBuffer( 61, string.byte('I') ) + -- multiBuffer( 62, string.byte('D') ) + -- multiBuffer( 63, 0x00 ) +end + +-- Main +local function Config_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + Config_Release() + return 2 + else + Config_Draw_Menu() + if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then + -- Not editing, ok to change page + if event == EVT_VIRTUAL_PREV_PAGE then + killEvents(event) + if Page > 0 then + --Page = Page - 1 + --Config_Page() + end + else + --Page = Page + 1 + --Config_Page() + end + end + if Focus > 0 then + -- At least one line has an action + if Edit >= 0 then + -- Currently editing + Config_Draw_Edit( event ) + elseif event == EVT_VIRTUAL_ENTER then + -- Switch to edit + Config_Draw_Edit( 0 ) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then + -- Main menu selection + Config_Next_Prev( event ) + end + end + return 0 + end +end + +return { init=Config_Init, run=Config_Run } diff --git a/radio/sdcard/taranis-x7/SxR Calibrate/SxR_Calibrate.lua b/radio/sdcard/taranis-x7/UTILITIES/SxR Calibrate/SxR_Calibrate.lua similarity index 100% rename from radio/sdcard/taranis-x7/SxR Calibrate/SxR_Calibrate.lua rename to radio/sdcard/taranis-x7/UTILITIES/SxR Calibrate/SxR_Calibrate.lua diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt index b03b2c860..305451422 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiChan.txt @@ -6,6 +6,7 @@ 14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop 14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop 59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video +59,1,BayangRX,CPPM,1,AnAux1,AnAux2,Flip,RTH,Pict,Video 41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED 42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED 42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol @@ -34,9 +35,9 @@ 6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill 6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill 70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH 45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH -45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH 16,0,ESKY,Std,0,Gyro,Pitch 16,1,ESKY,ET4,0,Gyro,Pitch 35,0,ESKY150,4CH,0 @@ -54,6 +55,7 @@ 28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 +56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14 53,0,Height,5ch,0,Gear 53,1,Height,8ch,0,Gear,Gyro,Flap,Light 25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8 @@ -79,6 +81,8 @@ 65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8 55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 55,1,FrSkyRX,CloneTX,0 +55,2,FrSkyRX,EraseTX,0 +55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 58,0,FX816,P38,1 20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib 20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib @@ -99,13 +103,14 @@ 26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib 26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib -57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 +57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess 2,1,Hubsan,H301,0,RTH,Light,Stab,Video 2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes 22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12 -71,0,JJRC345,Std,1,Flip,HLess,RTH +71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3 +71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3 49,0,KF606,Std,1,Trim 9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim 9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim @@ -122,6 +127,8 @@ 17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess 17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess 17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess +17,5,MT99XX,A180,0,3D_6G +17,6,MT99XX,Dragon,0,Mode,RTH 44,0,NCC1701,Std,1,Warp 77,0,OMP,M2,0,THold,IdleUp,6G_3D 60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8 @@ -138,10 +145,11 @@ 72,0,Q90C,Std,0,FMode,VTX+ 74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 +74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8 76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK 50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16 -21,0,SFHSS,Std,0,CH5,CH6,CH7,CH8 +21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8 19,0,Shenqi,Cycle,1 68,0,Skyartec,Std,0,CH5,CH6,CH7 11,0,SLT,V1,0,Gear,Pitch @@ -174,3 +182,11 @@ 8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess 8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess 52,0,ZSX,280,1,Light +78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16 +79,0,WFLY2,RF20x,0,CH5,CH6,CH7,CH8,CH9,CH10 +80,0,E016Hv2,E016Hv2,1,TakLan,EmStop,Flip,Calib,HLess,RTH +81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE +82,0,LOLI,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe +83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR +84,0,JOYSWAY,Std,0 +85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiLOLI.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiLOLI.lua new file mode 100644 index 000000000..4d309e37e --- /dev/null +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/MultiLOLI.lua @@ -0,0 +1,221 @@ + +local toolName = "TNS|Multi LOLI RX config|TNE" + +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + +local loli_nok = false +local channels={ { 768, "PWM", 100, 102, "PPM", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH1 + { 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH2 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH3 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH4 + { 102, "SBUS", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH5 + { -768, "Servo", 0, -2048, "Switch", -100 }, -- CH6 + { 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH7 + { -768, "Servo", 0, -2048, "Switch", -100 } } -- CH8 + +local sel = 1 +local edit = false + +local blink = 0 +local BLINK_SPEED = 15 + +local function drawScreenTitle(title) + if LCD_W == 480 then + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, title, MENU_TITLE_COLOR) + else + lcd.drawScreenTitle(title, 0, 0) + end +end + +local function LOLI_Draw_LCD(event) + local line = 0 + + lcd.clear() + + --Display settings + local lcd_opt = 0 + if LCD_W == 480 then + drawScreenTitle("Multi - LOLI RX configuration tool") + x_pos = 152 + x_inc = 90 + y_pos = 40 + y_inc = 20 + else + x_pos = 5 + x_inc = 30 + y_pos = 1 + y_inc = 8 + lcd_opt = SMLSIZE + end + + --Multi Module detection + if loli_nok then + if LCD_W == 480 then + lcd.drawText(10,50,"The LOLI protocol is not selected...", lcd_opt) + else + --Draw on LCD_W=128 + lcd.drawText(2,17,"LOLI protocol not selected...",SMLSIZE) + end + return + end + + --Display current config + if LCD_W == 480 then + line = line + 1 + lcd.drawText(x_pos, y_pos+y_inc*line -2, "Channel", lcd_opt) + lcd.drawText(x_pos+x_inc, y_pos+y_inc*line -2, "Function", lcd_opt) + lcd.drawRectangle(x_pos-4, y_pos+y_inc*line -4 , 2*x_inc +2, 188) + lcd.drawLine(x_pos-4, y_pos+y_inc*line +18, x_pos-4 +2*x_inc +1, y_pos+y_inc*line +18, SOLID, 0) + lcd.drawLine(x_pos+x_inc -5, y_pos+y_inc*line -4, x_pos+x_inc -5, y_pos+y_inc*line -5 +188, SOLID, 0) + line = line + 1 + end + + local out + for i = 1, 8 do + out = getValue("ch"..(i+8)) + lcd.drawText(x_pos, y_pos+y_inc*line, "CH"..i, lcd_opt) + for j = 1, #channels[i], 3 do + if out > channels[i][j] then + if sel == i then + invert = INVERS + if edit == true then + blink = blink + 1 + if blink > BLINK_SPEED then + invert = 0 + if blink > BLINK_SPEED * 2 then + blink = 0 + end + end + end + else + invert = 0 + end + lcd.drawText(x_pos+x_inc, y_pos+y_inc*line, channels[i][j+1], lcd_opt + invert) + break + end + end + line = line + 1 + end +end + +local function LOLI_Change_Value(dir) + local pos = 0 + local out + --look for the current position + out = getValue("ch"..(sel+8)) + for j = 1, #channels[sel], 3 do + if out > channels[sel][j] then + pos = j + break + end + end + + --decrement or increment + if dir < 0 and pos > 1 then + pos = pos - 3 + elseif dir > 0 and pos + 3 < #channels[sel] then + pos = pos + 3 + else + return + end + + --delete all mixers for the selected channel + local num_mix = model.getMixesCount(sel-1 +8) + for i = 1, num_mix do + model.deleteMix(sel-1 +8, 0); + end + + --create new mixer + local source_max = getFieldInfo("cyc1") + + local val = { name = channels[sel][pos+1], + source = source_max.id - 1, -- MAX=100 on TX16S + weight = channels[sel][pos+2], + offset = 0, + switch = 0, + multiplex = 0, + curveType = 0, + curveValue = 0, + flightModes = 0, + carryTrim = false, + mixWarn = 0, + delayUp = 0, + delayDown = 0, + speedUp = 0, + speedDown = 0 } + model.insertMix(sel-1 +8, 0, val) +end + +local function LOLI_Menu(event) + if event == EVT_VIRTUAL_NEXT then + if edit == false then + -- not changing a value + if sel < 8 then + sel = sel + 1 + end + else + -- need to inc the value + LOLI_Change_Value(1) + end + elseif event == EVT_VIRTUAL_PREV then + if edit == false then + -- not changing a value + if sel > 1 then + sel = sel - 1 + end + else + -- need to dec the value + LOLI_Change_Value(-1) + end + elseif event == EVT_VIRTUAL_ENTER then + if edit == false then + edit = true + blink = BLINK_SPEED + else + edit = false + end + end +end + +-- Init +local function LOLI_Init() + local module_conf = model.getModule(0) + if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then + module_conf = model.getModule(1) + if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then + loli_nok = true + end + end +end + +-- Main +local function LOLI_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + return 2 + else + LOLI_Menu(event) + LOLI_Draw_LCD(event) + return 0 + end +end + +return { init=LOLI_Init, run=LOLI_Run } diff --git a/radio/sdcard/taranis-x9/UTILITIES/MultiConfigExternal.lua b/radio/sdcard/taranis-x9/UTILITIES/MultiConfigExternal.lua new file mode 100644 index 000000000..a8baf3d13 --- /dev/null +++ b/radio/sdcard/taranis-x9/UTILITIES/MultiConfigExternal.lua @@ -0,0 +1,499 @@ +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + + +--############################################################################### +-- Multi buffer for Config description +-- To start operation: +-- Write 0xFF at address 4 will request the buffer to be cleared +-- Write "Conf" at address 0..3 +-- Read +-- Read at address 12 gives the current config page +-- Read at address 13..172 gives the current data of the page = 8 lines * 20 caracters +-- Write +-- Write at address 5..11 the command +-- Write 0x01 at address 4 will send the command to the module +-- !! Before exiting the script must write 0 at address 0 for normal operation !! +--############################################################################### + +local Version = "v0.1" +local Focus = -1 +local Page = 0 +local Edit = -1 +local Edit_pos = 1 +local Menu = { {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""} } +local Menu_value = {} +local Blink = 0 +local Module = {} +local InitialProtocol = 0 + +function bitand(a, b) + local result = 0 + local bitval = 1 + while a > 0 and b > 0 do + if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits + result = result + bitval -- set the current bit + end + bitval = bitval * 2 -- shift left + a = math.floor(a/2) -- shift right + b = math.floor(b/2) + end + return result +end + +local function Config_Send(page, line, value) + local i + i = (page*16) + line + multiBuffer( 5, i ) + for i = 1 , 6 , 1 do + multiBuffer( 5+i, value[i] ) + end + multiBuffer( 4, 1 ) +end + +local function Config_Release() + Module.protocol = InitialProtocol + model.setModule(1, Module) + + local i + for i = 3 , 0 , -1 do + multiBuffer( i, 0 ) + end +end + +local function Config_Page( ) + Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 }) +end + +local function Config_Draw_Edit( event ) + local i + local text + + if Menu[Focus].field_type == 0xD0 then + -- Editable Hex value + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 1 + Blink = 0 + for i = 1, Menu[Focus].field_len, 1 do + Menu_value[i] = Menu[Focus].field_value[i] + end + end + if Edit == 0 then + -- Not editing value + if event == EVT_VIRTUAL_ENTER then + if Edit_pos > Menu[Focus].field_len then + -- Save or Cancel + Edit = -1 + if Edit_pos == Menu[Focus].field_len + 1 then + -- Save + Config_Send(Page, Focus, Menu_value) + end + return + else + -- Switch to edit mode + Edit = 1 + end + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Move cursor + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then + -- Move cursor + Edit_pos = Edit_pos + 1 + end + else + -- Editing value + if event == EVT_VIRTUAL_ENTER then + -- End edit + Edit = 0 + elseif event == EVT_VIRTUAL_PREV then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1 + elseif event == EVT_VIRTUAL_NEXT then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1 + end + --Blink + Blink = Blink + 1 + if Blink > 30 then + Blink = 0 + end + end + --Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + for i = 1, Menu[Focus].field_len, 1 do + if i==Edit_pos and (Edit ~= 1 or Blink > 15) then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib) + else + lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE) + end + end + if Edit_pos == Menu[Focus].field_len + 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Save", attrib) + else + lcd.drawText(17, 30, "Save", attrib + SMLSIZE) + end + if Edit_pos == Menu[Focus].field_len + 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "Cancel", attrib) + else + lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE) + end + + elseif Menu[Focus].field_type == 0x90 then + -- Action text + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 2 + end + if event == EVT_VIRTUAL_ENTER then + -- Exit + Edit = -1 + if Edit_pos == 1 then + -- Yes + Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } ) + end + return + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Switch to Yes + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then + -- Switch to No + Edit_pos = Edit_pos + 1 + end + -- Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + if LCD_W == 480 then + lcd.drawText(170, 110, Menu[Focus].field_text .. "?") + else + lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE) + end + if Edit_pos == 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Yes", attrib) + else + lcd.drawText(17, 30, "Yes", attrib + SMLSIZE) + end + if Edit_pos == 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "No", attrib) + else + lcd.drawText(77, 30, "No", attrib) + end + end +end + +local function Config_Next_Prev( event ) +-- Next Prev on main menu + local line + if event == EVT_VIRTUAL_PREV then + for line = Focus - 1, 1, -1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + elseif event == EVT_VIRTUAL_NEXT then + for line = Focus + 1, 7, 1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + end +end + +local function Config_Draw_Menu() +-- Main menu + local i + local value + local line + local length + local text + + lcd.clear() + + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR) + if multiBuffer(13) == 0x00 then + lcd.drawText(10,50,"No Config telemetry...", BLINK) + end + else + --Draw on LCD_W=128 + lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE) + if multiBuffer(13) == 0x00 then + lcd.drawText(2,17,"No Config telemetry...",SMLSIZE) + end + end + + if multiBuffer(13) ~= 0x00 then + if LCD_W == 480 then + --Draw firmware version and channels order + local ch_order = multiBuffer(17) + local channel_names = {} + channel_names[bitand(ch_order,3)+1] = "A" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "E" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "T" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "R" + lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16), MENU_TITLE_COLOR) + --lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR) + else + lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4]) + end + + --Draw Menu + for line = 1, 7, 1 do + --Clear line info + Menu[line].text = "" + Menu[line].field_type = 0 + Menu[line].field_len = 0 + for i = 1, 7, 1 do + Menu[line].field_value[i] = 0 + end + Menu[line].field_text = "" + length = 0 + --Read line from buffer + for i = 0, 20-1, 1 do + value=multiBuffer( line*20+13+i ) + if value == 0 then + break -- end of line + end + if value > 0x80 and Menu[line].field_type == 0 then + -- Read field type + Menu[line].field_type = bitand(value, 0xF0) + Menu[line].field_len = bitand(value, 0x0F) + length = Menu[line].field_len + if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then + -- First actionnable field if nothing was selected + Focus = line; + end + else + if Menu[line].field_type == 0 then + -- Text + Menu[line].text = Menu[line].text .. string.char(value) + else + -- Menu specific fields + length = length - 1 + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + Menu[line].field_text = Menu[line].field_text .. string.char(value) + else + Menu[line].field_value[Menu[line].field_len-length] = value + end + if length == 0 then + -- End of fields + break + end + end + end + end + -- Display menu text + if Menu[line].text ~= "" then + if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + Menu[line].text = Menu[line].text .. ":" + end + if LCD_W == 480 then + lcd.drawText(10,32+20*line,Menu[line].text ) + else + lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE) + end + end + -- Display specific fields + if line == Focus then + attrib = INVERS + else + attrib = 0 + end + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + -- Text + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then + -- Decimal value + value = 0 + for i = 1, Menu[line].field_len, 1 do + value = value*256 + value + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + -- Hex value + text="" + for i = 1, Menu[line].field_len, 1 do + text = text .. string.format('%02X ', Menu[line].field_value[i]) + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib) + end + end + end + end +end + +-- Init +local function Config_Init() + --get Module settings and set to config + Module = model.getModule(1) + InitialProtocol = Module.protocol + Module.protocol = 86 + model.setModule(1, Module) + for i = 0, 10, 1 do end + --Set protocol to talk to + multiBuffer( 0, string.byte('C') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('C') then + error("Not enough memory!") + return 2 + end + --Request init of the buffer + multiBuffer( 4, 0xFF ) + --Continue buffer init + multiBuffer( 1, string.byte('o') ) + multiBuffer( 2, string.byte('n') ) + multiBuffer( 3, string.byte('f') ) + + -- Test set + -- multiBuffer( 12, 0 ) + -- multiBuffer( 13, 1 ) + -- multiBuffer( 14, 3 ) + -- multiBuffer( 15, 2 ) + -- multiBuffer( 16, 62 ) + -- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64) + + -- multiBuffer( 33, string.byte('G') ) + -- multiBuffer( 34, string.byte('l') ) + -- multiBuffer( 35, string.byte('o') ) + -- multiBuffer( 36, string.byte('b') ) + -- multiBuffer( 37, string.byte('a') ) + -- multiBuffer( 38, string.byte('l') ) + -- multiBuffer( 39, string.byte(' ') ) + -- multiBuffer( 40, string.byte('I') ) + -- multiBuffer( 41, string.byte('D') ) + -- multiBuffer( 42, 0xD0 + 4 ) + -- multiBuffer( 43, 0x12 ) + -- multiBuffer( 44, 0x34 ) + -- multiBuffer( 45, 0x56 ) + -- multiBuffer( 46, 0x78 ) + -- multiBuffer( 47, 0x9A ) + -- multiBuffer( 48, 0xBC ) + + -- multiBuffer( 53, 0x90 + 9 ) + -- multiBuffer( 54, string.byte('R') ) + -- multiBuffer( 55, string.byte('e') ) + -- multiBuffer( 56, string.byte('s') ) + -- multiBuffer( 57, string.byte('e') ) + -- multiBuffer( 58, string.byte('t') ) + -- multiBuffer( 59, string.byte(' ') ) + -- multiBuffer( 60, string.byte('G') ) + -- multiBuffer( 61, string.byte('I') ) + -- multiBuffer( 62, string.byte('D') ) + -- multiBuffer( 63, 0x00 ) +end + +-- Main +local function Config_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + Config_Release() + return 2 + else + Config_Draw_Menu() + if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then + -- Not editing, ok to change page + if event == EVT_VIRTUAL_PREV_PAGE then + killEvents(event) + if Page > 0 then + --Page = Page - 1 + --Config_Page() + end + else + --Page = Page + 1 + --Config_Page() + end + end + if Focus > 0 then + -- At least one line has an action + if Edit >= 0 then + -- Currently editing + Config_Draw_Edit( event ) + elseif event == EVT_VIRTUAL_ENTER then + -- Switch to edit + Config_Draw_Edit( 0 ) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then + -- Main menu selection + Config_Next_Prev( event ) + end + end + return 0 + end +end + +return { init=Config_Init, run=Config_Run } diff --git a/radio/sdcard/taranis-x9/UTILITIES/MultiConfigInternal.lua b/radio/sdcard/taranis-x9/UTILITIES/MultiConfigInternal.lua new file mode 100644 index 000000000..29ced006c --- /dev/null +++ b/radio/sdcard/taranis-x9/UTILITIES/MultiConfigInternal.lua @@ -0,0 +1,499 @@ +---- ######################################################################### +---- # # +---- # Copyright (C) OpenTX # +-----# # +---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html # +---- # # +---- # This program is free software; you can redistribute it and/or modify # +---- # it under the terms of the GNU General Public License version 2 as # +---- # published by the Free Software Foundation. # +---- # # +---- # This program is distributed in the hope that it will be useful # +---- # but WITHOUT ANY WARRANTY; without even the implied warranty of # +---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +---- # GNU General Public License for more details. # +---- # # +---- ######################################################################### + + +--############################################################################### +-- Multi buffer for Config description +-- To start operation: +-- Write 0xFF at address 4 will request the buffer to be cleared +-- Write "Conf" at address 0..3 +-- Read +-- Read at address 12 gives the current config page +-- Read at address 13..172 gives the current data of the page = 8 lines * 20 caracters +-- Write +-- Write at address 5..11 the command +-- Write 0x01 at address 4 will send the command to the module +-- !! Before exiting the script must write 0 at address 0 for normal operation !! +--############################################################################### + +local Version = "v0.1" +local Focus = -1 +local Page = 0 +local Edit = -1 +local Edit_pos = 1 +local Menu = { {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""}, + {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""} } +local Menu_value = {} +local Blink = 0 +local Module = {} +local InitialProtocol = 0 + +function bitand(a, b) + local result = 0 + local bitval = 1 + while a > 0 and b > 0 do + if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits + result = result + bitval -- set the current bit + end + bitval = bitval * 2 -- shift left + a = math.floor(a/2) -- shift right + b = math.floor(b/2) + end + return result +end + +local function Config_Send(page, line, value) + local i + i = (page*16) + line + multiBuffer( 5, i ) + for i = 1 , 6 , 1 do + multiBuffer( 5+i, value[i] ) + end + multiBuffer( 4, 1 ) +end + +local function Config_Release() + Module.protocol = InitialProtocol + model.setModule(0, Module) + + local i + for i = 3 , 0 , -1 do + multiBuffer( i, 0 ) + end +end + +local function Config_Page( ) + Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 }) +end + +local function Config_Draw_Edit( event ) + local i + local text + + if Menu[Focus].field_type == 0xD0 then + -- Editable Hex value + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 1 + Blink = 0 + for i = 1, Menu[Focus].field_len, 1 do + Menu_value[i] = Menu[Focus].field_value[i] + end + end + if Edit == 0 then + -- Not editing value + if event == EVT_VIRTUAL_ENTER then + if Edit_pos > Menu[Focus].field_len then + -- Save or Cancel + Edit = -1 + if Edit_pos == Menu[Focus].field_len + 1 then + -- Save + Config_Send(Page, Focus, Menu_value) + end + return + else + -- Switch to edit mode + Edit = 1 + end + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Move cursor + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then + -- Move cursor + Edit_pos = Edit_pos + 1 + end + else + -- Editing value + if event == EVT_VIRTUAL_ENTER then + -- End edit + Edit = 0 + elseif event == EVT_VIRTUAL_PREV then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1 + elseif event == EVT_VIRTUAL_NEXT then + -- Change value + Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1 + end + --Blink + Blink = Blink + 1 + if Blink > 30 then + Blink = 0 + end + end + --Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + for i = 1, Menu[Focus].field_len, 1 do + if i==Edit_pos and (Edit ~= 1 or Blink > 15) then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib) + else + lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE) + end + end + if Edit_pos == Menu[Focus].field_len + 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Save", attrib) + else + lcd.drawText(17, 30, "Save", attrib + SMLSIZE) + end + if Edit_pos == Menu[Focus].field_len + 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "Cancel", attrib) + else + lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE) + end + + elseif Menu[Focus].field_type == 0x90 then + -- Action text + if Edit == -1 then + -- Init + Edit = 0 + Edit_pos = 2 + end + if event == EVT_VIRTUAL_ENTER then + -- Exit + Edit = -1 + if Edit_pos == 1 then + -- Yes + Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } ) + end + return + elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then + -- Switch to Yes + Edit_pos = Edit_pos - 1 + elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then + -- Switch to No + Edit_pos = Edit_pos + 1 + end + -- Display + if LCD_W == 480 then + lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR) + lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR) + else + lcd.clear() + end + if LCD_W == 480 then + lcd.drawText(170, 110, Menu[Focus].field_text .. "?") + else + lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE) + end + if Edit_pos == 1 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(170, 130, "Yes", attrib) + else + lcd.drawText(17, 30, "Yes", attrib + SMLSIZE) + end + if Edit_pos == 2 then + attrib = INVERS + else + attrib = 0 + end + if LCD_W == 480 then + lcd.drawText(260, 130, "No", attrib) + else + lcd.drawText(77, 30, "No", attrib) + end + end +end + +local function Config_Next_Prev( event ) +-- Next Prev on main menu + local line + if event == EVT_VIRTUAL_PREV then + for line = Focus - 1, 1, -1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + elseif event == EVT_VIRTUAL_NEXT then + for line = Focus + 1, 7, 1 do + if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then + Focus = line + break + end + end + end +end + +local function Config_Draw_Menu() +-- Main menu + local i + local value + local line + local length + local text + + lcd.clear() + + if LCD_W == 480 then + --Draw title + lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR) + lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR) + if multiBuffer(13) == 0x00 then + lcd.drawText(10,50,"No Config telemetry...", BLINK) + end + else + --Draw on LCD_W=128 + lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE) + if multiBuffer(13) == 0x00 then + lcd.drawText(2,17,"No Config telemetry...",SMLSIZE) + end + end + + if multiBuffer(13) ~= 0x00 then + if LCD_W == 480 then + --Draw firmware version and channels order + local ch_order = multiBuffer(17) + local channel_names = {} + channel_names[bitand(ch_order,3)+1] = "A" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "E" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "T" + ch_order = math.floor(ch_order/4) + channel_names[bitand(ch_order,3)+1] = "R" + lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16), MENU_TITLE_COLOR) + --lcd.drawText(150, 5, "Firmware v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR) + else + lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4]) + end + + --Draw Menu + for line = 1, 7, 1 do + --Clear line info + Menu[line].text = "" + Menu[line].field_type = 0 + Menu[line].field_len = 0 + for i = 1, 7, 1 do + Menu[line].field_value[i] = 0 + end + Menu[line].field_text = "" + length = 0 + --Read line from buffer + for i = 0, 20-1, 1 do + value=multiBuffer( line*20+13+i ) + if value == 0 then + break -- end of line + end + if value > 0x80 and Menu[line].field_type == 0 then + -- Read field type + Menu[line].field_type = bitand(value, 0xF0) + Menu[line].field_len = bitand(value, 0x0F) + length = Menu[line].field_len + if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then + -- First actionnable field if nothing was selected + Focus = line; + end + else + if Menu[line].field_type == 0 then + -- Text + Menu[line].text = Menu[line].text .. string.char(value) + else + -- Menu specific fields + length = length - 1 + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + Menu[line].field_text = Menu[line].field_text .. string.char(value) + else + Menu[line].field_value[Menu[line].field_len-length] = value + end + if length == 0 then + -- End of fields + break + end + end + end + end + -- Display menu text + if Menu[line].text ~= "" then + if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + Menu[line].text = Menu[line].text .. ":" + end + if LCD_W == 480 then + lcd.drawText(10,32+20*line,Menu[line].text ) + else + lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE) + end + end + -- Display specific fields + if line == Focus then + attrib = INVERS + else + attrib = 0 + end + if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then + -- Text + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then + -- Decimal value + value = 0 + for i = 1, Menu[line].field_len, 1 do + value = value*256 + value + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib) + end + elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then + -- Hex value + text="" + for i = 1, Menu[line].field_len, 1 do + text = text .. string.format('%02X ', Menu[line].field_value[i]) + end + if LCD_W == 480 then + lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib) + else + lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib) + end + end + end + end +end + +-- Init +local function Config_Init() + --get Module settings and set to config + Module = model.getModule(0) + InitialProtocol = Module.protocol + Module.protocol = 86 + model.setModule(0, Module) + for i = 0, 10, 1 do end + --Set protocol to talk to + multiBuffer( 0, string.byte('C') ) + --test if value has been written + if multiBuffer( 0 ) ~= string.byte('C') then + error("Not enough memory!") + return 2 + end + --Request init of the buffer + multiBuffer( 4, 0xFF ) + --Continue buffer init + multiBuffer( 1, string.byte('o') ) + multiBuffer( 2, string.byte('n') ) + multiBuffer( 3, string.byte('f') ) + + -- Test set + -- multiBuffer( 12, 0 ) + -- multiBuffer( 13, 1 ) + -- multiBuffer( 14, 3 ) + -- multiBuffer( 15, 2 ) + -- multiBuffer( 16, 62 ) + -- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64) + + -- multiBuffer( 33, string.byte('G') ) + -- multiBuffer( 34, string.byte('l') ) + -- multiBuffer( 35, string.byte('o') ) + -- multiBuffer( 36, string.byte('b') ) + -- multiBuffer( 37, string.byte('a') ) + -- multiBuffer( 38, string.byte('l') ) + -- multiBuffer( 39, string.byte(' ') ) + -- multiBuffer( 40, string.byte('I') ) + -- multiBuffer( 41, string.byte('D') ) + -- multiBuffer( 42, 0xD0 + 4 ) + -- multiBuffer( 43, 0x12 ) + -- multiBuffer( 44, 0x34 ) + -- multiBuffer( 45, 0x56 ) + -- multiBuffer( 46, 0x78 ) + -- multiBuffer( 47, 0x9A ) + -- multiBuffer( 48, 0xBC ) + + -- multiBuffer( 53, 0x90 + 9 ) + -- multiBuffer( 54, string.byte('R') ) + -- multiBuffer( 55, string.byte('e') ) + -- multiBuffer( 56, string.byte('s') ) + -- multiBuffer( 57, string.byte('e') ) + -- multiBuffer( 58, string.byte('t') ) + -- multiBuffer( 59, string.byte(' ') ) + -- multiBuffer( 60, string.byte('G') ) + -- multiBuffer( 61, string.byte('I') ) + -- multiBuffer( 62, string.byte('D') ) + -- multiBuffer( 63, 0x00 ) +end + +-- Main +local function Config_Run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + Config_Release() + return 2 + else + Config_Draw_Menu() + if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then + -- Not editing, ok to change page + if event == EVT_VIRTUAL_PREV_PAGE then + killEvents(event) + if Page > 0 then + --Page = Page - 1 + --Config_Page() + end + else + --Page = Page + 1 + --Config_Page() + end + end + if Focus > 0 then + -- At least one line has an action + if Edit >= 0 then + -- Currently editing + Config_Draw_Edit( event ) + elseif event == EVT_VIRTUAL_ENTER then + -- Switch to edit + Config_Draw_Edit( 0 ) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then + -- Main menu selection + Config_Next_Prev( event ) + end + end + return 0 + end +end + +return { init=Config_Init, run=Config_Run } diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/SxR_Calibrate.lua b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/SxR_Calibrate.lua similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/SxR_Calibrate.lua rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/SxR_Calibrate.lua diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/back.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/back.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/back.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/back.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/delta.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/delta.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/delta.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/delta.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/done.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/done.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/done.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/done.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/down.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/down.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/down.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/down.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/forward.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/forward.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/forward.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/forward.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/horz-r.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/horz-r.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/horz-r.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/horz-r.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/horz.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/horz.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/horz.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/horz.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/left.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/left.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/left.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/left.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/plane.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/plane.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/plane.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/plane.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/right.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/right.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/right.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/right.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/up.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/up.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/up.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/up.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/vert-r.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/vert-r.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/vert-r.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/vert-r.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/vert.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/vert.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/vert.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/vert.bmp diff --git a/radio/sdcard/taranis-x9/SxR Calibrate/bmp/vtail.bmp b/radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/vtail.bmp similarity index 100% rename from radio/sdcard/taranis-x9/SxR Calibrate/bmp/vtail.bmp rename to radio/sdcard/taranis-x9/UTILITIES/SxR Calibrate/bmp/vtail.bmp diff --git a/radio/src/gui/480x272/radio_tools.cpp b/radio/src/gui/480x272/radio_tools.cpp index 3964337a1..eb2d1b769 100644 --- a/radio/src/gui/480x272/radio_tools.cpp +++ b/radio/src/gui/480x272/radio_tools.cpp @@ -123,7 +123,7 @@ bool menuRadioTools(event_t event) #elif defined(INTERNAL_MODULE_MULTI) addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); #endif -#if defined(PXX2)|| defined(MULTIMODULE) +#if defined(PXX2) || defined(MULTIMODULE) if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER) || isModuleMultimodule(EXTERNAL_MODULE)) addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE); #endif diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp index f19246e62..8bd51a059 100644 --- a/radio/src/lua/api_model.cpp +++ b/radio/src/lua/api_model.cpp @@ -120,11 +120,11 @@ Get RF module parameters * `channelsCount` (number) number of channels sent to module * `Type` (number) module type * if the module type is Multi additional information are available - * `protocol` (number) protocol number - * `subProtocol` (number) sub-protocol number - * `channelsOrder` (number) first 4 channels expected order + * `protocol` (number) protocol number (Multi only) + * `subProtocol` (number) sub-protocol number (Multi only) + * `channelsOrder` (number) first 4 channels expected order (Multi only) -@status current Introduced in TODO +@status current Introduced in 2.2.0 */ static int luaModelGetModule(lua_State *L) { @@ -174,13 +174,16 @@ Set RF module parameters @notice If a parameter is missing from the value, then that parameter remains unchanged. -@status current Introduced in TODO +@status current Introduced in 2.2.0, modified in 2.3.12 (proto/subproto) */ static int luaModelSetModule(lua_State *L) { unsigned int idx = luaL_checkunsigned(L, 1); if (idx < NUM_MODULES) { + int protocol = -1; + int subprotocol = -1; + ModuleData & module = g_model.moduleData[idx]; luaL_checktype(L, -1, LUA_TTABLE); for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { @@ -201,7 +204,22 @@ static int luaModelSetModule(lua_State *L) else if (!strcmp(key, "channelsCount")) { module.channelsCount = luaL_checkinteger(L, -1) - 8; } +#if defined(MULTIMODULE) + if (!strcmp(key, "protocol")) { + protocol = luaL_checkinteger(L, -1); + } + if (!strcmp(key, "subProtocol")) { + subprotocol = luaL_checkinteger(L, -1); + } +#endif } +#if defined(MULTIMODULE) + if (protocol > 0 && subprotocol >= 0) { // Both are needed to compute otx protocol + convertMultiProtocolToOtx(&protocol, &subprotocol); + g_model.moduleData[idx].setMultiProtocol(protocol - 1); + g_model.moduleData[idx].subType = subprotocol; + } +#endif storageDirty(EE_MODEL); } return 0; diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h index 6fbec157e..b6b7a6abc 100644 --- a/radio/src/pulses/modules_constants.h +++ b/radio/src/pulses/modules_constants.h @@ -177,12 +177,17 @@ enum ModuleSubtypeMulti { MODULE_SUBTYPE_MULTI_ELRS, MODULE_SUBTYPE_MULTI_REALACC, MODULE_SUBTYPE_MULTI_OMP, - MODULE_SUBTYPE_MULTI_MLINK, //75 + MODULE_SUBTYPE_MULTI_MLINK, //75 MODULE_SUBTYPE_MULTI_WFLY2, MODULE_SUBTYPE_MULTI_E016HV2, - MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_E016HV2 + MODULE_SUBTYPE_MULTI_E010R5, + MODULE_SUBTYPE_MULTI_LOLI, + MODULE_SUBTYPE_MULTI_E129, //80 + MODULE_SUBTYPE_MULTI_JOYSWAY, + MODULE_SUBTYPE_MULTI_E016H, + MODULE_SUBTYPE_MULTI_CONFIG, + MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_CONFIG }; -#define MODULE_SUBTYPE_MULTI_XN297DP 63-3 enum MMDSM2Subtypes { MM_RF_DSM2_SUBTYPE_DSM2_22, diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index b2bd77de4..4b3448387 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -669,7 +669,7 @@ inline void getMultiOptionValues(int8_t multi_proto, int8_t & min, int8_t & max) min = 0; max = 70; break; - case MODULE_SUBTYPE_MULTI_XN297DP: + case MODULE_SUBTYPE_MULTI_XN297DUMP: min = -1; max = 84; break; diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index 37364199a..de0d54730 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -42,6 +42,7 @@ static void sendD16BindOption(uint8_t moduleIdx); #if defined(LUA) static void sendSport(uint8_t moduleIdx); static void sendHott(uint8_t moduleIdx); +static void sendConfig(uint8_t moduleIdx); static void sendDSM(uint8_t moduleIdx); #endif @@ -190,11 +191,14 @@ void setupPulsesMulti(uint8_t moduleIdx) #if defined(LUA) // SPort send if (IS_D16_MULTI(moduleIdx) && outputTelemetryBuffer.destination == TELEMETRY_ENDPOINT_SPORT && outputTelemetryBuffer.size) { - sendSport(moduleIdx); //8 bytes of additional data + sendSport(moduleIdx); //8 bytes of additional data } else if (IS_HOTT_MULTI(moduleIdx)) { sendHott(moduleIdx); //1 byte of additional data } + else if (IS_CONFIG_MULTI(moduleIdx)) { + sendConfig(moduleIdx); //7 bytes of additional data + } else if (IS_DSM_MULTI(moduleIdx)) { sendDSM(moduleIdx); //7 bytes of additional data } @@ -251,10 +255,54 @@ void sendChannels(uint8_t moduleIdx) } } +void convertMultiProtocolToOtx(int *protocol, int *subprotocol) +{ + if (*protocol == 3 and *subprotocol == 0) { + *protocol = MODULE_SUBTYPE_MULTI_FRSKY + 1; + *subprotocol = MM_RF_FRSKY_SUBTYPE_D8; + return; + } + + if (*protocol == 3 and *subprotocol == 1) { + *protocol = MODULE_SUBTYPE_MULTI_FRSKY + 1; + *subprotocol = MM_RF_FRSKY_SUBTYPE_D8_CLONED; + return; + } + + if (*protocol == 25) { + *protocol = MODULE_SUBTYPE_MULTI_FRSKY + 1; + *subprotocol = MM_RF_FRSKY_SUBTYPE_V8; + return; + } + + if (*protocol == 15) { + *protocol = MODULE_SUBTYPE_MULTI_FRSKY + 1; + + if (*subprotocol == 0) + *subprotocol = MM_RF_FRSKY_SUBTYPE_D16; + else if (*subprotocol == 1) + *subprotocol = MM_RF_FRSKY_SUBTYPE_D16_8CH; + else if (*subprotocol == 2) + *subprotocol = MM_RF_FRSKY_SUBTYPE_D16_LBT; + else if (*subprotocol == 3) + *subprotocol = MM_RF_FRSKY_SUBTYPE_D16_LBT_8CH; + else if (*subprotocol == 4) + *subprotocol = MM_RF_FRSKY_SUBTYPE_D16_CLONED; + + return; + } + + if (*protocol >= 25) + *protocol -= 1; + + if (*protocol >= 16) + *protocol -= 1; +} + void convertOtxProtocolToMulti(int *protocol, int *subprotocol) { // Special treatment for the FrSky entry... - if (*protocol == MODULE_SUBTYPE_MULTI_FRSKY +1) { + if (*protocol == MODULE_SUBTYPE_MULTI_FRSKY + 1) { if (*subprotocol == MM_RF_FRSKY_SUBTYPE_D8) { //D8 *protocol = 3; @@ -288,10 +336,10 @@ void convertOtxProtocolToMulti(int *protocol, int *subprotocol) // 15 for Multimodule is FrskyX or D16 which we map as a protocol of 3 (FrSky) // all protos > frskyx are therefore also off by one if (*protocol >= 15) - *protocol = *protocol + 1; + *protocol += 1; // 25 is again a FrSky *protocol (FrskyV) so shift again if (*protocol >= 25) - *protocol = *protocol + 1; + *protocol += 1; } } @@ -404,6 +452,23 @@ void sendHott(uint8_t moduleIdx) } } +void sendConfig(uint8_t moduleIdx) +{ + // Multi_Buffer[0..3]=="Conf" -> Lua script is running + // Multi_Buffer[4]==0x01 -> TX to Module data ready to be sent + // Multi_Buffer[4]==0xFF -> Clear buffer data + // Multi_Buffer[5..11]=7 bytes of TX to Module data + // Multi_Buffer[12] -> Current page + // Multi_Buffer[13..172]=8*20=160 bytes of Module to TX data + if (Multi_Buffer && memcmp(Multi_Buffer, "Conf", 4) == 0 && Multi_Buffer[4] == 0x01) { + // Config Lua script is running and sending + for (uint8_t i = 0; i < 7; i++) { + sendMulti(moduleIdx, Multi_Buffer[5 + i]); + } + Multi_Buffer[4] = 0x00; // Send data only once + } +} + void sendDSM(uint8_t moduleIdx) { // Multi_Buffer[0..2]=="DSM" -> Lua script is running diff --git a/radio/src/pulses/multi.h b/radio/src/pulses/multi.h index 29e335d3a..e3771d7eb 100644 --- a/radio/src/pulses/multi.h +++ b/radio/src/pulses/multi.h @@ -25,6 +25,7 @@ void multiPatchCustom(uint8_t moduleIdx); void convertOtxProtocolToMulti(int *protocol, int *subprotocol); +void convertMultiProtocolToOtx(int *protocol, int *subprotocol); class UartMultiPulses: public DataBuffer { diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index d71cdad34..ac9dfab7f 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -42,7 +42,8 @@ enum MultiPacketTypes : uint8_t FlyskyIBusTelemetryAC, MultiRxChannels, HottTelemetry, - MLinkTelemetry + MLinkTelemetry, + ConfigTelemetry }; enum MultiBufferState : uint8_t @@ -291,6 +292,31 @@ static void processMultiRxChannels(const uint8_t * data, uint8_t len) } #endif +#if defined(LUA) + +static void processConfigPacket(const uint8_t * packet, uint8_t len) +{ + // Multi_Buffer[0..3]=="Conf" -> Lua script is running + // Multi_Buffer[4]==0x01 -> TX to Module data ready to be sent + // Multi_Buffer[4]==0xFF -> Clear buffer data + // Multi_Buffer[5..11]=7 bytes of TX to Module data + // Multi_Buffer[12] -> Current page + // Multi_Buffer[13..172]=8*20=160 bytes of Module to TX data + if (Multi_Buffer && memcmp(Multi_Buffer, "Conf", 4) == 0) { + // HoTT Lua script is running + if (Multi_Buffer[4] == 0xFF) { + // Init + memset(&Multi_Buffer[4], 0x00, 1 + 7 + 1 + 160); // Clear the buffer + } + if ((packet[0] >> 4) != Multi_Buffer[12]) {// page change + memset(&Multi_Buffer[13], 0x00, 160); // Clear the buffer + Multi_Buffer[12] = (packet[0] >> 4); //Save the page number + } + memcpy(&Multi_Buffer[13 + (packet[0] & 0x0F) * 20], &packet[1], 20); // Store the received page in the buffer + } +} +#endif + static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) { uint8_t type = packet[0]; @@ -363,9 +389,18 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) if (len > 6) processMLinkPacket(data); else - TRACE("[MP] Received M-Link telemetry len %d < 6", len); + TRACE("[MP] Received M-Link telemetry len %d <= 6", len); break; +#if defined(LUA) + case ConfigTelemetry: + if (len >= 21) + processConfigPacket(data, len); + else + TRACE("[MP] Received Config telemetry len %d < 20", len); + break; +#endif + case FrSkyHubTelemetry: if (len >= 4) frskyDProcessPacket(data); diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 1189443ba..0ab6d3594 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -118,6 +118,7 @@ extern uint8_t telemetryProtocol; || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX2)) #define IS_R9_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKY_R9) #define IS_HOTT_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_HOTT) + #define IS_CONFIG_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_CONFIG) #define IS_DSM_MULTI(module) (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) #define IS_RX_MULTI(module) ((g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_AFHDS2A_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_FRSKYX_RX) \ || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_BAYANG_RX) || (g_model.moduleData[module].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM_RX)) @@ -130,6 +131,7 @@ extern uint8_t telemetryProtocol; #define IS_D16_MULTI(module) false #define IS_R9_MULTI(module) false #define IS_HOTT_MULTI(module) false + #define IS_CONFIG_MULTI(module) false #define IS_DSM_MULTI(module) false #define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) #define IS_RX_MULTI(module) false diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index a758b1a31..e9a0831d4 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -131,7 +131,7 @@ #define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX" #define LEN_MULTI_PROTOCOLS "\007" -#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""Futaba\0""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""Height\0""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 ""Kyosho\0""RadLink""ExpLRS\0""Realacc""OMP\0 ""M-Link\0""Wfly 2\0""E016Hv2" +#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""Futaba\0""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""Height\0""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 ""Kyosho\0""RadLink""ExpLRS\0""Realacc""OMP\0 ""M-Link\0""Wfly 2\0""E016Hv2""E010r5 ""LOLI\0 ""E129\0 ""JOYSWAY""E016H\0 ""Config\0" #define LEN_MULTI_POWER "\005" #define TR_MULTI_POWER "1.6mW""2.0mW""2.5mW""3.2mW""4.0mW""5.0mW""6.3mW""7.9mW""10mW\0""13mW\0""16mW\0""20mW\0""25mW\0""32mW\0""40mW\0""50mW\0" From 92445a5d5a5dc20fe70d413c2525ff2eb0d41c8e Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 5 May 2021 19:39:37 +0200 Subject: [PATCH 37/70] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index bfffa5489..b2a932909 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2255,3 +2255,5 @@ Gary Busler Stefano Boggia Vernon Martin Alexander W Wilson Jr +Adam Bowersock +Gary Burrows From 68f3727d2c40601140ac1dd403763a4d5d94cde8 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 6 May 2021 07:42:36 +0200 Subject: [PATCH 38/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index b2a932909..b9062c26f 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2257,3 +2257,4 @@ Vernon Martin Alexander W Wilson Jr Adam Bowersock Gary Burrows +Mark Gaskievicz From 6291229444516cfe8ef9354450adb37887256724 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 7 May 2021 10:13:08 +0200 Subject: [PATCH 39/70] Fix model navigation for rotary enc radios --- radio/src/gui/128x64/model_select.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/128x64/model_select.cpp b/radio/src/gui/128x64/model_select.cpp index bcf04117d..0a76ed532 100644 --- a/radio/src/gui/128x64/model_select.cpp +++ b/radio/src/gui/128x64/model_select.cpp @@ -244,7 +244,7 @@ void menuModelSelect(event_t event) #endif #endif -#if defined(ROTARY_ENCODER) && defined(NAVIGATION_X7) +#if defined(ROTARY_ENCODER_NAVIGATION) && defined(NAVIGATION_X7) case EVT_ROTARY_LEFT: case EVT_ROTARY_RIGHT: #endif From dfc84a9b85b36686297e8ee4995f5579ca3ab960 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 7 May 2021 10:58:39 +0200 Subject: [PATCH 40/70] Fix windows compilation --- radio/src/pulses/multi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index de0d54730..c6e56126c 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -257,13 +257,13 @@ void sendChannels(uint8_t moduleIdx) void convertMultiProtocolToOtx(int *protocol, int *subprotocol) { - if (*protocol == 3 and *subprotocol == 0) { + if (*protocol == 3 && *subprotocol == 0) { *protocol = MODULE_SUBTYPE_MULTI_FRSKY + 1; *subprotocol = MM_RF_FRSKY_SUBTYPE_D8; return; } - if (*protocol == 3 and *subprotocol == 1) { + if (*protocol == 3 && *subprotocol == 1) { *protocol = MODULE_SUBTYPE_MULTI_FRSKY + 1; *subprotocol = MM_RF_FRSKY_SUBTYPE_D8_CLONED; return; From 02f25e8346f0b34187adc3d15f513e40849da0ac Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 7 May 2021 14:10:39 +0200 Subject: [PATCH 41/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index b9062c26f..d0c3ec24e 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2258,3 +2258,4 @@ Alexander W Wilson Jr Adam Bowersock Gary Burrows Mark Gaskievicz +James Miller From 1d22ad69458ab28f091c2b63f8166110aa05933c Mon Sep 17 00:00:00 2001 From: elecpower Date: Sat, 8 May 2021 08:32:22 +1000 Subject: [PATCH 42/70] New AutoWidget base class --- companion/src/shared/CMakeLists.txt | 15 ++++++- companion/src/shared/autocheckbox.cpp | 58 +++++++++++++++++++++++++ companion/src/shared/autocheckbox.h | 56 +++++------------------- companion/src/shared/autowidget.cpp | 61 +++++++++++++++++++++++++++ companion/src/shared/autowidget.h | 45 ++++++++++++++++++++ companion/src/shared/autowidgets.h | 32 ++++++++++++++ companion/src/shared/genericpanel.h | 3 +- 7 files changed, 223 insertions(+), 47 deletions(-) create mode 100644 companion/src/shared/autocheckbox.cpp create mode 100644 companion/src/shared/autowidget.cpp create mode 100644 companion/src/shared/autowidget.h create mode 100644 companion/src/shared/autowidgets.h diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index ffd5942bf..0fd2e32fb 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -1,5 +1,8 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) +set(shared_NAMES + autocheckbox +) set(shared_SRCS genericpanel.cpp hexspinbox.cpp @@ -8,7 +11,6 @@ set(shared_SRCS set(shared_HDRS autobitsetcheckbox.h - autocheckbox.h autocombobox.h autodoublespinbox.h autohexspinbox.h @@ -19,7 +21,18 @@ set(shared_HDRS autotimeedit.h ) +foreach(name ${shared_NAMES}) + set(shared_SRCS ${shared_SRCS} ${name}.cpp) + set(shared_HDRS ${shared_HDRS} ${name}.h) +endforeach() + qt5_wrap_cpp(shared_SRCS ${shared_HDRS}) +# add after moc generation to stop warnings +set(shared_SRCS ${shared_SRCS} + autowidget.h + autowidget.cpp +) + add_library(shared ${shared_SRCS}) target_link_libraries(shared PRIVATE Qt5::Widgets ${CPN_COMMON_LIB}) diff --git a/companion/src/shared/autocheckbox.cpp b/companion/src/shared/autocheckbox.cpp new file mode 100644 index 000000000..79570d335 --- /dev/null +++ b/companion/src/shared/autocheckbox.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autocheckbox.h" + +AutoCheckBox::AutoCheckBox(QWidget * parent): + QCheckBox(parent), + AutoWidget(), + m_field(nullptr) +{ + connect(this, &QCheckBox::toggled, this, &AutoCheckBox::onToggled); +} + +AutoCheckBox::~AutoCheckBox() +{ +} + +void AutoCheckBox::setField(bool & field, GenericPanel * panel) +{ + m_field = &field; + setPanel(panel); + updateValue(); +} + +void AutoCheckBox::onToggled(bool checked) +{ + if (!lock() && m_field) { + *m_field = checked; + emit currentDataChanged(checked); + dataChanged(); + } +} + +void AutoCheckBox::updateValue() +{ + if (m_field) { + setLock(true); + setChecked(*m_field); + setLock(false); + } +} diff --git a/companion/src/shared/autocheckbox.h b/companion/src/shared/autocheckbox.h index 1c1a7207c..240278643 100644 --- a/companion/src/shared/autocheckbox.h +++ b/companion/src/shared/autocheckbox.h @@ -20,62 +20,28 @@ #pragma once -#include -#include "genericpanel.h" +#include "autowidget.h" -class AutoCheckBox: public QCheckBox +#include + +class AutoCheckBox : public QCheckBox, AutoWidget { Q_OBJECT public: - explicit AutoCheckBox(QWidget * parent = nullptr): - QCheckBox(parent), - field(nullptr), - panel(nullptr), - lock(false) - { - connect(this, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool))); - } + explicit AutoCheckBox(QWidget * parent = nullptr); + ~AutoCheckBox(); - void setField(bool & field, GenericPanel * panel = nullptr) - { - this->field = &field; - this->panel = panel; - updateValue(); - } + virtual void updateValue() override; - void setEnabled(bool enabled) - { - QCheckBox::setEnabled(enabled); - } - - void updateValue() - { - if (field) { - lock = true; - setChecked(*field); - lock = false; - } - } + void setField(bool & field, GenericPanel * panel = nullptr); signals: void currentDataChanged(bool value); protected slots: - void onToggled(bool checked) - { - if (panel && panel->lock) - return; - if (field && !lock) { - *field = checked; - emit currentDataChanged(checked); - if (panel) - emit panel->modified(); - } - } + void onToggled(bool checked); - protected: - bool *field = nullptr; - GenericPanel *panel = nullptr; - bool lock = false; + private: + bool *m_field; }; diff --git a/companion/src/shared/autowidget.cpp b/companion/src/shared/autowidget.cpp new file mode 100644 index 000000000..75fd1fb26 --- /dev/null +++ b/companion/src/shared/autowidget.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autowidget.h" +#include "genericpanel.h" + +AutoWidget::AutoWidget(): + m_panel(nullptr), + m_lock(false) +{ +} + +AutoWidget::~AutoWidget() +{ +} + +bool AutoWidget::lock() +{ + return panelLock() | m_lock; +} + +void AutoWidget::setLock(bool lock) +{ + m_lock = lock; +} + +void AutoWidget::setPanel(GenericPanel * panel) +{ + m_panel = panel; +} + +void AutoWidget::dataChanged() +{ + if (m_panel) + emit m_panel->modified(); +} + +bool AutoWidget::panelLock() +{ + if (m_panel) + return m_panel->lock; + else + return false; +} diff --git a/companion/src/shared/autowidget.h b/companion/src/shared/autowidget.h new file mode 100644 index 000000000..68d47547d --- /dev/null +++ b/companion/src/shared/autowidget.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +class GenericPanel; + +// Note: cannot be a Qt object as it will create a compiler ambiguity in the inheriting class +class AutoWidget +{ + public: + explicit AutoWidget(); + ~AutoWidget(); + + protected: + virtual void updateValue() = 0; + + bool lock(); + void setLock(bool lock); + void setPanel(GenericPanel * panel); + + void dataChanged(); + bool panelLock(); + + private: + GenericPanel *m_panel; + bool m_lock; +}; diff --git a/companion/src/shared/autowidgets.h b/companion/src/shared/autowidgets.h new file mode 100644 index 000000000..b2619acdb --- /dev/null +++ b/companion/src/shared/autowidgets.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "autobitsetcheckbox.h" +#include "autocheckbox.h" +#include "autocombobox.h" +#include "autodoublespinbox.h" +#include "autohexspinbox.h" +#include "autolineedit.h" +#include "autoprecisioncombobox.h" +#include "autoslider.h" +#include "autospinbox.h" +#include "autotimeedit.h" diff --git a/companion/src/shared/genericpanel.h b/companion/src/shared/genericpanel.h index 88c7f841b..d4d94cf46 100644 --- a/companion/src/shared/genericpanel.h +++ b/companion/src/shared/genericpanel.h @@ -34,13 +34,14 @@ class GenericPanel : public QWidget friend class AutoComboBox; friend class AutoDoubleSpinBox; - friend class AutoCheckBox; friend class AutoHexSpinBox; friend class AutoLineEdit; friend class GVarGroup; friend class AutoPrecisionComboBox; friend class AutoBitsetCheckBox; friend class AutoTimeEdit; + // this should be the only auto friend required excl GVArGroup + friend class AutoWidget; public: GenericPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware); From 674a5cd9381b401e3a8dc78a58fd8eb6f7b9e8b3 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 8 May 2021 10:50:08 +0200 Subject: [PATCH 43/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index d0c3ec24e..1c9640f0d 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2259,3 +2259,4 @@ Adam Bowersock Gary Burrows Mark Gaskievicz James Miller +Donald Taylor From ef90933f6696a846499d934585551404b0deddef Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 9 May 2021 12:23:53 +0200 Subject: [PATCH 44/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 1c9640f0d..a0a5afc3f 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2260,3 +2260,4 @@ Gary Burrows Mark Gaskievicz James Miller Donald Taylor +Paul Makepeace From 10e7a4fc475a21e4b470b50ce0252aac45c538da Mon Sep 17 00:00:00 2001 From: elecpower Date: Mon, 10 May 2021 06:57:34 +1000 Subject: [PATCH 45/70] Refactor autoxxxxx to use autowidget --- companion/src/shared/CMakeLists.txt | 30 +-- companion/src/shared/autobitsetcheckbox.cpp | 160 ++++++++++++ companion/src/shared/autobitsetcheckbox.h | 169 ++---------- companion/src/shared/autocheckbox.cpp | 2 +- companion/src/shared/autocheckbox.h | 2 +- companion/src/shared/autocombobox.cpp | 177 +++++++++++++ companion/src/shared/autocombobox.h | 179 ++----------- companion/src/shared/autodoublespinbox.cpp | 92 +++++++ companion/src/shared/autodoublespinbox.h | 91 ++----- companion/src/shared/autohexspinbox.cpp | 95 +++++++ companion/src/shared/autohexspinbox.h | 66 ++--- companion/src/shared/autolineedit.cpp | 82 ++++++ companion/src/shared/autolineedit.h | 76 +----- .../src/shared/autoprecisioncombobox.cpp | 227 +++++++++++++++++ companion/src/shared/autoprecisioncombobox.h | 241 ++---------------- companion/src/shared/autoslider.cpp | 89 +++++++ companion/src/shared/autoslider.h | 79 +----- companion/src/shared/autospinbox.cpp | 71 ++++++ companion/src/shared/autospinbox.h | 61 ++--- companion/src/shared/autotimeedit.cpp | 71 ++++++ companion/src/shared/autotimeedit.h | 76 +----- companion/src/shared/autowidget.h | 2 +- companion/src/shared/genericpanel.h | 10 - companion/src/shared/hexspinbox.cpp | 47 ---- companion/src/shared/hexspinbox.h | 41 --- companion/src/shared/verticalscrollarea.h | 2 + 26 files changed, 1258 insertions(+), 980 deletions(-) create mode 100644 companion/src/shared/autobitsetcheckbox.cpp create mode 100644 companion/src/shared/autocombobox.cpp create mode 100644 companion/src/shared/autodoublespinbox.cpp create mode 100644 companion/src/shared/autohexspinbox.cpp create mode 100644 companion/src/shared/autolineedit.cpp create mode 100644 companion/src/shared/autoprecisioncombobox.cpp create mode 100644 companion/src/shared/autoslider.cpp create mode 100644 companion/src/shared/autospinbox.cpp create mode 100644 companion/src/shared/autotimeedit.cpp delete mode 100644 companion/src/shared/hexspinbox.cpp delete mode 100644 companion/src/shared/hexspinbox.h diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index d63045061..bfd4d60fa 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -1,26 +1,18 @@ include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set(shared_NAMES + genericpanel + verticalscrollarea + autobitsetcheckbox autocheckbox -) -set(shared_SRCS - genericpanel.cpp - hexspinbox.cpp - verticalscrollarea.cpp -) - -set(shared_HDRS - autobitsetcheckbox.h - autocombobox.h - autodoublespinbox.h - autohexspinbox.h - autolineedit.h - genericpanel.h - hexspinbox.h - autoprecisioncombobox.h - autotimeedit.h - autospinbox.h - autoslider.h + autocombobox + autodoublespinbox + autohexspinbox + autolineedit + autoprecisioncombobox + autoslider + autospinbox + autotimeedit ) foreach(name ${shared_NAMES}) diff --git a/companion/src/shared/autobitsetcheckbox.cpp b/companion/src/shared/autobitsetcheckbox.cpp new file mode 100644 index 000000000..93faf35e5 --- /dev/null +++ b/companion/src/shared/autobitsetcheckbox.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autobitsetcheckbox.h" + +AutoBitsetCheckBox::AutoBitsetCheckBox(QWidget * parent) : + AutoBitsetCheckBox(QString(), parent) +{ +} + +AutoBitsetCheckBox::AutoBitsetCheckBox(const QString & text, QWidget * parent) : + QCheckBox(text, parent), + AutoWidget() +{ + init(); +} + +// int field constructors +AutoBitsetCheckBox::AutoBitsetCheckBox(int & field, int bitmask, const QString & text, QWidget * parent) : + AutoBitsetCheckBox(field, bitmask, false, text, parent) +{ +} + +AutoBitsetCheckBox::AutoBitsetCheckBox(int & field, int bitmask, bool invert, const QString & text, QWidget * parent) : + QCheckBox(text, parent), + AutoWidget() +{ + setField(field, bitmask, invert); + init(); +} + +AutoBitsetCheckBox::AutoBitsetCheckBox(int & field, int bitmask, int toggleMask, const QString & text, QWidget * parent) : + QCheckBox(text, parent), + AutoWidget() +{ + setField(field, bitmask, false, toggleMask); + init(); +} + +// unsigned field constructors +AutoBitsetCheckBox::AutoBitsetCheckBox(unsigned & field, int bitmask, const QString & text, QWidget * parent) : + AutoBitsetCheckBox(field, bitmask, false, text, parent) +{ +} + +AutoBitsetCheckBox::AutoBitsetCheckBox(unsigned & field, int bitmask, bool invert, const QString & text, QWidget * parent) : + QCheckBox(text, parent), + AutoWidget() +{ + setField(field, bitmask, invert); + init(); +} + +AutoBitsetCheckBox::AutoBitsetCheckBox(unsigned & field, int bitmask, int toggleMask, const QString & text, QWidget * parent) : + QCheckBox(text, parent), + AutoWidget() +{ + setField(field, bitmask, false, toggleMask); + init(); +} + +AutoBitsetCheckBox::~AutoBitsetCheckBox() +{ +} + +void AutoBitsetCheckBox::setField(int & field, int bitmask, bool invert, int toggleMask) +{ + m_field = &field; + initField(bitmask, invert, toggleMask); +} + +void AutoBitsetCheckBox::setField(unsigned & field, int bitmask, bool invert, int toggleMask) +{ + m_field = (int *)&field; + initField(bitmask, invert, toggleMask); +} + +void AutoBitsetCheckBox::setBitmask(int bitmask) +{ + m_bitmask = bitmask; + updateValue(); +} + +void AutoBitsetCheckBox::setToggleMask(int toggleMask) +{ + m_toggleMask = toggleMask; + updateValue(); +} + +void AutoBitsetCheckBox::setInverted(bool invert) +{ + m_invert = invert; + updateValue(); +} + +void AutoBitsetCheckBox::updateValue() +{ + if (m_field) + setLock(true); + setChecked((m_invert && !m_toggleMask) != bool(*m_field & m_bitmask)); + setLock(false); +} + +void AutoBitsetCheckBox::onToggled(bool checked) +{ + if (!m_field || lock()) + return; + + if (m_toggleMask) { + if (checked) { + *m_field &= ~m_toggleMask; + *m_field |= m_bitmask; + } + else { + *m_field &= ~m_bitmask; + *m_field |= m_toggleMask; + } + } + else { + if (m_invert) + checked = !checked; + if (checked) + *m_field |= m_bitmask; + else + *m_field &= ~m_bitmask; + } + + emit currentDataChanged(checked); + dataChanged(); +} + +void AutoBitsetCheckBox::init() +{ + connect(this, &QCheckBox::toggled, this, &AutoBitsetCheckBox::onToggled); +} + +void AutoBitsetCheckBox::initField(int bitmask, bool invert, int toggleMask) +{ + m_bitmask = bitmask; + m_toggleMask = toggleMask; + m_invert = toggleMask ? false : invert; + updateValue(); +} diff --git a/companion/src/shared/autobitsetcheckbox.h b/companion/src/shared/autobitsetcheckbox.h index af831948e..6c3fef5c7 100644 --- a/companion/src/shared/autobitsetcheckbox.h +++ b/companion/src/shared/autobitsetcheckbox.h @@ -20,165 +20,50 @@ #pragma once -#include -#include "genericpanel.h" +#include "autowidget.h" -class AutoBitsetCheckBox: public QCheckBox +#include + +class AutoBitsetCheckBox: public QCheckBox, AutoWidget { Q_OBJECT - //! \property bitmask The value (shifted bit(s)) to set/clear based on checked state. - Q_PROPERTY(int bitmask READ bitmask WRITE setBitmask) - //! \property inverted If \e true, then the \p bitmask is cleared when the checkbox is checked, and vice versa. Default behavior is to set the bitmask when checked. - Q_PROPERTY(bool inverted READ inverted WRITE setInverted) - //! \property toggleMask If > 0, then set this value when clearing the \p bitmask value (toggles between the two masks being set). \p inverted is ignored if \p toggleMask is set. - Q_PROPERTY(int toggleMask READ toggleMask WRITE setToggleMask) public: - explicit AutoBitsetCheckBox(QWidget *parent = nullptr) : - AutoBitsetCheckBox(QString(), parent) {} - explicit AutoBitsetCheckBox(const QString &text, QWidget *parent = nullptr) : - QCheckBox(text, parent) - { - init(); - } + explicit AutoBitsetCheckBox(QWidget * parent = nullptr); + explicit AutoBitsetCheckBox(const QString &text, QWidget * parent = nullptr); // int field constructors - explicit AutoBitsetCheckBox(int & field, int bitmask, const QString &text = QString(), QWidget *parent = nullptr) : - AutoBitsetCheckBox(field, bitmask, false, text, parent) {} - explicit AutoBitsetCheckBox(int & field, int bitmask, bool invert, const QString &text = QString(), QWidget *parent = nullptr) : - QCheckBox(text, parent) - { - setField(field, bitmask, invert); - init(); - } - explicit AutoBitsetCheckBox(int & field, int bitmask, int toggleMask, const QString &text = QString(), QWidget *parent = nullptr) : - QCheckBox(text, parent) - { - setField(field, bitmask, false, toggleMask); - init(); - } + explicit AutoBitsetCheckBox(int & field, int bitmask, const QString & text = QString(), QWidget * parent = nullptr); + explicit AutoBitsetCheckBox(int & field, int bitmask, bool invert, const QString & text = QString(), QWidget * parent = nullptr); + explicit AutoBitsetCheckBox(int & field, int bitmask, int toggleMask, const QString & text = QString(), QWidget * parent = nullptr); // unsigned field constructors - explicit AutoBitsetCheckBox(unsigned & field, int bitmask, const QString &text = QString(), QWidget *parent = nullptr) : - AutoBitsetCheckBox(field, bitmask, false, text, parent) {} - explicit AutoBitsetCheckBox(unsigned & field, int bitmask, bool invert, const QString &text = QString(), QWidget *parent = nullptr) : - QCheckBox(text, parent) - { - setField(field, bitmask, invert); - init(); - } - explicit AutoBitsetCheckBox(unsigned & field, int bitmask, int toggleMask, const QString &text = QString(), QWidget *parent = nullptr) : - QCheckBox(text, parent) - { - setField(field, bitmask, false, toggleMask); - init(); - } + explicit AutoBitsetCheckBox(unsigned & field, int bitmask, const QString & text = QString(), QWidget * parent = nullptr); + explicit AutoBitsetCheckBox(unsigned & field, int bitmask, bool invert, const QString & text = QString(), QWidget * parent = nullptr); + explicit AutoBitsetCheckBox(unsigned & field, int bitmask, int toggleMask, const QString & text = QString(), QWidget * parent = nullptr); - inline int bitmask() const { return m_bitmask; } - inline int toggleMask() const { return m_toggleMask; } - inline bool inverted() const { return m_toggleMask ? false : m_invert; } + virtual ~AutoBitsetCheckBox(); - public slots: - void setField(int & field, int bitmask = 0, bool invert = false, int toggleMask = 0) - { - m_field = &field; - initField(bitmask, invert, toggleMask); - } + virtual void updateValue() override; - void setField(unsigned & field, int bitmask = 0, bool invert = false, int toggleMask = 0) - { - m_field = reinterpret_cast(&field); - initField(bitmask, invert, toggleMask); - } + void setField(int & field, int bitmask = 0, bool invert = false, int toggleMask = 0); + void setField(unsigned & field, int bitmask = 0, bool invert = false, int toggleMask = 0); + void setBitmask(int bitmask); + void setToggleMask(int toggleMask); + void setInverted(bool invert); - void setBitmask(int bitmask) - { - m_bitmask = bitmask; - updateValue(); - } - - void setToggleMask(int toggleMask) - { - m_toggleMask = toggleMask; - updateValue(); - } - - void setInverted(bool invert) - { - m_invert = invert; - updateValue(); - } - - void updateValue() - { - if (m_panel && m_panel->lock) - return; - if (!m_field) - return; - const bool oldLock = setLocked(true); - setChecked((m_invert && !m_toggleMask) != bool(*m_field & m_bitmask)); - setLocked(oldLock); - } - - void setPanel(GenericPanel * panel) - { - m_panel = panel; - } + signals: + void currentDataChanged(bool checked); protected slots: - void init() - { - connect(this, &AutoBitsetCheckBox::toggled, this, &AutoBitsetCheckBox::onToggled); - } + void onToggled(bool checked); - void initField(int bitmask, bool invert, int toggleMask) - { - m_bitmask = bitmask; - m_toggleMask = toggleMask; - m_invert = toggleMask ? false : invert; - updateValue(); - } - - void onToggled(bool checked) - { - if (!m_field) - return; - - if (m_toggleMask) { - if (checked) { - *m_field &= ~m_toggleMask; - *m_field |= m_bitmask; - } - else { - *m_field &= ~m_bitmask; - *m_field |= m_toggleMask; - } - } - else { - if (m_invert) - checked = !checked; - if (checked) - *m_field |= m_bitmask; - else - *m_field &= ~m_bitmask; - } - - if (m_panel && !m_lock) - emit m_panel->modified(); - } - - bool setLocked(bool lock) - { - const bool ret = m_lock; - m_lock = lock; - return ret; - } - - protected: - int * m_field = nullptr; + private: + int *m_field = nullptr; int m_bitmask = 0; int m_toggleMask = 0; bool m_invert = false; - bool m_lock = false; - GenericPanel * m_panel = nullptr; + + void init(); + void initField(int bitmask, bool invert, int toggleMask); }; diff --git a/companion/src/shared/autocheckbox.cpp b/companion/src/shared/autocheckbox.cpp index 73b21294c..a2af1395c 100644 --- a/companion/src/shared/autocheckbox.cpp +++ b/companion/src/shared/autocheckbox.cpp @@ -49,7 +49,7 @@ void AutoCheckBox::setInvert(bool invert) void AutoCheckBox::onToggled(bool checked) { - if (!lock() && m_field) { + if (m_field && !lock()) { const bool val = m_invert ? !checked : checked; *m_field = val; emit currentDataChanged(val); diff --git a/companion/src/shared/autocheckbox.h b/companion/src/shared/autocheckbox.h index a9a1ef94e..4f4e3c992 100644 --- a/companion/src/shared/autocheckbox.h +++ b/companion/src/shared/autocheckbox.h @@ -30,7 +30,7 @@ class AutoCheckBox : public QCheckBox, AutoWidget public: explicit AutoCheckBox(QWidget * parent = nullptr); - ~AutoCheckBox(); + virtual ~AutoCheckBox(); virtual void updateValue() override; diff --git a/companion/src/shared/autocombobox.cpp b/companion/src/shared/autocombobox.cpp new file mode 100644 index 000000000..a14e08f2e --- /dev/null +++ b/companion/src/shared/autocombobox.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autocombobox.h" + +AutoComboBox::AutoComboBox(QWidget * parent): + QComboBox(parent), + AutoWidget(), + m_field(nullptr), + m_next(0), + m_hasModel(false), + m_rawSource(nullptr), + m_rawSwitch(nullptr) +{ + connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int))); +} + +AutoComboBox::~AutoComboBox() +{ +} + +void AutoComboBox::clear() +{ + if (m_hasModel) + return; + + setLock(true); + QComboBox::clear(); + m_next = 0; + setLock(false); +} + +void AutoComboBox::insertItems(int index, const QStringList & items) +{ + if (m_hasModel) + return; + + foreach(QString item, items) { + addItem(item); + } +} + +void AutoComboBox::addItem(const QString & item) +{ + if (m_hasModel) + return; + + addItem(item, m_next++); +} + +void AutoComboBox::addItem(const QString & item, int value) +{ + if (m_hasModel) + return; + + setLock(true); + QComboBox::addItem(item, value); + setLock(false); + updateValue(); +} + +void AutoComboBox::setField(unsigned int & field, GenericPanel * panel) +{ + m_field = (int *)&field; + m_rawSource = nullptr; + m_rawSwitch = nullptr; + setFieldInit(panel); +} + +void AutoComboBox::setField(int & field, GenericPanel * panel) +{ + m_field = &field; + m_rawSource = nullptr; + m_rawSwitch = nullptr; + setFieldInit(panel); +} + +void AutoComboBox::setField(RawSource & field, GenericPanel * panel) +{ + m_rawSource = &field; + m_rawSwitch = nullptr; + m_field = nullptr; + setFieldInit(panel); +} + +void AutoComboBox::setField(RawSwitch & field, GenericPanel * panel) +{ + m_rawSwitch = &field; + m_rawSource = nullptr; + m_field = nullptr; + setFieldInit(panel); +} + +void AutoComboBox::setFieldInit(GenericPanel * panel) +{ + setPanel(panel); + updateValue(); +} + +void AutoComboBox::setModel(QAbstractItemModel * model) +{ + setLock(true); + QComboBox::setModel(model); + setLock(false); + m_hasModel = true; + updateValue(); +} + +void AutoComboBox::setAutoIndexes() +{ + if (m_hasModel) + return; + + for (int i = 0; i < count(); ++i) + setItemData(i, i); + updateValue(); +} + +void AutoComboBox::updateValue() +{ + if (!m_field && !m_rawSource && !m_rawSwitch) + return; + + setLock(true); + + if (m_field) + setCurrentIndex(findData(*m_field)); + else if (m_rawSource) + setCurrentIndex(findData(m_rawSource->toValue())); + else if (m_rawSwitch) + setCurrentIndex(findData(m_rawSwitch->toValue())); + + setLock(false); +} + +void AutoComboBox::onCurrentIndexChanged(int index) +{ + if (lock() || index < 0) + return; + + bool ok; + const int val = itemData(index).toInt(&ok); + if (!ok) + return; + + if (m_field && *m_field != val) { + *m_field = val; + } + else if (m_rawSource && m_rawSource->toValue() != val) { + *m_rawSource = RawSource(val); + } + else if (m_rawSwitch && m_rawSwitch->toValue() != val) { + *m_rawSwitch = RawSwitch(val); + } + else + return; + + emit currentDataChanged(val); + dataChanged(); +} diff --git a/companion/src/shared/autocombobox.h b/companion/src/shared/autocombobox.h index ca6054555..5cecd3e70 100644 --- a/companion/src/shared/autocombobox.h +++ b/companion/src/shared/autocombobox.h @@ -20,174 +20,49 @@ #pragma once -#include -#include "genericpanel.h" +#include "autowidget.h" #include "rawsource.h" #include "rawswitch.h" -class AutoComboBox: public QComboBox +#include + +class AutoComboBox : public QComboBox, AutoWidget { Q_OBJECT public: - explicit AutoComboBox(QWidget * parent = nullptr): - QComboBox(parent), - field(nullptr), - panel(nullptr), - next(0), - lock(false), - hasModel(false), - rawSource(nullptr), - rawSwitch(nullptr) - { - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int))); - } + explicit AutoComboBox(QWidget * parent = nullptr); + virtual ~AutoComboBox(); - void clear() - { - if (!hasModel) { - lock = true; - QComboBox::clear(); - next = 0; - lock = false; - } - } + // QComboBox + virtual void addItem(const QString & item); + virtual void addItem(const QString & item, int value); + virtual void insertItems(int index, const QStringList & items); + // AutoWidget + virtual void updateValue() override; - virtual void insertItems(int index, const QStringList & items) - { - if (!hasModel) { - foreach(QString item, items) { - addItem(item); - } - } - } + void clear(); - virtual void addItem(const QString & item) - { - if (!hasModel) - addItem(item, next++); - } + void setField(unsigned int & field, GenericPanel * panel = nullptr); + void setField(int & field, GenericPanel * panel = nullptr); + void setField(RawSource & field, GenericPanel * panel = nullptr); + void setField(RawSwitch & field, GenericPanel * panel = nullptr); - virtual void addItem(const QString & item, int value) - { - if (!hasModel) { - lock = true; - QComboBox::addItem(item, value); - lock = false; - updateValue(); - } - } - - void setField(unsigned int & field, GenericPanel * panel = nullptr) - { - this->field = (int *)&field; - this->rawSource = nullptr; - this->rawSwitch = nullptr; - this->panel = panel; - updateValue(); - } - - void setField(int & field, GenericPanel * panel = nullptr) - { - this->field = &field; - this->rawSource = nullptr; - this->rawSwitch = nullptr; - this->panel = panel; - updateValue(); - } - - void setField(RawSource & field, GenericPanel * panel = nullptr) - { - this->rawSource = &field; - this->rawSwitch = nullptr; - this->field = nullptr; - this->panel = panel; - updateValue(); - } - - void setField(RawSwitch & field, GenericPanel * panel = nullptr) - { - this->rawSwitch = &field; - this->rawSource = nullptr; - this->field = nullptr; - this->panel = panel; - updateValue(); - } - - void setModel(QAbstractItemModel * model) - { - lock = true; - QComboBox::setModel(model); - lock = false; - hasModel = true; - updateValue(); - } - - void setAutoIndexes() - { - if (!hasModel) { - for (int i = 0; i < count(); ++i) - setItemData(i, i); - updateValue(); - } - } - - void updateValue() - { - if (!field && !rawSource && !rawSwitch) - return; - - lock = true; - - if (field) - setCurrentIndex(findData(*field)); - else if (rawSource) - setCurrentIndex(findData(rawSource->toValue())); - else if (rawSwitch) - setCurrentIndex(findData(rawSwitch->toValue())); - - lock = false; - } + void setAutoIndexes(); + void setModel(QAbstractItemModel * model); signals: void currentDataChanged(int value); protected slots: - void onCurrentIndexChanged(int index) - { - if (panel && panel->lock) - return; - if (lock || index < 0) - return; + void onCurrentIndexChanged(int index); - bool ok; - const int val = itemData(index).toInt(&ok); - if (!ok) - return; + private: + int *m_field; + int m_next; + bool m_hasModel; + RawSource *m_rawSource; + RawSwitch *m_rawSwitch; - if (field && *field != val) { - *field = val; - } - else if (rawSource && rawSource->toValue() != val) { - *rawSource = RawSource(val); - } - else if (rawSwitch && rawSwitch->toValue() != val) { - *rawSwitch = RawSwitch(val); - } - else - return; - - emit currentDataChanged(val); - if (panel) - emit panel->modified(); - } - - protected: - int *field = nullptr; - GenericPanel *panel = nullptr; - int next = 0; - bool lock = false; - bool hasModel = false; - RawSource *rawSource = nullptr; - RawSwitch *rawSwitch = nullptr; + void setFieldInit(GenericPanel * panel); }; diff --git a/companion/src/shared/autodoublespinbox.cpp b/companion/src/shared/autodoublespinbox.cpp new file mode 100644 index 000000000..a5590035f --- /dev/null +++ b/companion/src/shared/autodoublespinbox.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autodoublespinbox.h" + +AutoDoubleSpinBox::AutoDoubleSpinBox(QWidget * parent): + QDoubleSpinBox(parent), + AutoWidget(), + m_field(nullptr), + m_offset(0) +{ + connect(this, SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double))); +} + +AutoDoubleSpinBox::~AutoDoubleSpinBox() +{ +} + +void AutoDoubleSpinBox::setField(int & field, GenericPanel * panel) +{ + m_field = &field; + setPanel(panel); + updateValue(); +} + +void AutoDoubleSpinBox::setField(unsigned int & field, GenericPanel * panel) +{ + m_field = (int *)&field; + setPanel(panel); + updateValue(); +} + +void AutoDoubleSpinBox::setDecimals(int prec) +{ + QDoubleSpinBox::setDecimals(prec); + updateValue(); +} + +void AutoDoubleSpinBox::setOffset(int offset) +{ + m_offset = offset; + updateValue(); +} + +void AutoDoubleSpinBox::updateValue() +{ + if (m_field) { + setLock(true); + setValue(float(*m_field + m_offset) / multiplier()); + setLock(false); + } +} + +int AutoDoubleSpinBox::multiplier() +{ + switch (decimals()) { + case 1: + return 10; + case 2: + return 100; + case 3: + return 1000; + default: + return 1; + } + } + +void AutoDoubleSpinBox::onValueChanged(double value) +{ + if (m_field && !lock()) { + *m_field = round(value * multiplier() - m_offset); + emit currentDataChanged(*m_field); + dataChanged(); + } +} diff --git a/companion/src/shared/autodoublespinbox.h b/companion/src/shared/autodoublespinbox.h index f9614d882..fb3b26591 100644 --- a/companion/src/shared/autodoublespinbox.h +++ b/companion/src/shared/autodoublespinbox.h @@ -20,95 +20,38 @@ #pragma once +#include "autowidget.h" + #include -#include "genericpanel.h" + #if __GNUC__ #include #endif -class AutoDoubleSpinBox: public QDoubleSpinBox +class AutoDoubleSpinBox : public QDoubleSpinBox, AutoWidget { Q_OBJECT public: - explicit AutoDoubleSpinBox(QWidget * parent = nullptr): - QDoubleSpinBox(parent), - field(nullptr), - panel(nullptr), - lock(false), - offset(0) - { - connect(this, SIGNAL(valueChanged(double)), this, SLOT(onValueChanged(double))); - } + explicit AutoDoubleSpinBox(QWidget * parent = nullptr); + virtual ~AutoDoubleSpinBox(); - void setField(int & field, GenericPanel * panel = nullptr) - { - this->field = &field; - this->panel = panel; - updateValue(); - } + virtual void updateValue() override; - void setField(unsigned int & field, GenericPanel * panel = nullptr) - { - this->field = (int *)&field; - this->panel = panel; - updateValue(); - } - - void updateValue() - { - if (field) { - lock = true; - setValue(float(*field + offset) / multiplier()); - lock = false; - } - } - - void setDecimals(int prec) - { - QDoubleSpinBox::setDecimals(prec); - updateValue(); - } - - void setOffset(int offset) - { - this->offset = offset; - updateValue(); - } - - protected: - int multiplier() - { - switch (decimals()) { - case 1: - return 10; - case 2: - return 100; - default: - return 1; - } - } + void setField(int & field, GenericPanel * panel = nullptr); + void setField(unsigned int & field, GenericPanel * panel = nullptr); + void setDecimals(int prec); + void setOffset(int offset); signals: void currentDataChanged(double value); protected slots: - void onValueChanged(double value) - { - if (panel && panel->lock) - return; - if (field && !lock) { - *field = round(value * multiplier() - offset); - emit currentDataChanged(*field); - if (panel) { - emit panel->modified(); - } - } - } + void onValueChanged(double value); - protected: - int * field = nullptr; - GenericPanel * panel = nullptr; - bool lock = false; - int offset = 0; + private: + int *m_field; + int m_offset; + + int multiplier(); }; diff --git a/companion/src/shared/autohexspinbox.cpp b/companion/src/shared/autohexspinbox.cpp new file mode 100644 index 000000000..3096a1c2f --- /dev/null +++ b/companion/src/shared/autohexspinbox.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autohexspinbox.h" + +AutoHexSpinBox::AutoHexSpinBox(QWidget * parent): + QSpinBox(parent), + AutoWidget(), + m_field(nullptr) +{ + setRange(0, AUTOHEXSPINBOX_MAX_VALUE); + connect(this, QOverload::of(&QSpinBox::valueChanged), this, &AutoHexSpinBox::onValueChanged); +} + +AutoHexSpinBox::~AutoHexSpinBox() +{ +} + +void AutoHexSpinBox::setField(unsigned int & field, const unsigned int min, const unsigned int max, GenericPanel * panel) +{ + m_field = &field; + setRange(min, max); + setPanel(panel); + updateValue(); +} + +void AutoHexSpinBox::setField(unsigned int & field, GenericPanel * panel) +{ + m_field = &field; + setRange(0, AUTOHEXSPINBOX_MAX_VALUE); + setPanel(panel); + updateValue(); +} + +void AutoHexSpinBox::setRange(const unsigned int min, const unsigned int max) +{ + QSpinBox::setRange(min, max); + + m_length = QString("%1").arg(max, 0, 16).size(); + + m_validator = new QRegExpValidator(QRegExp(QString("[0-9A-Fa-f]{1,%1}").arg(m_length)), this); +} + +void AutoHexSpinBox::updateValue() +{ + if (m_field) { + setLock(true); + setValue(*m_field); + setLock(false); + } +} + +void AutoHexSpinBox::onValueChanged(int value) +{ + if (m_field && !lock()) { + if (*m_field != (unsigned)value) { + *m_field = (unsigned)value; + emit currentDataChanged(value); + dataChanged(); + } + } +} + +// reimplemented +QValidator::State AutoHexSpinBox::validate(QString &text, int &pos) const +{ + return m_validator->validate(text, pos); +} + +int AutoHexSpinBox::valueFromText(const QString &text) const +{ + return text.toInt(0, 16); +} + +QString AutoHexSpinBox::textFromValue(int value) const +{ + return QString("%1").arg(value, m_length, 16, QChar('0')).toUpper(); +} diff --git a/companion/src/shared/autohexspinbox.h b/companion/src/shared/autohexspinbox.h index 40cc24da4..440fb4740 100644 --- a/companion/src/shared/autohexspinbox.h +++ b/companion/src/shared/autohexspinbox.h @@ -20,58 +20,42 @@ #pragma once -#include "hexspinbox.h" -#include "genericpanel.h" +#include "autowidget.h" -class AutoHexSpinBox: public HexSpinBox +#include +#include + +class QRegExpValidator; + +class AutoHexSpinBox : public QSpinBox, AutoWidget { Q_OBJECT public: - explicit AutoHexSpinBox(QWidget * parent = nullptr): - HexSpinBox(parent), - field(nullptr), - panel(nullptr), - lock(false) - { - connect(this, SIGNAL(valueChanged(int)), this, SLOT(onValueChanged(int))); - } + constexpr static unsigned int AUTOHEXSPINBOX_MAX_VALUE {65535}; - void setField(unsigned int & field, GenericPanel * panel = nullptr) - { - this->field = &field; - this->panel = panel; - updateValue(); - } + explicit AutoHexSpinBox(QWidget * parent = nullptr); + virtual ~AutoHexSpinBox(); - void updateValue() - { - if (field) { - lock = true; - setValue(*field); - lock = false; - } - } + virtual void updateValue(); + + void setField(unsigned int & field, const unsigned int min = 0, const unsigned int max = AUTOHEXSPINBOX_MAX_VALUE, GenericPanel * panel = nullptr); + void setField(unsigned int & field, GenericPanel * panel = nullptr); + void setRange(unsigned int min = 0, unsigned int max = AUTOHEXSPINBOX_MAX_VALUE); + + protected: + QValidator::State validate(QString &text, int &pos) const; + int valueFromText(const QString &text) const; + QString textFromValue(int value) const; signals: void currentDataChanged(int value); protected slots: - void onValueChanged(int value) - { - if (panel && panel->lock) - return; - if (field && !lock) { - *field = value; - emit currentDataChanged(value); - if (panel) { - emit panel->modified(); - } - } - } + void onValueChanged(int value); - protected: - unsigned int * field = nullptr; - GenericPanel * panel = nullptr; - bool lock = false; + private: + unsigned int *m_field; + QRegExpValidator *m_validator; + unsigned int m_length; }; diff --git a/companion/src/shared/autolineedit.cpp b/companion/src/shared/autolineedit.cpp new file mode 100644 index 000000000..79e92d482 --- /dev/null +++ b/companion/src/shared/autolineedit.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autolineedit.h" + +AutoLineEdit::AutoLineEdit(QWidget * parent, bool updateOnChange): + QLineEdit(parent), + AutoWidget(), + m_charField(NULL), + m_strField(nullptr) +{ + if (updateOnChange) + connect(this, &QLineEdit::textChanged, this, &AutoLineEdit::onEdited); + else + connect(this, &QLineEdit::editingFinished, this, &AutoLineEdit::onEdited); +} + +AutoLineEdit::~AutoLineEdit() +{ +} + +void AutoLineEdit::setField(char * field, int len, GenericPanel * panel) +{ + m_charField = field; + setPanel(panel); + setValidator(new QRegExpValidator(QRegExp("[ A-Za-z0-9_.-,]*"), this)); + if (len) + setMaxLength(len); + updateValue(); +} + +void AutoLineEdit::setField(QString & field, int len, GenericPanel * panel) +{ + m_strField = &field; + if (len) + setMaxLength(len); + setPanel(panel); + updateValue(); +} + +void AutoLineEdit::updateValue() +{ + setLock(true); + if (m_strField) + setText(*m_strField); + else if (m_charField) + setText(m_charField); + setLock(false); +} + +void AutoLineEdit::onEdited() +{ + if (lock()) + return; + + if (m_strField && *m_strField != text()) + *m_strField = text(); + else if (m_charField && strcmp(m_charField, text().toLatin1())) + strcpy(m_charField, text().toLatin1()); + else + return; + + emit currentDataChanged(); + dataChanged(); +} diff --git a/companion/src/shared/autolineedit.h b/companion/src/shared/autolineedit.h index b2815796c..0820bc5dc 100644 --- a/companion/src/shared/autolineedit.h +++ b/companion/src/shared/autolineedit.h @@ -20,83 +20,31 @@ #pragma once +#include "autowidget.h" + #include #include -#include "genericpanel.h" -class AutoLineEdit: public QLineEdit +class AutoLineEdit: public QLineEdit, AutoWidget { Q_OBJECT public: - explicit AutoLineEdit(QWidget * parent = nullptr, bool updateOnChange = false): - QLineEdit(parent), - field(NULL), - strField(nullptr), - panel(nullptr), - lock(false) - { - if (updateOnChange) - connect(this, &AutoLineEdit::textChanged, this, &AutoLineEdit::onEdited); - else - connect(this, &AutoLineEdit::editingFinished, this, &AutoLineEdit::onEdited); - } + explicit AutoLineEdit(QWidget * parent = nullptr, bool updateOnChange = false); + virtual ~AutoLineEdit(); - void setField(char * field, int len, GenericPanel * panel = nullptr) - { - this->field = field; - this->panel = panel; - setValidator(new QRegExpValidator(QRegExp("[ A-Za-z0-9_.-,]*"), this)); - setMaxLength(len); - updateValue(); - } + virtual void updateValue() override; - void setField(QString & field, int len = 0, GenericPanel * panel = nullptr) - { - strField = &field; - this->panel = panel; - if (len) - setMaxLength(len); - updateValue(); - } - - void updateValue() - { - lock = true; - if (field) - setText(field); - else if (strField) - setText(*strField); - lock = false; - } + void setField(char * field, int len, GenericPanel * panel = nullptr); + void setField(QString & field, int len = 0, GenericPanel * panel = nullptr); signals: void currentDataChanged(); protected slots: - void onEdited() - { - if (panel && panel->lock) - return; - if (lock) - return; + void onEdited(); - if (field) - strcpy(field, text().toLatin1()); - else if (strField) - *strField = text(); - else - return; - - emit currentDataChanged(); - - if (panel) - emit panel->modified(); - } - - protected: - char * field; - QString * strField = nullptr; - GenericPanel * panel = nullptr; - bool lock = false; + private: + char *m_charField; + QString *m_strField; }; diff --git a/companion/src/shared/autoprecisioncombobox.cpp b/companion/src/shared/autoprecisioncombobox.cpp new file mode 100644 index 000000000..6add0ff92 --- /dev/null +++ b/companion/src/shared/autoprecisioncombobox.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autoprecisioncombobox.h" + +constexpr unsigned int APCB_DECIMALS_MIN {0}; +constexpr unsigned int APCB_DECIMALS_MAX {6}; + +AutoPrecisionComboBox::AutoPrecisionComboBox(QWidget * parent): + QComboBox(parent), + AutoWidget() +{ + setFieldInit(); + init(); +} + +AutoPrecisionComboBox::AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, QWidget * parent, GenericPanel * panel): + QComboBox(parent), + AutoWidget() +{ + m_field = &field; + setFieldInit(minDecimals, maxDecimals, padding, suffix, panel); + init(); +} + +AutoPrecisionComboBox::AutoPrecisionComboBox(int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, QWidget * parent, GenericPanel * panel): + QComboBox(parent), + AutoWidget() +{ + m_field = (unsigned int *)&field; + setFieldInit(minDecimals, maxDecimals, padding, suffix, panel); + init(); +} + +AutoPrecisionComboBox::~AutoPrecisionComboBox() +{ +} + +void AutoPrecisionComboBox::setField(int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, GenericPanel * panel) +{ + m_field = (unsigned int *)&field; + setFieldInit(minDecimals, maxDecimals, padding, suffix, panel); + setPanel(panel); +} + +void AutoPrecisionComboBox::setField(unsigned int & field, unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, GenericPanel * panel) +{ + m_field = &field; + setFieldInit(minDecimals, maxDecimals, padding, suffix, panel); + setPanel(panel); +} + +void AutoPrecisionComboBox::setMinDecimals(unsigned int minDecimals) +{ + m_minDecimals = rangecheckDecimals(minDecimals); + if (m_minDecimals > m_maxDecimals) + m_minDecimals = m_maxDecimals; + if (!lock()) + updateList(); +} + +void AutoPrecisionComboBox::setMaxDecimals(unsigned int maxDecimals) +{ + m_maxDecimals = rangecheckDecimals(maxDecimals); + if (m_maxDecimals < m_minDecimals) + m_maxDecimals = m_minDecimals; + if (!lock()) + updateList(); +} + +void AutoPrecisionComboBox::setDecimalsRange(unsigned int min, unsigned int max) +{ + setMinDecimals(min); + setMaxDecimals(max); +} + +void AutoPrecisionComboBox::setPadding(bool padding) +{ + m_padding = padding; + if (!lock()) + updateList(); +} + +void AutoPrecisionComboBox::setSuffix(QString suffix) +{ + m_suffix = suffix.trimmed(); + if (!lock()) + updateList(); +} + +void AutoPrecisionComboBox::setValue(int value) +{ + if (!m_field) + return; + + const unsigned int val = (unsigned int)value; + if (*m_field != val) { + *m_field = rangecheckDecimals(val); + updateValue(); + emit currentDataChanged(value); + dataChanged(); + } +} + +void AutoPrecisionComboBox::setValue(unsigned int value) +{ + if (!m_field) + return; + + if (*m_field != value) { + *m_field = rangecheckDecimals(value); + updateValue(); + emit currentDataChanged((int)value); + dataChanged(); + } +} + +void AutoPrecisionComboBox::updateValue() +{ + if (!m_field) + return; + + if (!isValidDecimals(*m_field)) + return; + + if (*m_field > m_maxDecimals) + setMaxDecimals(*m_field); + + setLock(true); + setCurrentIndex(findData(*m_field)); + setLock(false); +} + +void AutoPrecisionComboBox::setAutoIndexes() +{ + for (int i = 0; i < count(); ++i) + setItemData(i, i); + updateValue(); +} + +void AutoPrecisionComboBox::init() +{ + connect(this, QOverload::of(&QComboBox::currentIndexChanged), this, &AutoPrecisionComboBox::onCurrentIndexChanged); +} + +void AutoPrecisionComboBox::setFieldInit(unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix, GenericPanel * panel) +{ + setLock(true); + setMinDecimals(minDecimals); + setMaxDecimals(maxDecimals); + setPadding(padding); + setSuffix(suffix); + setLock(false); + setPanel(panel); + updateList(); +} + +void AutoPrecisionComboBox::updateList() +{ + setLock(true); + unsigned int i; + int j; + clear(); + + for (i = APCB_DECIMALS_MIN, j = (int)m_maxDecimals; j >= 0; i++, j--) { + if (i >= m_minDecimals) { + QString str = QString("0.%1").arg(QString(i, '0')); + if (m_padding) + str.append(QString(j, '_')); + if (m_suffix != "") + str.append(QString(" %1").arg(m_suffix)); + addItem(str, i); + } + } + + setSizeAdjustPolicy(QComboBox::AdjustToContents); + setLock(false); +} + +void AutoPrecisionComboBox::onCurrentIndexChanged(int index) +{ + if (!m_field || index < 0 || lock()) + return; + + if (*m_field != itemData(index).toUInt()) { + *m_field = itemData(index).toUInt(); + emit currentDataChanged(index); + dataChanged(); + } +} + +unsigned int AutoPrecisionComboBox::rangecheckDecimals(unsigned int decimals) +{ + unsigned int ret; + if (decimals < APCB_DECIMALS_MIN) + ret = APCB_DECIMALS_MIN; + else if (decimals > APCB_DECIMALS_MAX) + ret = APCB_DECIMALS_MAX; + else + ret = decimals; + return ret; +} + +bool AutoPrecisionComboBox::isValidDecimals(unsigned int value) +{ + if (value >= APCB_DECIMALS_MIN && value <= APCB_DECIMALS_MAX) + return true; + else + return false; +} diff --git a/companion/src/shared/autoprecisioncombobox.h b/companion/src/shared/autoprecisioncombobox.h index 72dd89406..7cebeaa36 100644 --- a/companion/src/shared/autoprecisioncombobox.h +++ b/companion/src/shared/autoprecisioncombobox.h @@ -20,235 +20,50 @@ #pragma once -#include "genericpanel.h" +#include "autowidget.h" #include #include -class AutoPrecisionComboBox: public QComboBox +class AutoPrecisionComboBox : public QComboBox, AutoWidget { - Q_OBJECT - //! \property minDecimals Determines the first list item - Q_PROPERTY(unsigned int minDecimals READ minDecimals WRITE setMinDecimals) - //! \property maxDecimals Determines the last list item - Q_PROPERTY(unsigned int maxDecimals READ maxDecimals WRITE setMaxDecimals) - //! \property padding If true, add trailing underscore placeholders to each list item - Q_PROPERTY(bool padding READ padding WRITE setPadding) - //! \property suffix Optional text suffix to each list value - Q_PROPERTY(QString suffix READ suffix WRITE setSuffix) + Q_OBJECT public: - explicit AutoPrecisionComboBox(QWidget * parent = nullptr): - QComboBox(parent) - { - init(); - } + explicit AutoPrecisionComboBox(QWidget * parent = nullptr); + explicit AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr); + explicit AutoPrecisionComboBox(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr); + virtual ~AutoPrecisionComboBox(); - explicit AutoPrecisionComboBox(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr): - QComboBox(parent) - { - setField(field, minDecimals, maxDecimals, padding, suffix, panel); - init(); - } + virtual void updateValue() override; - explicit AutoPrecisionComboBox(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", QWidget * parent = nullptr, GenericPanel * panel = nullptr): - QComboBox(parent) - { - setField(field, minDecimals, maxDecimals, padding, suffix, panel); - init(); - } - - inline int minDecimals() const { return m_minDecimals; } - inline int maxDecimals() const { return m_maxDecimals; } - inline bool padding() const { return m_padding; } - inline QString suffix() const { return m_suffix; } - - public slots: - void setField(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr) - { - m_field = reinterpret_cast(&field); - initField(minDecimals, maxDecimals, padding, suffix); - setPanel(panel); - } - - void setField(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr) - { - m_field = &field; - initField(minDecimals, maxDecimals, padding, suffix); - setPanel(panel); - } - - void setMinDecimals(unsigned int minDecimals) - { - m_minDecimals = rangecheckDecimals(minDecimals); - if (m_minDecimals > m_maxDecimals) - m_minDecimals = m_maxDecimals; - if (!m_lock) - updateList(); - } - - void setMaxDecimals(unsigned int maxDecimals) - { - m_maxDecimals = rangecheckDecimals(maxDecimals); - if (m_maxDecimals < m_minDecimals) - m_maxDecimals = m_minDecimals; - if (!m_lock) - updateList(); - } - - void setPadding(bool padding) - { - m_padding = padding; - if (!m_lock) - updateList(); - } - - void setSuffix(QString suffix) - { - m_suffix = suffix.trimmed(); - if (!m_lock) - updateList(); - } - - void setPanel(GenericPanel * panel) - { - m_panel = panel; - } - - void setValue(int value) - { - if (!m_field) - return; - const unsigned int val = (unsigned int)value; - if (*m_field != val) { - *m_field = rangecheckDecimals(val); - updateValue(); - emit currentDataChanged(value); - } - } - - void setValue(unsigned int value) - { - if (!m_field) - return; - if (*m_field != value) { - *m_field = rangecheckDecimals(value); - updateValue(); - emit currentDataChanged((int)value); - } - } - - void updateValue() - { - if (!m_field) - return; - if (!isValidDecimals(*m_field)) - return; - if (*m_field > m_maxDecimals) { - setMaxDecimals(*m_field); - } - const bool savedlock = setLocked(true); - setCurrentIndex(findData(*m_field)); - setLocked(savedlock); - } - - void setAutoIndexes() - { - for (int i = 0; i < count(); ++i) - setItemData(i, i); - updateValue(); - } + void setField(int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr); + void setField(unsigned int & field, unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr); + void setMinDecimals(unsigned int minDecimals); + void setMaxDecimals(unsigned int maxDecimals); + void setDecimalsRange(unsigned int min, unsigned int max); + void setPadding(bool padding); + void setSuffix(QString suffix); + void setValue(int value); + void setValue(unsigned int value); + void setAutoIndexes(); signals: void currentDataChanged(int index); protected slots: - void init() - { - connect(this, QOverload::of(&AutoPrecisionComboBox::currentIndexChanged), this, &AutoPrecisionComboBox::onCurrentIndexChanged); - } + void onCurrentIndexChanged(int index); - void initField(unsigned int minDecimals, unsigned int maxDecimals, bool padding, QString suffix) - { - const bool savedlock = setLocked(true); - setMinDecimals(minDecimals); - setMaxDecimals(maxDecimals); - setPadding(padding); - setSuffix(suffix); - setLocked(savedlock); - updateList(); - } - - void updateList() - { - const bool savedlock = setLocked(true); - unsigned int i; - int j; - clear(); - - for (i = APCB_DECIMALS_MIN, j = (int)m_maxDecimals; j >= 0; i++, j--) { - if (i >= m_minDecimals) { - QString str = QString("0.%1").arg(QString(i, '0')); - if (m_padding) - str.append(QString(j, '_')); - if (m_suffix != "") - str.append(QString(" %1").arg(m_suffix)); - addItem(str, i); - } - } - - setSizeAdjustPolicy(QComboBox::AdjustToContents); - setLocked(savedlock); - } - - void onCurrentIndexChanged(int index) - { - if (index < 0 || (m_panel && m_panel->lock) || m_lock) - return; - if (m_field) { - *m_field = itemData(index).toUInt(); - emit currentDataChanged(index); - if (m_panel) - emit m_panel->modified(); - } - } - - unsigned int rangecheckDecimals(unsigned int decimals) - { - unsigned int ret; - if (decimals < APCB_DECIMALS_MIN) - ret = APCB_DECIMALS_MIN; - else if (decimals > APCB_DECIMALS_MAX) - ret = APCB_DECIMALS_MAX; - else - ret = decimals; - return ret; - } - - bool isValidDecimals(unsigned int value) - { - if (value >= APCB_DECIMALS_MIN && value <= APCB_DECIMALS_MAX) - return true; - else - return false; - } - - bool setLocked(bool lock) - { - const bool ret = m_lock; - m_lock = lock; - return ret; - } - - protected: - constexpr static unsigned int APCB_DECIMALS_MIN = {0}; - constexpr static unsigned int APCB_DECIMALS_MAX = {6}; - - unsigned int * m_field = nullptr; - GenericPanel * m_panel = nullptr; + private: + unsigned int *m_field = nullptr; unsigned int m_minDecimals = 0; - unsigned int m_maxDecimals = 0; + unsigned int m_maxDecimals = 1; bool m_padding = false; QString m_suffix = ""; - bool m_lock = false; + + void init(); + void setFieldInit(unsigned int minDecimals = 0, unsigned int maxDecimals = 1, bool padding = false, QString suffix = "", GenericPanel * panel = nullptr); + bool isValidDecimals(unsigned int value); + unsigned int rangecheckDecimals(unsigned int decimals); + void updateList(); }; diff --git a/companion/src/shared/autoslider.cpp b/companion/src/shared/autoslider.cpp new file mode 100644 index 000000000..5b02b3603 --- /dev/null +++ b/companion/src/shared/autoslider.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autoslider.h" + +AutoSlider::AutoSlider(QWidget * parent): + QSlider(parent), + AutoWidget() +{ + init(); +} + +AutoSlider::AutoSlider(Qt::Orientation orientation, QWidget * parent): + QSlider(orientation, parent), + AutoWidget() +{ + init(); +} + +AutoSlider::~AutoSlider() +{ +} + +void AutoSlider::setField(int & field, int min, int max, GenericPanel * panel) +{ + m_field = &field; + setFieldInit(min, max, panel); +} + +void AutoSlider::setField(unsigned int & field, int min, int max, GenericPanel * panel) +{ + m_field = (int *)&field; + setFieldInit(min, max, panel); +} + +void AutoSlider::setTick(int interval, QSlider::TickPosition position) +{ + setTickInterval(interval); + setTickPosition(position); +} + +void AutoSlider::updateValue() +{ + if (m_field) { + setLock(true); + setValue(*m_field); + setLock(false); + } +} + +void AutoSlider::init() +{ + connect(this, &QSlider::valueChanged, this, &AutoSlider::onValueChanged); +} + +void AutoSlider::setFieldInit(int min, int max, GenericPanel * panel) +{ + setPanel(panel); + setRange(min, max); + updateValue(); +} + +void AutoSlider::onValueChanged(int value) +{ + if (m_field && !lock()) { + if (*m_field != value) { + *m_field = value; + emit currentDataChanged(value); + dataChanged(); + } + } +} diff --git a/companion/src/shared/autoslider.h b/companion/src/shared/autoslider.h index e81ea66b4..f83177c87 100644 --- a/companion/src/shared/autoslider.h +++ b/companion/src/shared/autoslider.h @@ -20,85 +20,34 @@ #pragma once -#include "genericpanel.h" +#include "autowidget.h" #include -class AutoSlider : public QSlider +class AutoSlider : public QSlider, AutoWidget { Q_OBJECT public: - explicit AutoSlider(QWidget * parent = nullptr): - QSlider(parent) - { - init(); - } + explicit AutoSlider(QWidget * parent = nullptr); + explicit AutoSlider(Qt::Orientation orientation, QWidget * parent = nullptr); + virtual ~AutoSlider(); - explicit AutoSlider(Qt::Orientation orientation, QWidget * parent = nullptr): - QSlider(orientation, parent) - { - init(); - } + virtual void updateValue() override; - void setField(int & field, int min, int max, GenericPanel * panel = nullptr) - { - this->field = &field; - setFieldInit(min, max, panel); - } - - void setField(unsigned int & field, int min, int max, GenericPanel * panel = nullptr) - { - this->field = reinterpret_cast(&field); - setFieldInit(min, max, panel); - } - - void setTick(int interval, QSlider::TickPosition position) - { - setTickInterval(interval); - setTickPosition(position); - } - - void updateValue() - { - if (field) { - lock = true; - setValue(*field); - lock = false; - } - } + void setField(int & field, int min, int max, GenericPanel * panel = nullptr); + void setField(unsigned int & field, int min, int max, GenericPanel * panel = nullptr); + void setTick(int interval, QSlider::TickPosition position); signals: void currentDataChanged(int value); protected slots: - void init() - { - connect(this, &AutoSlider::valueChanged, this, &AutoSlider::onValueChanged); - } + void onValueChanged(int value); - void onValueChanged(int value) - { - if (panel && panel->lock) - return; - if (field && !lock) { - *field = value; - emit currentDataChanged(value); - if (panel) { - emit panel->modified(); - } - } - } + private: + int *m_field = nullptr; - protected: - void setFieldInit(int min, int max, GenericPanel * panel) - { - this->panel = panel; - setRange(min, max); - updateValue(); - } - - int *field = nullptr; - GenericPanel *panel = nullptr; - bool lock = false; + void init(); + void setFieldInit(int min, int max, GenericPanel * panel); }; diff --git a/companion/src/shared/autospinbox.cpp b/companion/src/shared/autospinbox.cpp new file mode 100644 index 000000000..ecee90edd --- /dev/null +++ b/companion/src/shared/autospinbox.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autospinbox.h" + +AutoSpinBox::AutoSpinBox(QWidget * parent): + QSpinBox(parent), + AutoWidget(), + m_field(nullptr) +{ + connect(this, QOverload::of(&QSpinBox::valueChanged), this, &AutoSpinBox::onValueChanged); +} + +AutoSpinBox::~AutoSpinBox() +{ +} + +void AutoSpinBox::setField(int & field, GenericPanel * panel) +{ + m_field = &field; + setFieldInit(panel); +} + +void AutoSpinBox::setField(unsigned int & field, GenericPanel * panel) +{ + m_field = (int *)&field; + setFieldInit(panel); +} + +void AutoSpinBox::setFieldInit(GenericPanel * panel) +{ + setPanel(panel); + updateValue(); +} + +void AutoSpinBox::updateValue() +{ + if (m_field) { + setLock(true); + setValue(*m_field); + setLock(false); + } +} + +void AutoSpinBox::onValueChanged(int value) +{ + if (m_field && !lock()) { + if (*m_field != value) { + *m_field = value; + emit currentDataChanged(value); + dataChanged(); + } + } +} diff --git a/companion/src/shared/autospinbox.h b/companion/src/shared/autospinbox.h index 65b49c0f3..a92d6db56 100644 --- a/companion/src/shared/autospinbox.h +++ b/companion/src/shared/autospinbox.h @@ -20,62 +20,31 @@ #pragma once +#include "autowidget.h" + #include -#include "genericpanel.h" - -class AutoSpinBox : public QSpinBox +class AutoSpinBox : public QSpinBox, AutoWidget { Q_OBJECT public: - explicit AutoSpinBox(QWidget * parent = nullptr): - QSpinBox(parent), - field(nullptr), - panel(nullptr), - lock(false) - { - connect(this, QOverload::of(&AutoSpinBox::valueChanged), this, &AutoSpinBox::onValueChanged); - } + explicit AutoSpinBox(QWidget * parent = nullptr); + virtual ~AutoSpinBox(); - void setField(int & field, GenericPanel * panel = nullptr) - { - this->field = &field; - this->panel = panel; - updateValue(); - } + virtual void updateValue() override; - void setField(unsigned int & field, GenericPanel * panel = nullptr) - { - this->field = (int *)&field; - this->panel = panel; - updateValue(); - } + void setField(int & field, GenericPanel * panel = nullptr); + void setField(unsigned int & field, GenericPanel * panel = nullptr); - void updateValue() - { - lock = true; - if (field) { - setValue(*field); - } - lock = false; - } + signals: + void currentDataChanged(int value); protected slots: - void onValueChanged(int value) - { - if (panel && panel->lock) - return; - if (field && !lock) { - *field = value; - if (panel) { - emit panel->modified(); - } - } - } + void onValueChanged(int value); - protected: - int * field; - GenericPanel * panel; - bool lock; + private: + int *m_field; + + void setFieldInit(GenericPanel * panel); }; diff --git a/companion/src/shared/autotimeedit.cpp b/companion/src/shared/autotimeedit.cpp new file mode 100644 index 000000000..7b0c4422a --- /dev/null +++ b/companion/src/shared/autotimeedit.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autotimeedit.h" + +AutoTimeEdit::AutoTimeEdit(QWidget * parent): + QTimeEdit(parent), + AutoWidget(), + m_field(nullptr) +{ + connect(this, &QTimeEdit::timeChanged, this, &AutoTimeEdit::onTimeChanged); +} + +AutoTimeEdit::~AutoTimeEdit() +{ +} + +void AutoTimeEdit::setField(unsigned int & field, GenericPanel * panel) +{ + m_field = &field; + setPanel(panel); + updateValue(); +} + +void AutoTimeEdit::setTimeRange(const QTime min, const QTime max) +{ + QTimeEdit::setMinimumTime(min); + QTimeEdit::setMaximumTime(max); +} + +void AutoTimeEdit::updateValue() +{ + if (m_field) { + setLock(true); + int hour = *m_field / 3600; + int min = (*m_field - (hour * 3600)) / 60; + int sec = (*m_field - (hour * 3600)) % 60; + setTime(QTime(hour, min, sec)); + setLock(false); + } +} + +void AutoTimeEdit::onTimeChanged(QTime time) +{ + if (!m_field || lock()) + return; + + unsigned int val = time.hour() * 3600 + time.minute() * 60 + time.second(); + if (*m_field != val) { + *m_field = val; + emit currentDataChanged(val); + dataChanged(); + } +} diff --git a/companion/src/shared/autotimeedit.h b/companion/src/shared/autotimeedit.h index 2ba75d70e..e27607ce5 100644 --- a/companion/src/shared/autotimeedit.h +++ b/companion/src/shared/autotimeedit.h @@ -20,80 +20,30 @@ #pragma once -#include -#include "genericpanel.h" +#include "autowidget.h" -class AutoTimeEdit: public QTimeEdit +#include + +class AutoTimeEdit : public QTimeEdit, AutoWidget { Q_OBJECT public: - explicit AutoTimeEdit(QWidget * parent = nullptr): - QTimeEdit(parent), - field(nullptr), - panel(nullptr), - lock(false) - { - connect(this, SIGNAL(timeChanged(QTime)), this, SLOT(onTimeChanged(QTime))); - } + explicit AutoTimeEdit(QWidget * parent = nullptr); + virtual ~AutoTimeEdit(); - void setField(unsigned int & field, GenericPanel * panel = nullptr) - { - this->field = &field; - this->panel = panel; - updateValue(); - } + virtual void updateValue() override; - void setMinimumTime(const QTime time) - { - QTimeEdit::setMinimumTime(time); - } - - void setMaximumTime(const QTime time) - { - QTimeEdit::setMaximumTime(time); - } - - void setEnabled(bool enabled) - { - QTimeEdit::setEnabled(enabled); - } - - void updateValue() - { - if (field) { - lock = true; - int hour = *field / 3600; - int min = (*field - (hour * 3600)) / 60; - int sec = (*field - (hour * 3600)) % 60; - setTime(QTime(hour, min, sec)); - lock = false; - } - } + void setField(unsigned int & field, GenericPanel * panel = nullptr); + void setTimeRange(const QTime min, const QTime max); signals: - void currentDataChanged(unsigned int value); + void currentDataChanged(unsigned int val); protected slots: - void onTimeChanged(QTime time) - { - if (panel && panel->lock) - return; - if (!field || lock) - return; + void onTimeChanged(QTime time); - unsigned int val = time.hour() * 3600 + time.minute() * 60 + time.second(); - if (*field != val) { - *field = val; - emit currentDataChanged(val); - if (panel) - emit panel->modified(); - } - } - - protected: - unsigned int *field = nullptr; - GenericPanel *panel = nullptr; - bool lock = false; + private: + unsigned int *m_field; }; diff --git a/companion/src/shared/autowidget.h b/companion/src/shared/autowidget.h index 68d47547d..9680726b7 100644 --- a/companion/src/shared/autowidget.h +++ b/companion/src/shared/autowidget.h @@ -22,7 +22,7 @@ class GenericPanel; -// Note: cannot be a Qt object as it will create a compiler ambiguity in the inheriting class +// Note: cannot be a Qt object otherwise it will create a compiler ambiguity in the inheriting class class AutoWidget { public: diff --git a/companion/src/shared/genericpanel.h b/companion/src/shared/genericpanel.h index c0ccb949b..f013584bd 100644 --- a/companion/src/shared/genericpanel.h +++ b/companion/src/shared/genericpanel.h @@ -32,17 +32,7 @@ class GenericPanel : public QWidget { Q_OBJECT - friend class AutoComboBox; - friend class AutoDoubleSpinBox; - friend class AutoHexSpinBox; - friend class AutoLineEdit; friend class GVarGroup; - friend class AutoPrecisionComboBox; - friend class AutoBitsetCheckBox; - friend class AutoTimeEdit; - friend class AutoSpinBox; - friend class AutoSlider; - // this should be the only auto friend required excl GVArGroup friend class AutoWidget; public: diff --git a/companion/src/shared/hexspinbox.cpp b/companion/src/shared/hexspinbox.cpp deleted file mode 100644 index 63889ef11..000000000 --- a/companion/src/shared/hexspinbox.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "hexspinbox.h" - -HexSpinBox::HexSpinBox(QWidget *parent): - QSpinBox(parent) -{ - validator = new QRegExpValidator(QRegExp("[0-9A-Fa-f]{1,8}"), this); -} - -QValidator::State HexSpinBox::validate(QString &text, int &pos) const -{ - return validator->validate(text, pos); -} - -int HexSpinBox::valueFromText(const QString &text) const -{ - return text.toInt(0, 16); -} - -QString HexSpinBox::textFromValue(int value) const -{ - QString text; - text.sprintf("%04X", value); - return text; -} - - - diff --git a/companion/src/shared/hexspinbox.h b/companion/src/shared/hexspinbox.h deleted file mode 100644 index 204cc8a55..000000000 --- a/companion/src/shared/hexspinbox.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#pragma once - -#include - -class QRegExpValidator; - -class HexSpinBox : public QSpinBox -{ - Q_OBJECT - - public: - HexSpinBox(QWidget *parent = 0); - - protected: - QValidator::State validate(QString &text, int &pos) const; - int valueFromText(const QString &text) const; - QString textFromValue(int value) const; - - private: - QRegExpValidator *validator; -}; diff --git a/companion/src/shared/verticalscrollarea.h b/companion/src/shared/verticalscrollarea.h index d409a18ca..4f6d2af18 100644 --- a/companion/src/shared/verticalscrollarea.h +++ b/companion/src/shared/verticalscrollarea.h @@ -26,6 +26,8 @@ class GenericPanel; class VerticalScrollArea : public QScrollArea { + Q_OBJECT + public: VerticalScrollArea(QWidget * parent, GenericPanel * panel); From c8bd18441a69a9c672c882b34854df7ee19c1d7f Mon Sep 17 00:00:00 2001 From: Lucas1188 <64507210+Lucas1188@users.noreply.github.com> Date: Mon, 10 May 2021 21:46:15 -0600 Subject: [PATCH 46/70] Update api_general.cpp --- radio/src/lua/api_general.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 3c6f20d42..5d0d9f8b2 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1532,6 +1532,19 @@ static int luaGetUsage(lua_State * L) return 1; } +/*luadoc +@function getAvailableMemory() + +Get available memory remaining in the Heap for Lua. + +@retval usage (number) a value returned in b +*/ +static int luaGetAvailableMemory(lua_State * L) +{ + lua_pushunsigned(L, availableMemory()); + return 1; +} + /*luadoc @function resetGlobalTimer([type]) @@ -1759,6 +1772,7 @@ const luaL_Reg opentxLib[] = { { "chdir", luaChdir }, { "loadScript", luaLoadScript }, { "getUsage", luaGetUsage }, + { "getAvailableMemory", luaGetAvailableMemory }, { "resetGlobalTimer", luaResetGlobalTimer }, #if LCD_DEPTH > 1 && !defined(COLORLCD) { "GREY", luaGrey }, From cfc7c0ea86242b5c10dc18cf4560246b706111e3 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 11 May 2021 18:15:25 +0200 Subject: [PATCH 47/70] Improved sync --- radio/src/mixer_scheduler.cpp | 6 +++++- radio/src/mixer_scheduler.h | 4 ++++ .../src/targets/common/arm/stm32/mixer_scheduler_driver.cpp | 4 +++- radio/src/tasks.cpp | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp index dcf95383b..fef9034c0 100644 --- a/radio/src/mixer_scheduler.cpp +++ b/radio/src/mixer_scheduler.cpp @@ -68,9 +68,13 @@ void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs) mixerSchedules[moduleIdx].period = periodUs; } -bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs) +void mixerSchedulerClearTrigger() { RTOS_CLEAR_FLAG(mixerFlag); +} + +bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs) +{ return RTOS_WAIT_FLAG(mixerFlag, timeoutMs); } diff --git a/radio/src/mixer_scheduler.h b/radio/src/mixer_scheduler.h index 601f3fcd7..75a6ad1aa 100644 --- a/radio/src/mixer_scheduler.h +++ b/radio/src/mixer_scheduler.h @@ -43,6 +43,9 @@ void mixerSchedulerResetTimer(); // Set the scheduling period for a given module void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs); +// Clear the flag before waiting +void mixerSchedulerClearTrigger(); + // Wait for the scheduler timer to trigger // returns true if timeout, false otherwise bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs); @@ -66,6 +69,7 @@ void mixerSchedulerISRTrigger(); #define mixerSchedulerStop() #define mixerSchedulerResetTimer() #define mixerSchedulerSetPeriod(m,p) +#define mixerSchedulerClearTrigger() static inline bool mixerSchedulerWaitForTrigger(uint8_t timeout) { diff --git a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp index 7f7b23a1c..f89548fd2 100644 --- a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp +++ b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp @@ -39,8 +39,9 @@ void mixerSchedulerStart() NVIC_SetPriority(MIXER_SCHEDULER_TIMER_IRQn, 8); MIXER_SCHEDULER_TIMER->SR &= TIM_SR_UIF; // clear interrupt flag - MIXER_SCHEDULER_TIMER->DIER |= TIM_DIER_UIE; // enable interrupt MIXER_SCHEDULER_TIMER->CR1 |= TIM_CR1_CEN; + + mixerSchedulerEnableTrigger(); } void mixerSchedulerStop() @@ -58,6 +59,7 @@ void mixerSchedulerResetTimer() void mixerSchedulerEnableTrigger() { + mixerSchedulerClearTrigger(); MIXER_SCHEDULER_TIMER->DIER |= TIM_DIER_UIE; // enable interrupt } diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 4878535fd..aa3ec3974 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -136,6 +136,7 @@ TASK_FUNCTION(mixerTask) s_pulses_paused = true; mixerSchedulerInit(); + #if !defined(PCBSKY9X) mixerSchedulerStart(); #endif From 8b61ce5ce75836fd8a081fbce46b7d65bcdc4228 Mon Sep 17 00:00:00 2001 From: elecpower Date: Wed, 12 May 2021 06:12:27 +1000 Subject: [PATCH 48/70] New autolabel widget --- companion/src/shared/CMakeLists.txt | 1 + companion/src/shared/autolabel.cpp | 67 +++++++++++++++++++++++++++++ companion/src/shared/autolabel.h | 44 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 companion/src/shared/autolabel.cpp create mode 100644 companion/src/shared/autolabel.h diff --git a/companion/src/shared/CMakeLists.txt b/companion/src/shared/CMakeLists.txt index bfd4d60fa..7bedeebf6 100644 --- a/companion/src/shared/CMakeLists.txt +++ b/companion/src/shared/CMakeLists.txt @@ -8,6 +8,7 @@ set(shared_NAMES autocombobox autodoublespinbox autohexspinbox + autolabel autolineedit autoprecisioncombobox autoslider diff --git a/companion/src/shared/autolabel.cpp b/companion/src/shared/autolabel.cpp new file mode 100644 index 000000000..61099a9a7 --- /dev/null +++ b/companion/src/shared/autolabel.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "autolabel.h" + +#include + +AutoLabel::AutoLabel(QWidget * parent): + QLabel(parent), + AutoWidget(), + m_charField(NULL), + m_strField(nullptr) +{ +} + +AutoLabel::~AutoLabel() +{ +} + +void AutoLabel::setField(char * field, GenericPanel * panel) +{ + m_charField = field; + setPanel(panel); + updateValue(); +} + +void AutoLabel::setField(QString & field, GenericPanel * panel) +{ + m_strField = &field; + setPanel(panel); + updateValue(); +} + +void AutoLabel::setWidth(int numChars) +{ + QFontMetrics *f = new QFontMetrics(this->font()); + QSize sz = f->size(Qt::TextSingleLine, QString(numChars, QChar('X'))); + setMinimumWidth(sz.width()); + delete f; +} + +void AutoLabel::updateValue() +{ + setLock(true); + if (m_strField) + setText(*m_strField); + else if (m_charField) + setText(m_charField); + setLock(false); +} diff --git a/companion/src/shared/autolabel.h b/companion/src/shared/autolabel.h new file mode 100644 index 000000000..1b31db024 --- /dev/null +++ b/companion/src/shared/autolabel.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "autowidget.h" + +#include + +class AutoLabel: public QLabel, AutoWidget +{ + Q_OBJECT + + public: + explicit AutoLabel(QWidget * parent = nullptr); + virtual ~AutoLabel(); + + virtual void updateValue() override; + + void setField(char * field, GenericPanel * panel = nullptr); + void setField(QString & field, GenericPanel * panel = nullptr); + void setWidth(int numChars); + + private: + char *m_charField; + QString *m_strField; +}; From afef06374ab71099175b37a2610d083f9b29ad93 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 10 May 2021 22:33:33 +0200 Subject: [PATCH 49/70] Fix mixer scheduler 33Hz only issue introduced by opentx/opentx#8474 --- radio/src/mixer_scheduler.cpp | 6 +++++- radio/src/mixer_scheduler.h | 4 ++++ radio/src/tasks.cpp | 17 ++++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/radio/src/mixer_scheduler.cpp b/radio/src/mixer_scheduler.cpp index dcf95383b..fef9034c0 100644 --- a/radio/src/mixer_scheduler.cpp +++ b/radio/src/mixer_scheduler.cpp @@ -68,9 +68,13 @@ void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs) mixerSchedules[moduleIdx].period = periodUs; } -bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs) +void mixerSchedulerClearTrigger() { RTOS_CLEAR_FLAG(mixerFlag); +} + +bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs) +{ return RTOS_WAIT_FLAG(mixerFlag, timeoutMs); } diff --git a/radio/src/mixer_scheduler.h b/radio/src/mixer_scheduler.h index 601f3fcd7..75a6ad1aa 100644 --- a/radio/src/mixer_scheduler.h +++ b/radio/src/mixer_scheduler.h @@ -43,6 +43,9 @@ void mixerSchedulerResetTimer(); // Set the scheduling period for a given module void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs); +// Clear the flag before waiting +void mixerSchedulerClearTrigger(); + // Wait for the scheduler timer to trigger // returns true if timeout, false otherwise bool mixerSchedulerWaitForTrigger(uint8_t timeoutMs); @@ -66,6 +69,7 @@ void mixerSchedulerISRTrigger(); #define mixerSchedulerStop() #define mixerSchedulerResetTimer() #define mixerSchedulerSetPeriod(m,p) +#define mixerSchedulerClearTrigger() static inline bool mixerSchedulerWaitForTrigger(uint8_t timeout) { diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 4878535fd..a06c6fb3f 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -140,11 +140,19 @@ TASK_FUNCTION(mixerTask) mixerSchedulerStart(); #endif + // clear the flag before first loop + mixerSchedulerClearTrigger(); + while (true) { - for (int timeout = 0; timeout < MIXER_MAX_PERIOD; timeout += MIXER_FREQUENT_ACTIONS_PERIOD) { - bool interruptedByTimeout = mixerSchedulerWaitForTrigger(MIXER_FREQUENT_ACTIONS_PERIOD); + int timeout = 0; + for (; timeout < MIXER_MAX_PERIOD; timeout += MIXER_FREQUENT_ACTIONS_PERIOD) { + + // run periodicals before waiting for the trigger + // to keep the delay short execMixerFrequentActions(); - if (!interruptedByTimeout) { + + // mixer flag triggered? + if (!mixerSchedulerWaitForTrigger(MIXER_FREQUENT_ACTIONS_PERIOD)) { break; } } @@ -155,6 +163,9 @@ TASK_FUNCTION(mixerTask) #endif #if !defined(PCBSKY9X) + // clear the flag ASAP to avoid missing a tick + mixerSchedulerClearTrigger(); + // re-enable trigger mixerSchedulerEnableTrigger(); #endif From 7f80cd7f6cff3b68a117c77597b501765445f6cf Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 11 May 2021 07:30:34 +0200 Subject: [PATCH 50/70] Added gh actions --- .github/workflows/actions.yml | 59 ++++++++++++++++ tools/build-gh.sh | 129 ++++++++++++++++++++++++++++++++++ tools/commit-tests.sh | 109 +++++++++++++--------------- 3 files changed, 238 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/actions.yml create mode 100755 tools/build-gh.sh diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml new file mode 100644 index 000000000..55d45ee10 --- /dev/null +++ b/.github/workflows/actions.yml @@ -0,0 +1,59 @@ +name: Commit Tests +on: + push: + branches: [ 2.3 ] + pull_request: + branches: [ 2.3 ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + target: + - X9LITE + - X7 + - T12 + - TX12 + - T8 + - TLITE + - XLITE + - X9DP + - X9DP2019 + - X10 + - T16 + - TX16S + - X12S + container: + image: ghcr.io/edgetx/edgetx-commit-tests:2.3 + volumes: + - ${{ github.workspace }}:/src + steps: + - + name: Check out the repo + uses: actions/checkout@v2 + with: + submodules: recursive + # - + # name: Fetch tags + # run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* + - + name: Test ${{ matrix.target }} + env: + FLAVOR: ${{ matrix.target }} + run: | + echo "Running commit tests" + ./tools/commit-tests.sh + - + name: Build ${{ matrix.target }} + env: + FLAVOR: ${{ matrix.target }} + run: | + echo "Running firmware build" + ./tools/build-gh.sh + - + name: Package firmware ${{ matrix.target }} + uses: 'actions/upload-artifact@v2' + with: + name: edgetx-firmware + path: ${{ github.workspace }}/*.bin diff --git a/tools/build-gh.sh b/tools/build-gh.sh new file mode 100755 index 000000000..7826a4243 --- /dev/null +++ b/tools/build-gh.sh @@ -0,0 +1,129 @@ +#!/bin/bash + +# Stops on first error, echo on +set -e +set -x + +# Allow variable core usage, default uses all cpu cores, to set 8 cores for example : commit-tests.sh -j8 +num_cpus=$(nproc) +: "${CORES:=$num_cpus}" +# Default build treats warnings as errors, set -Wno-error to override, e.g.: commit-tests.sh -Wno-error +#: "${WERROR:=1}" +# A board name to build for, or ALL +: "${FLAVOR:=ALL}" + +for i in "$@" +do +case $i in + --jobs=*) + CORES="${i#*=}" + shift + ;; + -j*) + CORES="${i#*j}" + shift + ;; + -Wno-error) + WERROR=0 + shift + ;; + -b*) + FLAVOR="${i#*b}" + shift + ;; +esac +done + +if [ "$(uname)" = "Darwin" ]; then + SCRIPT=$(python -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' "$0") +else + SCRIPT=$(readlink -f "$0") +fi + +if [[ -n ${GCC_ARM} ]] ; then + export PATH=${GCC_ARM}:$PATH +fi + +: ${SRCDIR:=$(dirname "$SCRIPT")/..} + +: ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=Debug -DTRACE_SIMPGMSPACE=NO -DVERBOSE_CMAKELISTS=YES -DCMAKE_RULE_MESSAGES=OFF -Wno-dev "} +if (( $WERROR )); then COMMON_OPTIONS+=" -DWARNINGS_AS_ERRORS=YES -DMULTIMODULE=YES "; fi + +: ${EXTRA_OPTIONS:="$EXTRA_OPTIONS"} + +COMMON_OPTIONS+=${EXTRA_OPTIONS} + +: ${FIRMARE_TARGET:="firmware-size"} + +mkdir build || true +cd build + +# wipe clean in case of serial builds in the same dir +rm -rf ./* || true + +BUILD_OPTIONS=${COMMON_OPTIONS} + +GIT_SHA_SHORT=`git rev-parse --short HEAD` +#GIT_TAG=`git describe --tags` + +target_name=`echo "$FLAVOR" | tr '[:upper:]' '[:lower:]'` +fw_name="${target_name}-2.3-${GIT_SHA_SHORT}.bin" + +echo "Building ${fw_name}" + +case $FLAVOR in + + X9LITE) + BUILD_OPTIONS+="-DPCB=X9LITE" + ;; + X9LITES) + BUILD_OPTIONS+="-DPCB=X9LITES" + ;; + X7) + BUILD_OPTIONS+="-DPCB=X7" + ;; + T12) + BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=T12" + ;; + TX12) + BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=TX12" + ;; + T8) + BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=T8" + ;; + TLITE) + BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=TLITE" + ;; + XLITE) + BUILD_OPTIONS+="-DPCB=XLITE" + ;; + XLITES) + BUILD_OPTIONS+="-DPCB=XLITES" + ;; + X9DP) + BUILD_OPTIONS+="-DPCB=X9D+" + ;; + X9DP2019) + BUILD_OPTIONS+="-DPCB=X9D+ -DPCBREV=2019" + ;; + X9E) + BUILD_OPTIONS+="-DPCB=X9E" + ;; + X10) + BUILD_OPTIONS+="-DPCB=X10" + ;; + X12S) + BUILD_OPTIONS+="-DPCB=X12S" + ;; + T16) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=T16" + ;; + TX16S) + BUILD_OPTIONS+="-DPCB=X10 -DPCBREV=TX16S" + ;; +esac + +cmake ${BUILD_OPTIONS} "${SRCDIR}" +make -j"${CORES}" ${FIRMARE_TARGET} + +mv firmware.bin "../${fw_name}" diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 8ef5e85fb..24634d79a 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -58,27 +58,27 @@ COMMON_OPTIONS+=${EXTRA_OPTIONS} mkdir build || true cd build -if [[ " SKY9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " SKY9X ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on Sky9x - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=SKY9X -DHELI=YES DLUA=YES -DTELEMETRY=FRSKY -DPPM_LIMITS_SYMETRICAL=YES -DVARIO=YES -DAUTOSWITCH=YES -DAUTOSOURCE=YES -DAUDIO=YES -DGPS=YES -DPPM_CENTER_ADJUSTABLE=YES -DFLIGHT_MODES=YES -DOVERRIDE_CHANNEL_FUNCTION=YES -DFRSKY_STICKS=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " AR9X ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " AR9X ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on AR9X - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=AR9X -DHELI=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " 9XRPRO ARM9X ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " 9XRPRO ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on Sky9x - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=9XRPRO -DHELI=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -87,16 +87,16 @@ fi if [[ " X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITE - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X9LITE -DHELI=YES -DGVARS=YES -DTRANSLATIONS=CZ "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " X9LITES X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " X9LITES ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITES - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES -DMULTIMODULE=NO -DTRANSLATIONS=DE "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -105,14 +105,14 @@ fi if [[ " X7 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X7 - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DHELI=YES -DGVARS=YES -DTRANSLATIONS=ES "${SRCDIR}" + rm -rf ./* || true + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DHELI=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " X7ACCESS X7 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " X7ACCESS ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X7 ACCESS rm -rf ./* cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=ACCESS -DHELI=YES -DGVARS=YES -DTRANSLATIONS=FR "${SRCDIR}" @@ -121,43 +121,16 @@ if [[ " X7ACCESS X7 ALL " =~ \ ${FLAVOR}\ ]] ; then make -j"${CORES}" tests-radio fi -if [[ " T12 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " T12 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on T12 - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=T12 -DHELI=YES -DGVARS=YES -DTRANSLATIONS=IT "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " TX12 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then - # OpenTX on TX12 - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=TX12 -DHELI=YES -DGVARS=YES -DTRANSLATIONS=PT "${SRCDIR}" - make -j"${CORES}" ${FIRMARE_TARGET} - make -j"${CORES}" libsimulator - make -j"${CORES}" tests-radio -fi - -if [[ " T8 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then - # OpenTX on T8 - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=T8 -DHELI=YES -DGVARS=YES "${SRCDIR}" - make -j"${CORES}" ${FIRMARE_TARGET} - make -j"${CORES}" libsimulator - make -j"${CORES}" tests-radio -fi - -if [[ " TLITE X7 ALL " =~ \ ${FLAVOR}\ ]] ; then - # OpenTX on TLITE - rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=TLITE -DHELI=YES -DGVARS=YES "${SRCDIR}" - make -j"${CORES}" ${FIRMARE_TARGET} - make -j"${CORES}" libsimulator - make -j"${CORES}" tests-radio -fi - -if [[ " TX12 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " TX12 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on TX12 rm -rf ./* cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=TX12 -DHELI=YES -DGVARS=YES "${SRCDIR}" @@ -166,54 +139,72 @@ if [[ " TX12 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then make -j"${CORES}" tests-radio fi +if [[ " T8 ALL " =~ \ ${FLAVOR}\ ]] ; then + # OpenTX on T8 + rm -rf ./* + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=T8 -DHELI=YES -DGVARS=YES "${SRCDIR}" + make -j"${CORES}" ${FIRMARE_TARGET} + make -j"${CORES}" libsimulator + make -j"${CORES}" tests-radio +fi + +if [[ " TLITE ALL " =~ \ ${FLAVOR}\ ]] ; then + # OpenTX on TLITE + rm -rf ./* + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=TLITE -DHELI=YES -DGVARS=YES "${SRCDIR}" + make -j"${CORES}" ${FIRMARE_TARGET} + make -j"${CORES}" libsimulator + make -j"${CORES}" tests-radio +fi + if [[ " XLITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X-Lite - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=XLITE -DHELI=YES -DGVARS=YES -DTRANSLATIONS=SK "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " XLITES XLITE ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " XLITES ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X-Lites - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=XLITES -DHELI=YES -DGVARS=YES -DTRANSLATIONS=SE "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " X9D X9 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " X9D ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9D - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X9D -DHELI=YES -DLUA=YES -DGVARS=YES -DTRANSLATIONS=PL "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " X9D+ X9 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " X9DP ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9D+ - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X9D+ -DHELI=YES -DLUA=YES -DGVARS=YES -DTRANSLATIONS=HU "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " X9D+2019 X9 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " X9DP2019 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9D+ 2019 - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X9D+ -DPCBREV=2019 -DHELI=YES -DLUA=YES -DGVARS=YES -DTRANSLATIONS=NL "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio fi -if [[ " X9E X9 ALL " =~ \ ${FLAVOR}\ ]] ; then +if [[ " X9E ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on Taranis X9E - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X9E -DHELI=YES -DLUA=YES -DGVARS=YES -DPPM_UNIT=PERCENT_PREC1 "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -222,7 +213,7 @@ fi if [[ " X10 COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X10 boards - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X10 -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -231,7 +222,7 @@ fi if [[ " T16 COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on T16 boards - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X10 -DPCBREV=T16 -DHELI=YES -DLUA=YES -DGVARS=YES -DAFHDS3=NO "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -240,7 +231,7 @@ fi if [[ " TX16S COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on TX16S boards - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X10 -DPCBREV=TX16S -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -249,7 +240,7 @@ fi if [[ " X12S COLORLCD ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X12S - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" -DPCB=X12S -DHELI=YES -DLUA=YES -DGVARS=YES -DMULTIMODULE=NO "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -258,8 +249,8 @@ fi if [[ " COMPANION ALL " =~ \ ${FLAVOR}\ ]] ; then # Companion - rm -rf ./* + rm -rf ./* || true cmake "${COMMON_OPTIONS}" "${SRCDIR}" - make -j"${CORES}" companion23 simulator23 + make -j"${CORES}" companion24 simulator24 make -j"${CORES}" tests-companion fi From 0dddcd2ac81e06f983e1725b75b6339b56e1234f Mon Sep 17 00:00:00 2001 From: elecpower Date: Wed, 12 May 2021 08:45:14 +1000 Subject: [PATCH 51/70] Function to update all autowidgets --- companion/src/shared/autobitsetcheckbox.h | 2 +- companion/src/shared/autocheckbox.h | 2 +- companion/src/shared/autocombobox.h | 2 +- companion/src/shared/autodoublespinbox.h | 2 +- companion/src/shared/autohexspinbox.h | 2 +- companion/src/shared/autolabel.h | 2 +- companion/src/shared/autolineedit.h | 2 +- companion/src/shared/autoprecisioncombobox.h | 2 +- companion/src/shared/autoslider.h | 2 +- companion/src/shared/autospinbox.h | 2 +- companion/src/shared/autotimeedit.h | 2 +- companion/src/shared/autowidget.h | 2 ++ companion/src/shared/genericpanel.cpp | 11 +++++++++++ companion/src/shared/genericpanel.h | 1 + 14 files changed, 25 insertions(+), 11 deletions(-) diff --git a/companion/src/shared/autobitsetcheckbox.h b/companion/src/shared/autobitsetcheckbox.h index 6c3fef5c7..cf54bae85 100644 --- a/companion/src/shared/autobitsetcheckbox.h +++ b/companion/src/shared/autobitsetcheckbox.h @@ -24,7 +24,7 @@ #include -class AutoBitsetCheckBox: public QCheckBox, AutoWidget +class AutoBitsetCheckBox: public QCheckBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autocheckbox.h b/companion/src/shared/autocheckbox.h index 4f4e3c992..5eb0a3dfb 100644 --- a/companion/src/shared/autocheckbox.h +++ b/companion/src/shared/autocheckbox.h @@ -24,7 +24,7 @@ #include -class AutoCheckBox : public QCheckBox, AutoWidget +class AutoCheckBox : public QCheckBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autocombobox.h b/companion/src/shared/autocombobox.h index 5cecd3e70..1502a6176 100644 --- a/companion/src/shared/autocombobox.h +++ b/companion/src/shared/autocombobox.h @@ -26,7 +26,7 @@ #include -class AutoComboBox : public QComboBox, AutoWidget +class AutoComboBox : public QComboBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autodoublespinbox.h b/companion/src/shared/autodoublespinbox.h index fb3b26591..31eef93c4 100644 --- a/companion/src/shared/autodoublespinbox.h +++ b/companion/src/shared/autodoublespinbox.h @@ -28,7 +28,7 @@ #include #endif -class AutoDoubleSpinBox : public QDoubleSpinBox, AutoWidget +class AutoDoubleSpinBox : public QDoubleSpinBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autohexspinbox.h b/companion/src/shared/autohexspinbox.h index 440fb4740..6d7711c32 100644 --- a/companion/src/shared/autohexspinbox.h +++ b/companion/src/shared/autohexspinbox.h @@ -27,7 +27,7 @@ class QRegExpValidator; -class AutoHexSpinBox : public QSpinBox, AutoWidget +class AutoHexSpinBox : public QSpinBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autolabel.h b/companion/src/shared/autolabel.h index 1b31db024..369a1e680 100644 --- a/companion/src/shared/autolabel.h +++ b/companion/src/shared/autolabel.h @@ -24,7 +24,7 @@ #include -class AutoLabel: public QLabel, AutoWidget +class AutoLabel: public QLabel, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autolineedit.h b/companion/src/shared/autolineedit.h index 0820bc5dc..be1cccaa3 100644 --- a/companion/src/shared/autolineedit.h +++ b/companion/src/shared/autolineedit.h @@ -25,7 +25,7 @@ #include #include -class AutoLineEdit: public QLineEdit, AutoWidget +class AutoLineEdit: public QLineEdit, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autoprecisioncombobox.h b/companion/src/shared/autoprecisioncombobox.h index 7cebeaa36..b973c09fd 100644 --- a/companion/src/shared/autoprecisioncombobox.h +++ b/companion/src/shared/autoprecisioncombobox.h @@ -25,7 +25,7 @@ #include #include -class AutoPrecisionComboBox : public QComboBox, AutoWidget +class AutoPrecisionComboBox : public QComboBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autoslider.h b/companion/src/shared/autoslider.h index f83177c87..cb3a2fd11 100644 --- a/companion/src/shared/autoslider.h +++ b/companion/src/shared/autoslider.h @@ -24,7 +24,7 @@ #include -class AutoSlider : public QSlider, AutoWidget +class AutoSlider : public QSlider, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autospinbox.h b/companion/src/shared/autospinbox.h index a92d6db56..38842fbe0 100644 --- a/companion/src/shared/autospinbox.h +++ b/companion/src/shared/autospinbox.h @@ -24,7 +24,7 @@ #include -class AutoSpinBox : public QSpinBox, AutoWidget +class AutoSpinBox : public QSpinBox, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autotimeedit.h b/companion/src/shared/autotimeedit.h index e27607ce5..f398fd855 100644 --- a/companion/src/shared/autotimeedit.h +++ b/companion/src/shared/autotimeedit.h @@ -24,7 +24,7 @@ #include -class AutoTimeEdit : public QTimeEdit, AutoWidget +class AutoTimeEdit : public QTimeEdit, public AutoWidget { Q_OBJECT diff --git a/companion/src/shared/autowidget.h b/companion/src/shared/autowidget.h index 9680726b7..820befbdc 100644 --- a/companion/src/shared/autowidget.h +++ b/companion/src/shared/autowidget.h @@ -25,6 +25,8 @@ class GenericPanel; // Note: cannot be a Qt object otherwise it will create a compiler ambiguity in the inheriting class class AutoWidget { + friend class GenericPanel; + public: explicit AutoWidget(); ~AutoWidget(); diff --git a/companion/src/shared/genericpanel.cpp b/companion/src/shared/genericpanel.cpp index 5dfad648e..a60ed0cf0 100644 --- a/companion/src/shared/genericpanel.cpp +++ b/companion/src/shared/genericpanel.cpp @@ -19,6 +19,7 @@ */ #include "genericpanel.h" +#include "autowidget.h" #include #include @@ -127,3 +128,13 @@ void GenericPanel::disableMouseScrolling() foreach(QWidget * te, findChildren()) setFocusFilter(te); } + +void GenericPanel::updateAutoWidgets() +{ + foreach(QWidget *wdgt, findChildren()) { + AutoWidget *autowdgt = dynamic_cast(wdgt); + if (autowdgt) { + autowdgt->updateValue(); + } + } +} diff --git a/companion/src/shared/genericpanel.h b/companion/src/shared/genericpanel.h index f013584bd..32dfdadc8 100644 --- a/companion/src/shared/genericpanel.h +++ b/companion/src/shared/genericpanel.h @@ -58,4 +58,5 @@ class GenericPanel : public QWidget virtual bool eventFilter(QObject *obj, QEvent *event); void setFocusFilter(QWidget * w); void disableMouseScrolling(); + void updateAutoWidgets(); }; From f38460bfcc97825b2b404d71cc2d4cb42ec5f07c Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 12 May 2021 11:30:46 +0200 Subject: [PATCH 52/70] Fix R9M on colorlcd --- radio/src/targets/horus/extmodule_driver.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index e73d5c3d3..ef59d0b29 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -131,9 +131,8 @@ void extmodulePxx1PulsesStart() #endif EXTMODULE_TIMER->ARR = 45000; - EXTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - EXTMODULE_TIMER->DIER |= TIM_DIER_UDE | TIM_DIER_CC2IE; // Enable DMA on update + EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn); @@ -292,13 +291,21 @@ void extmoduleSendNextFrame() #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: - EXTMODULE_TIMER->CCR2 = extmodulePulsesData.pxx.getLast() - 4000; // 2mS in advance + if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) + return; + + // disable timer + EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData()); EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.pxx.getSize(); EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA + + // re-init timer + EXTMODULE_TIMER->EGR = 1; + EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; break; #endif From 3be966633a08e973815d9f6939f83d089ba07bf7 Mon Sep 17 00:00:00 2001 From: elecpower Date: Wed, 12 May 2021 19:58:47 +1000 Subject: [PATCH 53/70] Remove reference comments and cosmetics --- companion/src/modeledit/curves.cpp | 82 ++++++++++-------------------- 1 file changed, 28 insertions(+), 54 deletions(-) diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index 9f0a71ae5..600f58e97 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -33,20 +33,20 @@ float curveLinear(float x, float coeff, float yMin, float yMid, float yMax) { - float a = (yMax-yMin) / 200.0; - return yMin + a * (x+100.0); + float a = (yMax - yMin) / 200.0; + return yMin + a * (x + 100.0); } float c9xexpou(float point, float coeff) { - float x = point*1024.0/100.0; - float k = coeff*256.0/100.0; - return ((k*x*x*x/(1024*1024) + x*(256-k) + 128) / 256) / 1024.0 * 100; + float x = point * 1024.0 / 100.0; + float k = coeff * 256.0 / 100.0; + return ((k * x * x * x / (1024 * 1024) + x * (256 - k) + 128) / 256) / 1024.0 * 100; } float curveExpo(float x, float coeff, float yMin, float yMid, float yMax) { - float a = (yMax-yMin) / 100.0; + float a = (yMax - yMin) / 100.0; x += 100.0; x /= 2.0; @@ -57,14 +57,14 @@ float curveExpo(float x, float coeff, float yMin, float yMid, float yMax) else { coeff = -coeff; x = 100 - x; - return round((100.0 - c9xexpou(x, coeff))*a + yMin); + return round((100.0 - c9xexpou(x, coeff)) * a + yMin); } } float curveSymmetricalY(float x, float coeff, float yMin, float yMid, float yMax) { bool invert; - if (x<0) { + if (x < 0) { x = -x; invert = 1; } @@ -74,12 +74,12 @@ float curveSymmetricalY(float x, float coeff, float yMin, float yMid, float yMax float y; if (coeff >= 0) { - y = round(c9xexpou(x, coeff) * (yMax/100.0)); + y = round(c9xexpou(x, coeff) * (yMax / 100.0)); } else { coeff = -coeff; x = 100.0 - x; - y = round((100.0-c9xexpou(x, coeff)) * (yMax/100.0)); + y = round((100.0 - c9xexpou(x, coeff)) * (yMax / 100.0)); } if (invert) { @@ -91,9 +91,9 @@ float curveSymmetricalY(float x, float coeff, float yMin, float yMid, float yMax float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax) { - float a = (yMax-yMid) / 100.0; + float a = (yMax - yMid) / 100.0; - if (x<0) + if (x < 0) x = -x; float y; @@ -102,8 +102,8 @@ float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax } else { coeff = -coeff; - x = 100-x; - y = round((100.0-c9xexpou(x, coeff)) * a + yMid); + x = 100 - x; + y = round((100.0 - c9xexpou(x, coeff)) * a + yMid); } return y; @@ -148,38 +148,6 @@ CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & // The edit curve button QPushButton * edit = new QPushButton(this); edit->setProperty("index", i); - /* - From https://doc.qt.io/qt-5/qwidget.html#palette-prop - - The current style, which is used to render the content of all standard Qt widgets, is free to choose colors and brushes - from the widget palette, or in some cases, to ignore the palette (partially, or completely). - In particular, certain styles like GTK style, Mac style, and Windows Vista style, depend on third party APIs to render - the content of widgets, and these styles typically do not follow the palette. Because of this, assigning roles to a widget's palette - is not guaranteed to change the appearance of the widget. Instead, you may choose to apply a styleSheet. - - Warning: Do not use this function in conjunction with Qt Style Sheets. - When using style sheets, the palette of a widget can be customized using the "color", "background-color", - "selection-color", "selection-background-color" and "alternate-background-color". - */ - - // can only assume there have been some OS version specific display issues so the stylesheet was added - // to ensure control remove use of QPalette - //QPalette palette; - //palette.setBrush(QPalette::Active, QPalette::Button, QBrush(colors[i])); - //palette.setBrush(QPalette::Active, QPalette::ButtonText, QBrush(Qt::white)); - -/* rework see below -#ifdef __APPLE__ - // this sets text color to background color !!!! - //edit->setStyleSheet(QString("color: %1;").arg(colors[i].name())); -#elif defined WIN32 || !defined __GNUC__ - edit->setStyleSheet(QString("background-color: %1; color: white;").arg(colors[i].name())); -#else - // creates more compact buttons - edit->setStyleSheet(QString("background-color: %1; color: white; padding: 2px 3px; border-style: outset; border-width: 1px; - border-radius: 2px; border-color: inherit;").arg(colors[i].name())); -#endif -*/ #ifdef __GNUC__ // creates more compact and likely consistent buttons across OS flavors @@ -188,7 +156,6 @@ CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & edit->setStyleSheet(QString("background-color: %1; color: white;").arg(colors[i].name())); #endif - //edit->setPalette(palette); edit->setText(tr("Curve %1").arg(i + 1)); edit->setContextMenuPolicy(Qt::CustomContextMenu); edit->setToolTip(tr("Popup menu available")); @@ -203,8 +170,6 @@ CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & // The curve plot checkbox QCheckBox * plot = new QCheckBox(this); plot->setProperty("index", i); - // this has no effect on the checkbox so remove - //plot->setPalette(palette); connect(plot, SIGNAL(toggled(bool)), this, SLOT(plotCurve(bool))); if (i < limit) { ui->curvesLayout->addWidget(plot, i, 2, 1, 1); @@ -363,9 +328,15 @@ void CurvesPanel::updateCurve() int numpoints = model->curves[k].count; for (int i = 0; i < numpoints - 1; i++) { if (model->curves[k].type == CurveData::CURVE_TYPE_CUSTOM) - scene->addLine(centerX + (qreal)model->curves[k].points[i].x*width/200, centerY - (qreal)model->curves[k].points[i].y*height/200,centerX + (qreal)model->curves[k].points[i+1].x*width/200,centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen); + scene->addLine(centerX + (qreal)model->curves[k].points[i].x * width / 200, + centerY - (qreal)model->curves[k].points[i].y * height / 200, + centerX + (qreal)model->curves[k].points[i + 1].x * width / 200, + centerY - (qreal)model->curves[k].points[i + 1].y * height / 200, pen); else - scene->addLine(GFX_MARGIN + i*width/(numpoints-1), centerY - (qreal)model->curves[k].points[i].y*height/200,GFX_MARGIN + (i+1)*width/(numpoints-1),centerY - (qreal)model->curves[k].points[i+1].y*height/200, pen); + scene->addLine(GFX_MARGIN + i * width / (numpoints - 1), + centerY - (qreal)model->curves[k].points[i].y * height / 200, + GFX_MARGIN + (i + 1) * width / (numpoints - 1), + centerY - (qreal)model->curves[k].points[i + 1].y * height / 200, pen); } } } @@ -387,11 +358,13 @@ void CurvesPanel::updateCurve() else { nodex->setFixedX(true); } - nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x * width / 200, centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200); + nodex->setPos(centerX + (qreal)model->curves[currentCurve].points[i].x * width / 200, + centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200); } else { nodex->setFixedX(true); - nodex->setPos(GFX_MARGIN + i * width / (numpoints - 1), centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200); + nodex->setPos(GFX_MARGIN + i * width / (numpoints - 1), + centerY - (qreal)model->curves[currentCurve].points[i].y * height / 200); } connect(nodex, SIGNAL(moved(int, int)), this, SLOT(onNodeMoved(int, int))); connect(nodex, SIGNAL(focus()), this, SLOT(onNodeFocus())); @@ -623,7 +596,8 @@ void CurvesPanel::on_curveApply_clicked() } if (apply) { - model->curves[currentCurve].points[i].y = templates[index].function(x, ui->curveCoeff->value(), ui->yMin->value(), ui->yMid->value(), ui->yMax->value()); + model->curves[currentCurve].points[i].y = templates[index].function(x, ui->curveCoeff->value(), ui->yMin->value(), ui->yMid->value(), + ui->yMax->value()); } } From 74ad1edecea93b1c8148b42d64ee6a2b771cb48a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 12 May 2021 17:03:08 +0200 Subject: [PATCH 54/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index a0a5afc3f..78b0805b5 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2261,3 +2261,4 @@ Mark Gaskievicz James Miller Donald Taylor Paul Makepeace +Thomas Fowler From 7ba9a92feb30c42cd9229c25b4888bb188dca4f5 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 12 May 2021 17:26:56 +0200 Subject: [PATCH 55/70] cleanups --- radio/src/targets/horus/extmodule_driver.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index ef59d0b29..878e3ffea 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -182,8 +182,6 @@ void extmoduleSerialStart() NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn); NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn, 7); - NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); } #if defined(EXTMODULE_USART) @@ -296,7 +294,6 @@ void extmoduleSendNextFrame() // disable timer EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | EXTMODULE_TIMER_DMA_SIZE | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData()); @@ -439,7 +436,6 @@ extern "C" void EXTMODULE_TIMER_DMA_IRQHandler() DMA_ClearITPendingBit(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC); switch (moduleState[EXTERNAL_MODULE].protocol) { - case PROTOCOL_CHANNELS_PXX1_PULSES: case PROTOCOL_CHANNELS_PPM: EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt From 8a4787d1992e6b69fb0ae184500e33c60782a07d Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 12 May 2021 17:41:03 +0200 Subject: [PATCH 56/70] cleanups --- radio/src/targets/taranis/extmodule_driver.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 512f16c5d..46dd891bf 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -230,8 +230,6 @@ void extmodulePxx1PulsesStart() NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn); NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn, 7); - NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn); - NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); } #endif @@ -259,14 +257,12 @@ void extmoduleSendNextFrame() #if defined(PXX1) case PROTOCOL_CHANNELS_PXX1_PULSES: - if (EXTMODULE_TIMER_DMA_STREAM->CR & DMA_SxCR_EN) return; // disable timer EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData()); From 1703ffc06126e137dac8fbd5c7b9fbc93ab05024 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 12 May 2021 17:48:31 +0200 Subject: [PATCH 57/70] latency improve --- radio/src/tasks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index aa3ec3974..14fb0d92e 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -143,8 +143,8 @@ TASK_FUNCTION(mixerTask) while (true) { for (int timeout = 0; timeout < MIXER_MAX_PERIOD; timeout += MIXER_FREQUENT_ACTIONS_PERIOD) { - bool interruptedByTimeout = mixerSchedulerWaitForTrigger(MIXER_FREQUENT_ACTIONS_PERIOD); execMixerFrequentActions(); + bool interruptedByTimeout = mixerSchedulerWaitForTrigger(MIXER_FREQUENT_ACTIONS_PERIOD); if (!interruptedByTimeout) { break; } From d695719262922a89b8acdb3e7efbe1bdf0cbecc7 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 12 May 2021 17:52:03 +0200 Subject: [PATCH 58/70] Cosmetics --- radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp | 3 ++- radio/src/tasks.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp index f89548fd2..79e5c7bd0 100644 --- a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp +++ b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp @@ -41,6 +41,7 @@ void mixerSchedulerStart() MIXER_SCHEDULER_TIMER->SR &= TIM_SR_UIF; // clear interrupt flag MIXER_SCHEDULER_TIMER->CR1 |= TIM_CR1_CEN; + mixerSchedulerClearTrigger(); mixerSchedulerEnableTrigger(); } @@ -54,12 +55,12 @@ void mixerSchedulerResetTimer() { mixerSchedulerDisableTrigger(); MIXER_SCHEDULER_TIMER->CNT = 0; + mixerSchedulerClearTrigger(); mixerSchedulerEnableTrigger(); } void mixerSchedulerEnableTrigger() { - mixerSchedulerClearTrigger(); MIXER_SCHEDULER_TIMER->DIER |= TIM_DIER_UIE; // enable interrupt } diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 14fb0d92e..692ae6d27 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -157,6 +157,7 @@ TASK_FUNCTION(mixerTask) #if !defined(PCBSKY9X) // re-enable trigger + mixerSchedulerClearTrigger(); mixerSchedulerEnableTrigger(); #endif From 266ec075d89938d88168b06e9875a646093268fe Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 12 May 2021 17:55:45 +0200 Subject: [PATCH 59/70] Cosmetics --- radio/src/tasks.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/tasks.cpp b/radio/src/tasks.cpp index 692ae6d27..a0f7384a9 100644 --- a/radio/src/tasks.cpp +++ b/radio/src/tasks.cpp @@ -156,7 +156,6 @@ TASK_FUNCTION(mixerTask) #endif #if !defined(PCBSKY9X) - // re-enable trigger mixerSchedulerClearTrigger(); mixerSchedulerEnableTrigger(); #endif From c3ed75644c78f31d3d3d69b7874fc604347505f0 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 13 May 2021 11:03:17 +0200 Subject: [PATCH 60/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 78b0805b5..7c965b4a8 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2262,3 +2262,4 @@ James Miller Donald Taylor Paul Makepeace Thomas Fowler +Walter Szempruch From 30bdb4ff239b03d81619b0931cedc5d7989666f2 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 14 May 2021 08:55:00 +0200 Subject: [PATCH 61/70] Create macosx_cpn_nightly.yml --- .github/workflows/macosx_cpn_nightly.yml | 112 +++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 .github/workflows/macosx_cpn_nightly.yml diff --git a/.github/workflows/macosx_cpn_nightly.yml b/.github/workflows/macosx_cpn_nightly.yml new file mode 100644 index 000000000..66b68ee6c --- /dev/null +++ b/.github/workflows/macosx_cpn_nightly.yml @@ -0,0 +1,112 @@ +name: MacOSX nightly Companion + +on: + schedule: + - cron: '20 23 * * *' + + workflow_dispatch: + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + + - name: Create Build Environment + # Some projects don't allow in-source building, so create a separate build directory + # We'll use this as our working directory for all subsequent commands + run: cmake -E make_directory ${{github.workspace}}/build + + - name: Install Qt + uses: jurplel/install-qt-action@v2 + with: + version: '5.12.9' + + - name: Install dependencies + run: python -m pip install --upgrade pip Pillow + + - name: Install ARM toolchain + uses: fiam/arm-none-eabi-gcc@v1 + with: + release: '6-2017-q2' + + - name: Install dfu-util + run: wget https://downloads.sourceforge.net/project/dfu-util/dfu-util-0.9.tar.gz && + tar xfv dfu-util-0.9.tar.gz && + cd dfu-util-0.9 && + ./configure && + make install + + - name: Install libusb + run: wget https://github.com/libusb/libusb/releases/download/v1.0.20/libusb-1.0.20.tar.bz2 && + export MACOSX_DEPLOYMENT_TARGET=10.9 && + tar xfv libusb-1.0.20.tar.bz2 && + cd libusb-1.0.20 && + ./configure && + make install && + cd .. + + - name: Install libsdl + run: wget https://www.libsdl.org/release/SDL-1.2.15.tar.gz && + tar xfv SDL-1.2.15.tar.gz && + export MACOSX_DEPLOYMENT_TARGET=10.9 && + cd SDL-1.2.15 && + wget 'https://bugzilla-attachments.libsdl.org/attachment.cgi?id=1320' -O patch1 && + wget 'https://bugzilla-attachments.libsdl.org/attachment.cgi?id=1324' -O patch2 && + wget 'https://hg.libsdl.org/SDL/raw-rev/91ad7b43317a' -O patch3 && + patch -p1 < patch1 && + patch -p1 < patch2 && + patch -p1 < patch3 && + ./configure --without-x && + make install + + - name: install lftp + working-directory: ${{github.workspace}} + shell: bash + run: brew install lftp + + - name: Configure CMake + # Use a bash shell so we can use the same syntax for environment variable + # access regardless of the host operating system + shell: bash + working-directory: ${{github.workspace}}/build + # Note the current convention is to use the -S and -B options here to specify source + # and build directories, but this is only available with CMake 3.13 and higher. + # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_OSX_DEPLOYMENT_TARGET='10.9' + + - name: Build + working-directory: ${{github.workspace}} + shell: bash + # Execute the build. You can specify a specific target with "--target " + run: mkdir ${{github.workspace}}/output && tools/build-companion-nightly.sh ${{github.workspace}} ${{github.workspace}}/output/ + + - name: Archive production artifacts + uses: actions/upload-artifact@v2 + with: + name: companion-nightly + path: ${{github.workspace}}/output + retention-days: 1 + + publish: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v2 + with: + name: companion-nightly + - uses: eine/tip@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: 'nightly' + rm: true + files: ./* From d636cab1847a3f77d66019ecd55545c4a60e9479 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 14 May 2021 09:22:25 +0200 Subject: [PATCH 62/70] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 7c965b4a8..ea0603324 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2263,3 +2263,5 @@ Donald Taylor Paul Makepeace Thomas Fowler Walter Szempruch +Charles Starck +Fabian Mächler From 4047dbdd8289f732b7f55d75923d2081c54f6980 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 14 May 2021 12:16:48 +0200 Subject: [PATCH 63/70] Update makefiles (#8506) --- tools/build-companion-nightly.sh | 22 +++++++++++++++++++++- tools/build-companion-release.sh | 15 ++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index a0406f691..774abb2fc 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -4,7 +4,12 @@ set -e set -x -JOBS=3 +if [ "$(uname)" = "Darwin" ]; then + num_cpus=$(sysctl -n hw.ncpu) + : "${JOBS:=$num_cpus}" +else + JOBS=3 +fi while [ $# -gt 0 ] do @@ -32,6 +37,13 @@ fi if [ "$3" != "" ]; then COMMON_OPTIONS="${COMMON_OPTIONS} -DVERSION_SUFFIX=$3" +elif [ "$(uname)" = "Darwin" ]; then + wget https://downloads.open-tx.org/2.3/nightlies/companion/companion-linux.stamp + version=$(cut -d'N' -f 3 < companion-linux.stamp) + version=$(echo $version | tr -cd '[[:digit:]]') + version=$((version+1)) + nightly=N"$version" + COMMON_OPTIONS="${COMMON_OPTIONS} -DVERSION_SUFFIX=$nightly" fi rm -rf build @@ -74,6 +86,14 @@ cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TX12 ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt +cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T8 ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + +cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TLITE ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + cmake ${COMMON_OPTIONS} -DPCB=X9D ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt diff --git a/tools/build-companion-release.sh b/tools/build-companion-release.sh index 463645dc2..e8214977f 100755 --- a/tools/build-companion-release.sh +++ b/tools/build-companion-release.sh @@ -4,7 +4,12 @@ set -e set -x -JOBS=2 +if [ "$(uname)" = "Darwin" ]; then + num_cpus=$(sysctl -n hw.ncpu) + : "${JOBS:=$num_cpus}" +else + JOBS=3 +fi while [ $# -gt 0 ] do @@ -74,6 +79,14 @@ cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TX12 ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt +cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T8 ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + +cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TLITE ${SRCDIR} +make -j${JOBS} libsimulator +rm CMakeCache.txt + cmake ${COMMON_OPTIONS} -DPCB=X9D ${SRCDIR} make -j${JOBS} libsimulator rm CMakeCache.txt From 8db5244ed0c3348e04cf6f2a5a53d46fb036e7d5 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 14 May 2021 13:10:46 +0200 Subject: [PATCH 64/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index ea0603324..b5abbb54f 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2265,3 +2265,4 @@ Thomas Fowler Walter Szempruch Charles Starck Fabian Mächler +David Van Dyne From 2d36ef626c3ead532a1e4a0c7c77ee4a5883fcee Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 15 May 2021 08:30:59 +0200 Subject: [PATCH 65/70] Fix #8510 --- radio/src/targets/taranis/hal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 5c00b3052..08f882076 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -2034,7 +2034,7 @@ #define AUDIO_SPEAKER_ENABLE_GPIO_PIN GPIO_Pin_14 // PD.14 #define HEADPHONE_TRAINER_SWITCH_GPIO GPIOD #define HEADPHONE_TRAINER_SWITCH_GPIO_PIN GPIO_Pin_9 // PD.09 -#elif defined(AUDIO_MUTE_GPIO) +#elif defined(RADIO_TX12) || defined(RADIO_T8) || defined(RADIO_TLITE) #define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1) #define AUDIO_MUTE_GPIO GPIOE #define AUDIO_MUTE_GPIO_PIN GPIO_Pin_12 // PE.12 From 4c8c107830872c2e2b551c085368385d29f5f052 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 15 May 2021 11:21:36 +0200 Subject: [PATCH 66/70] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index b5abbb54f..dc9dc238d 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2266,3 +2266,4 @@ Walter Szempruch Charles Starck Fabian Mächler David Van Dyne +Karim el Mawardi From dcbea93d31429d1f5e48e8e2cb7a8da3800fab83 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 15 May 2021 13:38:03 +0200 Subject: [PATCH 67/70] Add linux nightly companion action --- .github/workflows/linux_cpn_nightly.yml | 58 +++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 .github/workflows/linux_cpn_nightly.yml diff --git a/.github/workflows/linux_cpn_nightly.yml b/.github/workflows/linux_cpn_nightly.yml new file mode 100644 index 000000000..b1c0d3ebe --- /dev/null +++ b/.github/workflows/linux_cpn_nightly.yml @@ -0,0 +1,58 @@ +name: Do Linux nightly Companion + +on: + workflow_run: + workflows: ["Do MacOSX nightly Companion"] + types: + - completed + + workflow_dispatch: + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-18.04 + + steps: + - name: Init + run: sudo apt update + + - name: Install dependencies + run: sudo apt-get -y install build-essential cmake gcc git lib32ncurses5 lib32z1 libfox-1.6-dev libsdl1.2-dev + qt5-default qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5svg5-dev + software-properties-common wget zip libgtest-dev libclang1-7 python3-pip + + - name: Install cross compiler + run: wget -q https://launchpad.net/gcc-arm-embedded/4.7/4.7-2013-q3-update/+download/gcc-arm-none-eabi-4_7-2013q3-20130916-linux.tar.bz2 && + tar xjf gcc-arm-none-eabi-4_7-2013q3-20130916-linux.tar.bz2 && + mv gcc-arm-none-eabi-4_7-2013q3 /opt/gcc-arm-none-eabi && + echo "/opt/gcc-arm-none-eabi/bin:/opentx/code/radio/util" >> $GITHUB_PATH + + - name: Install pillow + run: python -m pip install filelock clang pillow + + - uses: actions/checkout@v2 + - name: Create Build Environment + # Some projects don't allow in-source building, so create a separate build directory + # We'll use this as our working directory for all subsequent commands + run: cmake -E make_directory ${{github.workspace}}/build + + - name: Build + working-directory: ${{github.workspace}} + shell: bash + # Execute the build. You can specify a specific target with "--target " + run: mkdir ${{github.workspace}}/output && tools/build-companion-nightly.sh ${{github.workspace}} ${{github.workspace}}/output/ + + - uses: eine/tip@master + with: + token: ${{ secrets.GITHUB_TOKEN }} + tag: 'nightly' + files: ${{github.workspace}}/output/*.deb + From a94fec31d560385b18904f7fb52ff4eb1eff1b15 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 15 May 2021 13:39:08 +0200 Subject: [PATCH 68/70] Fixes --- .github/workflows/linux_cpn_nightly.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux_cpn_nightly.yml b/.github/workflows/linux_cpn_nightly.yml index b1c0d3ebe..bd181a686 100644 --- a/.github/workflows/linux_cpn_nightly.yml +++ b/.github/workflows/linux_cpn_nightly.yml @@ -1,8 +1,8 @@ -name: Do Linux nightly Companion +name: Linux nightly Companion on: workflow_run: - workflows: ["Do MacOSX nightly Companion"] + workflows: ["MacOSX nightly Companion"] types: - completed From af17efaddaaa75bedddf62113ef2ef2c18955407 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 15 May 2021 13:40:25 +0200 Subject: [PATCH 69/70] Fix #8477 --- radio/src/io/multi_firmware_update.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index 125ef900f..c58e52fec 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -118,7 +118,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver if (inverted) telemetryPortInvertedInit(57600); else - telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT); + telemetryPortInit(57600, TELEMETRY_SERIAL_WITHOUT_DMA); } bool getByte(uint8_t & byte) const override @@ -164,7 +164,7 @@ class MultiExtSportUpdateDriver: public MultiFirmwareUpdateDriver void init(bool inverted) const override { - telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT); + telemetryPortInit(57600, TELEMETRY_SERIAL_WITHOUT_DMA); } bool getByte(uint8_t & byte) const override From 418d212ad931be13358d37ef869ae449577a0145 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 15 May 2021 13:41:14 +0200 Subject: [PATCH 70/70] GH Companion nightlies --- tools/build-companion-nightly.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index 774abb2fc..8608ac6fd 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -37,7 +37,7 @@ fi if [ "$3" != "" ]; then COMMON_OPTIONS="${COMMON_OPTIONS} -DVERSION_SUFFIX=$3" -elif [ "$(uname)" = "Darwin" ]; then +else wget https://downloads.open-tx.org/2.3/nightlies/companion/companion-linux.stamp version=$(cut -d'N' -f 3 < companion-linux.stamp) version=$(echo $version | tr -cd '[[:digit:]]')