From 744bcab0b96125c776306ab36158d22bc875ef20 Mon Sep 17 00:00:00 2001 From: WismyYao Date: Sat, 30 Jan 2021 13:39:09 +0800 Subject: [PATCH 001/114] 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 002/114] 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 003/114] 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 004/114] 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 005/114] 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 006/114] 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 007/114] 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 008/114] 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 009/114] 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 010/114] [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 011/114] 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 012/114] 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 013/114] 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 014/114] 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 015/114] 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 016/114] 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 017/114] 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 018/114] 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 019/114] 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 020/114] 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 021/114] 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 022/114] 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 023/114] 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 024/114] 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 025/114] 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 026/114] 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 027/114] 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 028/114] 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 029/114] 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 030/114] 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 031/114] 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 032/114] 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 033/114] 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 034/114] 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 035/114] 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 036/114] 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 037/114] 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 038/114] 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 039/114] 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 040/114] 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 041/114] 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 042/114] 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 043/114] 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 044/114] 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 045/114] 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 046/114] 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 047/114] 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 048/114] 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 049/114] 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 050/114] 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 051/114] 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 052/114] 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 053/114] 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 054/114] 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 055/114] 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 056/114] 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 057/114] 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 058/114] 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 059/114] 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 060/114] 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 061/114] 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 062/114] 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 063/114] 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 064/114] 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 065/114] 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 066/114] 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 067/114] 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 068/114] 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 069/114] 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 070/114] 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:]]') From ea616c71876843a32352eab4c68d27a76ca19405 Mon Sep 17 00:00:00 2001 From: Risto Date: Sat, 15 May 2021 20:20:55 +0200 Subject: [PATCH 071/114] Fix -DLUA=OFF build on color radios (#21) --- radio/src/gui/colorlcd/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index d1271bda3..b7000a10e 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -64,7 +64,6 @@ set(GUI_SRC menu_screen.cpp screen_setup.cpp switch_warn_dialog.cpp - standalone_lua.cpp ) macro(add_gui_src src) @@ -74,6 +73,10 @@ macro(add_gui_src src) ) endmacro(add_gui_src) +if(LUA) + add_gui_src(standalone_lua.cpp) +endif() + if(HELI) add_gui_src(model_heli.cpp) endif() From c3989f7a663d51e260743ab1147e9972ecae443e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 16 May 2021 13:14:34 +0200 Subject: [PATCH 072/114] Compilation fix --- 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 8b8615b4c..93bba22e9 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -455,7 +455,7 @@ PACK(struct ModuleData { uint8_t spare2:1 SKIP; int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms) } sbus); - NOBACKUP(PACK(struct { + NOBACKUP(struct { uint8_t receivers:7; // 4 bits spare uint8_t racingMode:1; char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME]; From e2c621c9a1f8043dfbf974e19a859614c6a9d66e Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 16 May 2021 20:48:31 +1000 Subject: [PATCH 073/114] Use the selection colour as the progress bar border --- radio/src/targets/horus/bootloader/boot_menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/horus/bootloader/boot_menu.cpp b/radio/src/targets/horus/bootloader/boot_menu.cpp index a4ae513d1..310b5fbb7 100644 --- a/radio/src/targets/horus/bootloader/boot_menu.cpp +++ b/radio/src/targets/horus/bootloader/boot_menu.cpp @@ -141,7 +141,7 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) opt = 100; // Completed > 100% } - lcd->drawRect(70, 120, 340, 31, 2); + lcd->drawRect(70, 120, 340, 31, 2, SOLID, BL_SELECTED); lcd->drawSolidFilledRect(74, 124, (332 * opt) / 100, 23, color); } else if (st == ST_DIR_CHECK) { From e66189308ea4f4f4b151b82a16b02f34842fce19 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 16 May 2021 19:50:11 +0200 Subject: [PATCH 074/114] Repair Chinese translation --- radio/src/translations/cn.h.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/src/translations/cn.h.txt b/radio/src/translations/cn.h.txt index 337592c68..4a2cc6617 100644 --- a/radio/src/translations/cn.h.txt +++ b/radio/src/translations/cn.h.txt @@ -199,9 +199,10 @@ #endif #define TR_SF_SCREENSHOT "截屏\0 " +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[保留]\0 " -#define TR_VFSWFUNC TR_SF_SAFETY "教练\0 " "摇杆值存储到微调" "复位\0 " "设置\0 " TR_ADJUST_GVAR "音量\0 " "设置失控保护\0 " "测距模式\0 " "模块对频\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 "背光\0 " TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "教练\0 " "摇杆值存储到微调" "复位\0 " "设置\0 " TR_ADJUST_GVAR "音量\0 " "设置失控保护\0 " "测距模式\0 " "模块对频\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 "背光\0 " TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\010") @@ -1155,6 +1156,7 @@ #define TR_JITTER_FILTER "类比输入滤波" #define TR_RTC_CHECK TR("Check RTC", "检查时间驱动电池电压") #define TR_AUTH_FAILURE "验证失败" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" From 926065e3a1008e2640caf08f2cd72ffe63725b42 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Sun, 16 May 2021 23:33:58 +0200 Subject: [PATCH 075/114] add a gps icon if internal gps (and mavtelem) --- radio/src/bitmaps/480x272/mask_topmenu_gps_18.png | Bin 0 -> 781 bytes radio/src/gui/colorlcd/bitmaps.cpp | 4 ++++ radio/src/gui/colorlcd/bitmaps.h | 1 + radio/src/gui/colorlcd/layouts/topbar_impl.cpp | 12 ++++++++++++ 4 files changed, 17 insertions(+) create mode 100644 radio/src/bitmaps/480x272/mask_topmenu_gps_18.png diff --git a/radio/src/bitmaps/480x272/mask_topmenu_gps_18.png b/radio/src/bitmaps/480x272/mask_topmenu_gps_18.png new file mode 100644 index 0000000000000000000000000000000000000000..8e3ee9cfb8f4193f918835bf9d143cf336d940d2 GIT binary patch literal 781 zcmV+o1M>WdP)rfEJ=g1+pbfK$0K-XP%Bl;G)?Mg7vr7l`1iG2Y@s^Fri+3BiFK|zEr zEN)6)K<(yo@ffcsHvgM5a~C&}+@kk7kT6UpU(PrA4bWUDrEq(D`@Prec|?SW_~-VY zfGj~ojN>?2UtbRaz%P|b-tqCVn?9p&31wfb*XthV+;tphdU|?l0{|Wz98A*|{LYDR zYir8^favk@(amayhlheO7Mz`(1^Jggv-@G~?(WV50N*f-=bRn9xVVs-rbX>``=wT^ z`KD<~B2x1Q{L9+y?X3#{Xc)$itU(A7S1Oel04Te5cXyqC4x5PZ^77IJfUwnSNg+hg zY&PwMg@q(9RIAmzFNN|k9*;fFc~~eEkTIt6A^I0%`?lgd|lVWZnyi+IS*T{mdvAZa&q!oDwVumujhkhSx&WD^@)f&osPe>wB!;| zl3za}!tr?Q0YI2XLrVDu0MnhFohjJ1tu#&Z`~AL*qG-0VvJx*ZFS~=mAP_<%>CA|T zC`AJe!+3spcyIu~+1S_!l~M?)UzahaZf*^Cx3W_4|F9&FKFAUXDg1IR`BbheJ=-b(yb0F2|#zBX4nW(XUpk z{@&hRbaizVKRrG9a|?@~1E$UV3KiP00000 LNkvXXu0mjfcFSpq literal 0 HcmV?d00001 diff --git a/radio/src/gui/colorlcd/bitmaps.cpp b/radio/src/gui/colorlcd/bitmaps.cpp index a66602f93..c079a4225 100644 --- a/radio/src/gui/colorlcd/bitmaps.cpp +++ b/radio/src/gui/colorlcd/bitmaps.cpp @@ -32,6 +32,10 @@ const uint8_t LBM_DOT[] = { * Main view bitmaps */ +const uint8_t LBM_TOPMENU_GPS[] = { +#include "mask_topmenu_gps_18.lbm" +}; + const uint8_t LBM_TOPMENU_USB[] = { #include "mask_topmenu_usb.lbm" }; diff --git a/radio/src/gui/colorlcd/bitmaps.h b/radio/src/gui/colorlcd/bitmaps.h index 7c163867c..3c6512153 100644 --- a/radio/src/gui/colorlcd/bitmaps.h +++ b/radio/src/gui/colorlcd/bitmaps.h @@ -25,6 +25,7 @@ extern const uint8_t LBM_DOT[]; // Main view icons +extern const uint8_t LBM_TOPMENU_GPS[]; extern const uint8_t LBM_TOPMENU_USB[]; extern const uint8_t LBM_TOPMENU_ANTENNA[]; extern const uint8_t LBM_TOPMENU_VOLUME_0[]; diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp index 70cbd56dc..4e12fe4ba 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp @@ -32,6 +32,9 @@ TopbarImpl::TopbarImpl(Window * parent) : unsigned int TopbarImpl::getZonesCount() const { +#if defined(TELEMETRY_MAVLINK) && defined(INTERNAL_GPS) + return MAX_TOPBAR_ZONES-1; +#endif return MAX_TOPBAR_ZONES; } @@ -88,6 +91,15 @@ void TopbarImpl::paint(BitmapBuffer * dc) getTimerString(str, getValue(MIXSRC_TX_TIME)); dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | MENU_COLOR); +#if defined(TELEMETRY_MAVLINK) && defined(INTERNAL_GPS) + if (gpsData.fix) { + char s[10]; + sprintf(s, "%d", gpsData.numSat); + dc->drawText(LCD_W-148, 4, s, FONT(XS) | CENTERED | MENU_COLOR); + } + dc->drawBitmapPattern(LCD_W-158, 22, LBM_TOPMENU_GPS, (gpsData.fix) ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR); +#endif + // USB icon if (usbPlugged()) { dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, MENU_COLOR); From 0939d1bdffb9590435aa7e51640c93b76d13a7e5 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Sun, 16 May 2021 23:54:58 +0200 Subject: [PATCH 076/114] get rid of two warnings, the 1st is in fact close to a bug --- radio/src/gui/colorlcd/colors.h | 2 +- radio/src/gui/colorlcd/select_fab_carousel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/colors.h b/radio/src/gui/colorlcd/colors.h index 7a9c76604..8d0991676 100644 --- a/radio/src/gui/colorlcd/colors.h +++ b/radio/src/gui/colorlcd/colors.h @@ -101,7 +101,7 @@ inline void lcdSetColor(uint16_t color) lcdColorTable[CUSTOM_COLOR_INDEX] = color; } -#define COLOR(index) (lcdColorTable[ unsigned(index) & 0xFF ] << 16u) +#define COLOR(index) ((uint32_t)lcdColorTable[ unsigned(index) & 0xFF ] << 16u) #define ALARM_COLOR COLOR(ALARM_COLOR_INDEX) #define BARGRAPH1_COLOR COLOR(BARGRAPH1_COLOR_INDEX) diff --git a/radio/src/gui/colorlcd/select_fab_carousel.cpp b/radio/src/gui/colorlcd/select_fab_carousel.cpp index 215efe8d7..f1abe1d3c 100644 --- a/radio/src/gui/colorlcd/select_fab_carousel.cpp +++ b/radio/src/gui/colorlcd/select_fab_carousel.cpp @@ -40,7 +40,7 @@ void SelectFabCarousel::addButton(uint8_t icon, const char* title, coord_t x_pos = pageWidth * buttons;// + SELECT_BUTTON_BORDER / 2; buttons++; - auto button = new SelectFabButton(this, x_pos, y_pos, icon, title, pressHandler); + /*auto button =*/ new SelectFabButton(this, x_pos, y_pos, icon, title, pressHandler); setInnerWidth(pageWidth * buttons); // y_pos += button->width() + SELECT_BUTTON_BORDER; From 97c94f910187e59eba086d8a86c8cdda77a70663 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Mon, 17 May 2021 00:45:12 +0200 Subject: [PATCH 077/114] system hardware menu, aligned it really looks much better --- radio/src/gui/colorlcd/radio_hardware.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/radio/src/gui/colorlcd/radio_hardware.cpp b/radio/src/gui/colorlcd/radio_hardware.cpp index f2932f9a3..7e1c353ae 100644 --- a/radio/src/gui/colorlcd/radio_hardware.cpp +++ b/radio/src/gui/colorlcd/radio_hardware.cpp @@ -152,9 +152,9 @@ void RadioHardwarePage::build(FormWindow * window) { FormGridLayout grid; #if LCD_W > LCD_H - grid.setLabelWidth(130); + grid.setLabelWidth(180); #else - grid.setLabelWidth(100); + grid.setLabelWidth(130); #endif grid.spacer(6); @@ -233,15 +233,10 @@ void RadioHardwarePage::build(FormWindow * window) }); grid.nextLine(); } -#if LCD_W > LCD_H - grid.setLabelWidth(180); -#else - grid.setLabelWidth(130); -#endif // Bat calibration new StaticText(window, grid.getLabelSlot(), STR_BATT_CALIB); - auto batCal = new NumberEdit(window, grid.getFieldSlot(), -127, 127, GET_SET_DEFAULT(g_eeGeneral.txVoltageCalibration)); + auto batCal = new NumberEdit(window, grid.getFieldSlot(1,0), -127, 127, GET_SET_DEFAULT(g_eeGeneral.txVoltageCalibration)); batCal->setDisplayHandler([](BitmapBuffer * dc, LcdFlags flags, int32_t value) { dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, getBatteryVoltage(), flags | PREC2, 0, nullptr, "V"); }); @@ -250,14 +245,14 @@ void RadioHardwarePage::build(FormWindow * window) // RTC Batt display new StaticText(window, grid.getLabelSlot(), STR_RTC_BATT); - new DynamicNumber(window, grid.getFieldSlot(), [] { + new DynamicNumber(window, grid.getFieldSlot(1,0), [] { return getRTCBatteryVoltage(); }, PREC2, nullptr, "V"); grid.nextLine(); // RTC Batt check enable new StaticText(window, grid.getLabelSlot(), STR_RTC_CHECK); - new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_eeGeneral.disableRtcWarning )); + new CheckBox(window, grid.getFieldSlot(1,0), GET_SET_INVERTED(g_eeGeneral.disableRtcWarning )); grid.nextLine(); #if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000 @@ -301,7 +296,7 @@ void RadioHardwarePage::build(FormWindow * window) // ADC filter new StaticText(window, grid.getLabelSlot(), STR_JITTER_FILTER); - new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_eeGeneral.jitterFilter)); + new CheckBox(window, grid.getFieldSlot(1,0), GET_SET_INVERTED(g_eeGeneral.jitterFilter)); grid.nextLine(); // Debugs From 7faf142af115687fbb0c45213ce9cba942129a1c Mon Sep 17 00:00:00 2001 From: olliw42 Date: Mon, 17 May 2021 18:47:09 +0200 Subject: [PATCH 078/114] there is a const for it, so let's use it :) --- radio/src/gui/colorlcd/radio_hardware.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/radio_hardware.cpp b/radio/src/gui/colorlcd/radio_hardware.cpp index 7e1c353ae..d050eba19 100644 --- a/radio/src/gui/colorlcd/radio_hardware.cpp +++ b/radio/src/gui/colorlcd/radio_hardware.cpp @@ -156,7 +156,7 @@ void RadioHardwarePage::build(FormWindow * window) #else grid.setLabelWidth(130); #endif - grid.spacer(6); + grid.spacer(PAGE_PADDING); // Calibration new StaticText(window, grid.getLabelSlot(), STR_INPUTS, 0, FONT(BOLD)); From a6d3337978c04eda6dd1a44556947dd04f5d47b3 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Mon, 17 May 2021 18:35:21 +0200 Subject: [PATCH 079/114] model telemetry page, align fields, and correct discovery button --- radio/src/gui/colorlcd/model_telemetry.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/radio/src/gui/colorlcd/model_telemetry.cpp b/radio/src/gui/colorlcd/model_telemetry.cpp index 45e34a752..ca24c6c99 100644 --- a/radio/src/gui/colorlcd/model_telemetry.cpp +++ b/radio/src/gui/colorlcd/model_telemetry.cpp @@ -387,8 +387,7 @@ void ModelTelemetryPage::editSensor(FormWindow * window, uint8_t index) void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex) { FormGridLayout grid; - grid.spacer(8); - grid.setLabelWidth(170); + grid.spacer(PAGE_PADDING); this->window = window; @@ -470,7 +469,7 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex) } // Autodiscover button - auto discover = new TextButton(window, grid.getFieldSlot(2, 0), STR_DISCOVER_SENSORS); + auto discover = new TextButton(window, grid.getFieldSlot(2, 0), (allowNewSensors) ? STR_STOP_DISCOVER_SENSORS : STR_DISCOVER_SENSORS); discover->setPressHandler([=]() { allowNewSensors = !allowNewSensors; if (allowNewSensors) { @@ -509,14 +508,15 @@ void ModelTelemetryPage::build(FormWindow * window, int8_t focusSensorIndex) grid.nextLine(); } + // restore aligned layout + grid.setLabelWidth(PAGE_LABEL_WIDTH); + // Ignore instance button - grid.setLabelWidth(170); new StaticText(window, grid.getLabelSlot(true), STR_IGNORE_INSTANCE); new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.ignoreSensorIds)); grid.nextLine(); // Vario - grid.setLabelWidth(100); new Subtitle(window, grid.getLineSlot(), STR_VARIO); grid.nextLine(); new StaticText(window, grid.getLabelSlot(true), STR_SOURCE); From d3189b38e6862f60075a1cd07bc11a1e946c592e Mon Sep 17 00:00:00 2001 From: olliw42 Date: Mon, 17 May 2021 00:18:33 +0200 Subject: [PATCH 080/114] system radio setup gps two issues --- radio/src/gui/colorlcd/radio_setup.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/radio_setup.cpp b/radio/src/gui/colorlcd/radio_setup.cpp index 063805cc7..f2870a528 100644 --- a/radio/src/gui/colorlcd/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio_setup.cpp @@ -376,6 +376,7 @@ void RadioSetupPage::build(FormWindow * window) grid.nextLine(); #endif +#if defined(INTERNAL_GPS) // GPS { new Subtitle(window, grid.getLabelSlot(), STR_GPS); @@ -383,7 +384,7 @@ void RadioSetupPage::build(FormWindow * window) // Timezone new StaticText(window, grid.getLabelSlot(true), STR_TIMEZONE); - new NumberEdit(window, grid.getFieldSlot(2, 0), -12, 12, GET_SET_DEFAULT(g_eeGeneral.timezone)); + new NumberEdit(window, grid.getFieldSlot(), -12, 12, GET_SET_DEFAULT(g_eeGeneral.timezone)); grid.nextLine(); // Adjust RTC (from telemetry) @@ -396,6 +397,7 @@ void RadioSetupPage::build(FormWindow * window) new Choice(window, grid.getFieldSlot(), STR_GPSFORMAT, 0, 1, GET_SET_DEFAULT(g_eeGeneral.gpsFormat)); grid.nextLine(); } +#endif #if defined(PXX2) // Owner ID From b4842420105334eb7b01987dd42fb6e8647b3744 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Tue, 18 May 2021 09:16:22 +0200 Subject: [PATCH 081/114] view main decoration, sliders ticsk, T2,T3 swapped, potis sign --- radio/src/gui/colorlcd/layouts/sliders.cpp | 25 +++++++++---------- .../src/gui/colorlcd/view_main_decoration.cpp | 4 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/sliders.cpp b/radio/src/gui/colorlcd/layouts/sliders.cpp index 08a9fcc8c..54dc081ac 100644 --- a/radio/src/gui/colorlcd/layouts/sliders.cpp +++ b/radio/src/gui/colorlcd/layouts/sliders.cpp @@ -35,7 +35,7 @@ void MainViewHorizontalSlider::paint(BitmapBuffer * dc) } // The square - x = width() - TRIM_SQUARE_SIZE - divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); + x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); } @@ -58,19 +58,18 @@ void MainView6POS::paint(BitmapBuffer * dc) void MainViewVerticalSlider::paint(BitmapBuffer * dc) { - uint8_t slidersTick = height() / 5; - // The ticks - int delta = (height() - TRIM_SQUARE_SIZE) / slidersTick; - coord_t y = TRIM_SQUARE_SIZE / 2; - for (uint8_t i = 0; i <= slidersTick; i++) { - if (i == 0 || i == slidersTick / 2 || i == slidersTick) - dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR); - else - dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR); - y += delta; - } + // The ticks + int delta = (height() - TRIM_SQUARE_SIZE) / SLIDER_TICKS_COUNT; + coord_t y = TRIM_SQUARE_SIZE / 2; + for (uint8_t i = 0; i <= SLIDER_TICKS_COUNT; i++) { + if (i == 0 || i == SLIDER_TICKS_COUNT / 2 || i == SLIDER_TICKS_COUNT) + dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR); + else + dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR); + y += delta; + } // The square - y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); + y = divRoundClosest((height() - TRIM_SQUARE_SIZE) * (-value + RESX), 2 * RESX); drawTrimSquare(dc, 0, y, TRIM_BGCOLOR); } diff --git a/radio/src/gui/colorlcd/view_main_decoration.cpp b/radio/src/gui/colorlcd/view_main_decoration.cpp index 19684d928..16bc8cdfd 100644 --- a/radio/src/gui/colorlcd/view_main_decoration.cpp +++ b/radio/src/gui/colorlcd/view_main_decoration.cpp @@ -300,8 +300,8 @@ void ViewMainDecoration::createTrims() VERTICAL_SLIDERS_HEIGHT }; - trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 2); - trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 1); + trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); + trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); } void ViewMainDecoration::createFlightMode() From 5b4943e8764b8cd4671f8bd049dd9c68e1b5b403 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Wed, 19 May 2021 19:13:10 +0200 Subject: [PATCH 082/114] it's for all users of gps --- radio/src/gui/colorlcd/layouts/topbar_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp index 4e12fe4ba..3fe2ce672 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp @@ -32,7 +32,7 @@ TopbarImpl::TopbarImpl(Window * parent) : unsigned int TopbarImpl::getZonesCount() const { -#if defined(TELEMETRY_MAVLINK) && defined(INTERNAL_GPS) +#if defined(INTERNAL_GPS) return MAX_TOPBAR_ZONES-1; #endif return MAX_TOPBAR_ZONES; @@ -91,7 +91,7 @@ void TopbarImpl::paint(BitmapBuffer * dc) getTimerString(str, getValue(MIXSRC_TX_TIME)); dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | MENU_COLOR); -#if defined(TELEMETRY_MAVLINK) && defined(INTERNAL_GPS) +#if defined(INTERNAL_GPS) if (gpsData.fix) { char s[10]; sprintf(s, "%d", gpsData.numSat); From c0198a19a3981ab860c20a65b5c8894d4d5e7665 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 21 May 2021 21:59:57 +0200 Subject: [PATCH 083/114] Fix TW translation --- radio/src/translations/tw.h.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/tw.h.txt b/radio/src/translations/tw.h.txt index efd6ad04e..4e6ad979c 100644 --- a/radio/src/translations/tw.h.txt +++ b/radio/src/translations/tw.h.txt @@ -199,9 +199,10 @@ #endif #define TR_SF_SCREENSHOT "截屏\0 " +#define TR_SF_RACING_MODE "RacingMode" #define TR_SF_RESERVE "[保留]\0 " -#define TR_VFSWFUNC TR_SF_SAFETY "教練\0 " "搖桿值存儲到微調" "重啟\0 " "設置\0 " TR_ADJUST_GVAR "音量\0 " "設置失控保護\0 " "測距模式\0 " "模塊對頻\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 "背光\0 " TR_SF_SCREENSHOT TR_SF_TEST +#define TR_VFSWFUNC TR_SF_SAFETY "教練\0 " "搖桿值存儲到微調" "重啟\0 " "設置\0 " TR_ADJUST_GVAR "音量\0 " "設置失控保護\0 " "測距模式\0 " "模塊對頻\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 "背光\0 " TR_SF_SCREENSHOT TR_SF_RACING_MODE TR_SF_TEST #define LEN_VFSWRESET TR("\004", "\010") @@ -1163,6 +1164,7 @@ #define TR_JITTER_FILTER "類比輸入濾波" #define TR_RTC_CHECK TR("Check RTC", "檢查時間驅動電池電壓") #define TR_AUTH_FAILURE "驗證失敗" +#define TR_RACING_MODE "Racing mode" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" @@ -1321,4 +1323,4 @@ #define ZSTR_SERVO_STATUS "SrvS" #define ZSTR_LOSS "Loss" #define ZSTR_SPEED "Spd " -#define ZSTR_FLOW "Flow" \ No newline at end of file +#define ZSTR_FLOW "Flow" From a33b114ae4168f58fa8cb4b1d9069aadbd1b46b8 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 21 May 2021 21:59:45 +0200 Subject: [PATCH 084/114] Shrink fonts --- CMakeLists.txt | 1 + cmake/Bitmaps.cmake | 2 +- radio/src/gui/colorlcd/fonts.cpp | 43 ++++++++++++++++++++++++-------- radio/src/thirdparty/libopenui | 2 +- tools/build-font-bitmap.py | 1 + 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ccd04d375..80c365e64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ set(RADIO_SRC_DIR ${RADIO_DIRECTORY}/src) set(COMPANION_SRC_DIRECTORY ${PROJECT_SOURCE_DIR}/companion/src) set(SIMU_SRC_DIRECTORY ${COMPANION_SRC_DIRECTORY}/simulation) set(TOOLS_DIR ${PROJECT_SOURCE_DIR}/tools) +set(UTILS_DIR ${PROJECT_SOURCE_DIR}/radio/util) set(LIBOPENUI_TOOLS_DIR ${RADIO_SRC_DIR}/thirdparty/libopenui/tools) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) diff --git a/cmake/Bitmaps.cmake b/cmake/Bitmaps.cmake index 39ec10a9e..48b16f5a9 100644 --- a/cmake/Bitmaps.cmake +++ b/cmake/Bitmaps.cmake @@ -40,7 +40,7 @@ macro(add_truetype_font_target name size subset effect args) add_custom_command( OUTPUT ${target}.png ${target}.specs ${target}.lbm COMMAND ${PYTHON_EXECUTABLE} ${TOOLS_DIR}/build-font-bitmap.py --subset ${subset} --size ${size} --font ${font} --output ${target} - COMMAND ${PYTHON_EXECUTABLE} ${LIBOPENUI_TOOLS_DIR}/encode-bitmap.py --format 8bits --rle --size-format 2 ${args} ${target}.png ${target}.lbm + COMMAND ${PYTHON_EXECUTABLE} ${UTILS_DIR}/bin2lbm.py ${target}.png ${target}.lbm DEPENDS ${TOOLS_DIR}/build-font-bitmap.py ${TOOLS_DIR}/charset.py ${LIBOPENUI_TOOLS_DIR}/encode-bitmap.py ${RADIO_SRC_DIR}/translations/cn.h.txt ${RADIO_SRC_DIR}/fonts/extra_${size}px.png ) add_custom_target(truetype_font_${name} DEPENDS ${target}.png ${target}.specs) diff --git a/radio/src/gui/colorlcd/fonts.cpp b/radio/src/gui/colorlcd/fonts.cpp index 8468a74aa..54cf25236 100644 --- a/radio/src/gui/colorlcd/fonts.cpp +++ b/radio/src/gui/colorlcd/fonts.cpp @@ -131,8 +131,8 @@ const unsigned char font_xxl[] = { const uint16_t fontCharactersTable[FONTS_COUNT] = { sizeof(font_std_en_specs)/2-2 }; const uint16_t * const fontspecsTable[FONTS_COUNT] = { font_std_en_specs }; const uint8_t * fontsTable[FONTS_COUNT] = { font_std_en }; +const int fontsSizeTable[FONTS_COUNT] = { sizeof(font_std_en) }; #else - // -2 for: overall length and last boundary const uint16_t fontCharactersTable[FONTS_COUNT] = { sizeof(font_std_specs)/2-2, sizeof(font_bold_specs)/2-2, sizeof(font_xxs_specs)/2-2, @@ -146,21 +146,42 @@ const uint16_t *const fontspecsTable[FONTS_COUNT] = { const uint8_t *fontsTable[FONTS_COUNT] = { font_std, font_bold, font_xxs, font_xs, font_l, font_xl, font_xxl }; +const int fontsSizeTable[FONTS_COUNT] = { + sizeof(font_std), sizeof(font_bold), sizeof(font_xxs), + sizeof(font_xs), sizeof(font_l), sizeof(font_xl), + sizeof(font_xxl) +}; #endif -uint8_t * decompressFont(const uint8_t * font) +uint8_t * decompressFont(const uint8_t * font, unsigned len) { - uint16_t width = *((uint16_t *)font); - uint16_t height = *(((uint16_t *)font)+1); + int width = 0; + int height = 0; + + uint8_t* raw_font = BitmapBuffer::loadFont(font, len, width, height); + if (!raw_font) { + return nullptr; + } size_t font_size = width * height; - uint8_t * dec_buf = (uint8_t *)malloc(font_size + 4); + uint8_t * buf = (uint8_t *)malloc(font_size + 4); - // copy width / height - memcpy(dec_buf, font, 4); + ((uint16_t*)buf)[0] = (uint16_t)width; + ((uint16_t*)buf)[1] = (uint16_t)height; - RLEBitmap::decode(dec_buf+4, font_size, font+4); - return dec_buf; +#if defined(LCD_VERTICAL_INVERT) + uint8_t* src = raw_font + font_size - 1; + for(uint8_t* dst = buf + 4; src >= raw_font; --src, ++dst) { + *dst = 0xFF - *src; + } +#else + uint8_t* src = raw_font; + for(uint8_t* dst = buf + 4; src != raw_font + font_size; ++src, ++dst) { + *dst = 0xFF - *src; + } +#endif + + return buf; } void loadFonts() @@ -170,10 +191,10 @@ void loadFonts() return; #if defined(BOOT) - fontsTable[0] = decompressFont(fontsTable[0]); + fontsTable[0] = decompressFont(fontsTable[0], fontsSizeTable[0]); #else for (int i = 0; i < FONTS_COUNT; i++) { - fontsTable[i] = decompressFont(fontsTable[i]); + fontsTable[i] = decompressFont(fontsTable[i], fontsSizeTable[i]); } #endif diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 1bc7de6c4..5fa5a379e 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 1bc7de6c42c0a9e2284b55ae551a4d1245241bdb +Subproject commit 5fa5a379eeba432ea4aa5f154293552ebddfa3ea diff --git a/tools/build-font-bitmap.py b/tools/build-font-bitmap.py index d3176834e..336445dc7 100755 --- a/tools/build-font-bitmap.py +++ b/tools/build-font-bitmap.py @@ -123,6 +123,7 @@ class FontBitmap: image = image.crop((0, top, width - 1, bottom)) coords.insert(0, bottom - top + 1) + image = image.convert("L") image.save(filename + ".png") if generate_coords_file: with open(filename + ".specs", "w") as f: From e6b9620db83259c07b933305eab9288f8860c7cd Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 15 May 2021 01:21:12 +0200 Subject: [PATCH 085/114] Moved libopenui submodule to EdgeTX --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 7458ffe95..9ce4543c5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "libopenui"] path = radio/src/thirdparty/libopenui - url = https://github.com/opentx/libopenui.git + url = https://github.com/EdgeTX/libopenui.git branch = master [submodule "libACCESS"] path = radio/src/thirdparty/libACCESS From 61abc46547bf6519ef90429c4a0c88148ac41f9a Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 22 May 2021 08:46:37 +0200 Subject: [PATCH 086/114] Catch gestures outside widgets to be setup resolves #18 --- radio/src/gui/colorlcd/screen_setup.cpp | 10 +++++++++- radio/src/gui/colorlcd/topbar.cpp | 16 ++++++++++++++++ radio/src/gui/colorlcd/topbar.h | 6 ++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 856eaffa0..693e3628e 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -206,11 +206,19 @@ class SetupWidgetsPage: public FormWindow } #if defined(HARDWARE_TOUCH) - bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override + bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, + coord_t slideX, coord_t slideY) override { // prevent screen sliding when setting up widgets return true; } + + bool onTouchEnd(coord_t x, coord_t y) override + { + if (FormWindow::onTouchEnd(x, y)) return true; + + return true; + } #endif #if defined(HARDWARE_KEYS) diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index 172f4f9cf..5c935ec9b 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -83,3 +83,19 @@ void SetupTopBarWidgetsPage::onEvent(event_t event) } #endif +#if defined(HARDWARE_TOUCH) +bool SetupTopBarWidgetsPage::onTouchSlide(coord_t x, coord_t y, + coord_t startX, coord_t startY, + coord_t slideX, coord_t slideY) +{ + return true; +} + +bool SetupTopBarWidgetsPage::onTouchEnd(coord_t x, coord_t y) +{ + if (FormWindow::onTouchEnd(x, y)) + return true; + + return true; +} +#endif diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index d7b519b43..b20d2520f 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -59,6 +59,12 @@ class SetupTopBarWidgetsPage: public FormWindow void onEvent(event_t event) override; #endif +#if defined(HARDWARE_TOUCH) + bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, + coord_t slideX, coord_t slideY) override; + bool onTouchEnd(coord_t x, coord_t y) override; +#endif + protected: ScreenMenu* menu; unsigned savedView = 0; From 87ea446718b6f215857c3b9c50fab9fe62475a47 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 22 May 2021 14:27:10 +0200 Subject: [PATCH 087/114] Update libopenui Applies proper clipping to BitmapBuffer::invertRect() --- radio/src/thirdparty/libopenui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 5fa5a379e..9067eaad5 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 5fa5a379eeba432ea4aa5f154293552ebddfa3ea +Subproject commit 9067eaad591456503ff977435bf2a9dc1b5a9201 From ec87e40c56035068d7bea63e74d9581c1abb5710 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 22 May 2021 16:59:34 +0200 Subject: [PATCH 088/114] Added line clipping unit tests & updated libopenui with Liang-Barsky line clipping --- radio/src/tests/lcd_480x272.cpp | 17 +++++++++++++++++ radio/src/tests/lines_480x272.png | Bin 0 -> 4962 bytes radio/src/thirdparty/libopenui | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 radio/src/tests/lines_480x272.png diff --git a/radio/src/tests/lcd_480x272.cpp b/radio/src/tests/lcd_480x272.cpp index bd617eab1..867828f1c 100644 --- a/radio/src/tests/lcd_480x272.cpp +++ b/radio/src/tests/lcd_480x272.cpp @@ -90,6 +90,23 @@ bool checkScreenshot_colorlcd(const BitmapBuffer* dc, const char* test) return true; } +TEST(Lcd_colorlcd, lines) +{ + BitmapBuffer dc(BMP_RGB565, LCD_W, LCD_H); + dc.clear(DEFAULT_BGCOLOR); + dc.setClippingRect(50, 400, 50, 230); + + for (int x = 10; x <= 100; x += 10) { + dc.drawLine(x, x, x + 200, x + 50, 0xF0, DEFAULT_COLOR); + } + + for (int x = 200; x >= 100; x -= 10) { + dc.drawLine(x, x, x - 50, x + 100, 0xF0, DEFAULT_COLOR); + } + + dc.clearClippingRect(); + EXPECT_TRUE(checkScreenshot_colorlcd(&dc, "lines")); +} TEST(Lcd_colorlcd, vline) { diff --git a/radio/src/tests/lines_480x272.png b/radio/src/tests/lines_480x272.png new file mode 100644 index 0000000000000000000000000000000000000000..86c6ceb11dbe0e82b0f6949e6ad8dbe58e8316f8 GIT binary patch literal 4962 zcmeHLdr(tX8c)&?B7_*J#Slp#iWJ+84RU=^z(6nw6x>Lu);P30s$P7RDt0l8E)fh` zA`hXhO|4)rShWjvF|{s58$ey%V#x)nEv-{TSAvWktm_(}X&ELK3WE-9VGVh_N75uXD)L*dGASggmVCnqIj6uy-E z)6F5@&PZ{9i59sZMRGeKnNG=-5)OWpL~}L%PP%rUXDy(7T;!AoFNDdtnq>~^>~eyu zQD?ye7J29|UZ{(+Z9Z{UzGs!?EVDaBe<7cec^oEyRj}6+!UVuE5&;&oo#f+3RUn5_ zIBC~Rk8`vjn8+Z!{;jgK$Cy|JiCG2PbBW+e&+B1e6U^mRFy`2CRvr@w!PSj3(LpZK z7|ghah2%kA;P--Xrjl}W$nZUv; zEz8k*Z7-9fphP5=4vN!GGkNILS;(A~SsPSdfdsJA6SEMcFEN>*g;!c*@HZ#$EyC9< z5to_jHprD=F5(=sR(J(sF|($-A$^8%JqBN>fj9h}VO&kwTuseQPpt$!A~Be&x$0S4 zg2pyNtq4QzEA^i__IYEN*zL-E%fveFOQGRC2wH*3OdrO4^%094C&{LYj1o} z4ZPu3@=dh7f_^2|(^Dm2)1N%FK;Y}|E25|D&0F~cdBWX~U2^;A!sPyG2gGji`EwuN1yHxa0K+u?7Ao_Px+ZYwWeiK$S6 z>3F8WL`SXGW$Z-8o51*2s4XrF{yFAn*1yVCBU?8XbXkRvV)+)$bEjz$3l-9O)g+in#9R53rAIWvS~_Zk?f}qvPoX);e(v`O^fmKQ z^AyiVofDXT24N1b*8_v%FnJ4x*P;zBgO#m#e`1Pw?b6;qFOO^O&bR#}k;|2>UF%%O z7MW3b+9pH6f-%1?YldrQmYqLzgXXLTuWHozFXm(yl#C14Be1vik$k}#v^%%+4+Sk1 z@yQ#ID}IHU)r?A&tefoVxkWHFT>_Ya)+-KAIsFgPqWa&WmoxZ79>ndE0JZ_<6+7)? zz0_TG{IhlFXGH2EO0iluP|?f_Mnx@dLq78Mu1BE&5QBMc_A~;Dq3iX+i;#>ShUh*S zN`_tDj-1?#`tQ&}4d`DB5idZYs3S6Q(;!mhp)uC0JnbRHl#K*862>{lc;ZAee9B7T=2>E-C=BAYLlQ9et50s(w*9bVDKYJ##k@5-M9QY5%A)&Us zgK-`{$+24kIaeuzrLDn=20#KBXHY%<#NHcMqh()uAiqgKrarE!HmZ#PICMIS@oMEEyGlZjW*g{VR9R&n;JI=t~bJo*Nx}9d$J@m724WgX=z6akt z;{hEtMiuI_({Ib1OJh1OMtKHEIwfZzBi2Sq2q}iU3zE(etNa7lmG&e?nTZgP<6){ z-${R)ID|6O)`Xbg#if-I)ey}Aywxi^3nyBOERCS#sye*&yyPACRt#*7psjuK)K7;K zcBRUCrf)%1$^zUsB6xY*hREU6QyH^R#;D{5Ag$0yC>G7*YA%2y#3q<~N9%(%?{>S+ zE<~Z`Kyh?<)Dh#3fRn1;^MRxlP0 z?bGLHnvkg)ziYU?`iS1zk@2j};GP0{8E5Jz#WKZvW#qkJH0z3{J_&JwY`G&3;;4W3 z-fc2{GCqe&;XHh|yYrb3Eoka~b_oVtO(}KI_!Ug(-M7g>8LnOB{!7`2w%|6tz^y@! zPn`jR?mV?)%K;#w9=b!bsF>ahVf9P+Yx5-l-4AZidV5fzC>vYrO_w zcR_7hv^ByecPP1(+>T4h^-`o6Zm+xEhbo}nfN4a6WIW{}JKm4w?$#uRCARog$4lRM zL%X3POu!ykC9?U*?F|dkuSs^Ehc>wf0i2pl9W2ssvjgpjguqZvDrK702Tm8ww&jRc z!{%g|t>;DJs|siKcSR9rOQ=n5eM@e$JHs!LZ%CosNIfGl3##Q&RSGKdQ6Jagm;WBy zT9|9o!x5bw%IQ2(EX!<*vTnrE@)rV5I#|DiZ<$@E-S7<-J2ybhY;;i5H!;fSXYw0V zm$XEd_Ao^ULiO;fgv#d4nu@#hwjOFhI}D23B5}Nr%Q+Ze>j}PY8>QP~(EL_j0evkn z5;UWyL0@O5t12Ouce|plM!j~@tMzYwaq^?hvg5)c+c6|?fKj;)>L5%`7*H@D^7w*F9HZ^W*#07! zVhQXO!et}INl%Q&;lsmQz5@F}HC6yy9->H*(AEKQF2qmO-V7VJlP;Qr?5F@8qX(UL zG^^{hlTs>!<^Vhc(7HUh>M+T}6+!eg;vIEvh;DfWqFl(gG(#<}V@U#!pQ&r8g;V_S z3rW~Ct~u4;Sa3ahy{)2ov+UeeFcFxTMNV{3<#QY3R_Tn#V>IFi%xZYR ztqH{1Bi|%p4s^Cb`jI>Le9ucJEkQh-ZxX0YXyheEXylUYeJ=6~cV)mE+@qdnE-#+3 zK;GH}t!%gkMbVGP9M5BJLu0OZkidW7_|!I^xYj$t^Vk;X8ifebcAD+m_lAdL4x1L& z_L2|@8!I%p%3wn5@ydHWTq*z-2 OSjh_(CN(E!ZT%Mm8iQK^ literal 0 HcmV?d00001 diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 9067eaad5..fdf289100 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 9067eaad591456503ff977435bf2a9dc1b5a9201 +Subproject commit fdf289100013928330c08be5c74a05419e836ec5 From 95aa02ceddf0b5633f0c260df1c459ae74b8faef Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 22 May 2021 12:42:20 +0200 Subject: [PATCH 089/114] Switch the framebuffer address rather than using 2 LTDC layers --- radio/src/gui/colorlcd/draw_functions.cpp | 4 +- radio/src/main.cpp | 1 - .../targets/horus/bootloader/boot_menu.cpp | 6 -- radio/src/targets/horus/lcd_driver.cpp | 96 +++++++------------ radio/src/targets/simu/simpgmspace.cpp | 18 ---- radio/src/targets/simu/simulcd.cpp | 6 ++ radio/src/thirdparty/libopenui | 2 +- 7 files changed, 40 insertions(+), 93 deletions(-) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index f79c9b0dd..8b028ea6f 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -76,7 +76,6 @@ void drawValueOrGVar(BitmapBuffer * dc, coord_t x, coord_t y, gvar_t value, gvar void drawSleepBitmap() { - lcdNextLayer(); lcd->reset(); lcd->clear(); @@ -97,7 +96,6 @@ void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char static const BitmapBuffer * shutdown = BitmapBuffer::loadBitmap(OpenTxTheme::instance()->getFilePath("shutdown.bmp")); - lcdNextLayer(); lcd->reset(); if (shutdown) { @@ -431,4 +429,4 @@ void drawHexNumber(BitmapBuffer * dc, coord_t x, coord_t y, uint32_t val, LcdFla c += (c >= 10 ? 'A' - 10 : '0'); x = dc->drawSizedText(x, y, &c, 1, flags); } -} \ No newline at end of file +} diff --git a/radio/src/main.cpp b/radio/src/main.cpp index dfc742c5a..66610cf3e 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -475,7 +475,6 @@ void perMain() if (usbPlugged() && getSelectedUsbMode() == USB_MASS_STORAGE_MODE) { #if defined(LIBOPENUI) // draw some image showing USB - lcdNextLayer(); lcd->reset(); OpenTxTheme::instance()->drawUsbPluggedScreen(lcd); lcdRefresh(); diff --git a/radio/src/targets/horus/bootloader/boot_menu.cpp b/radio/src/targets/horus/bootloader/boot_menu.cpp index 310b5fbb7..a9a0e5aa3 100644 --- a/radio/src/targets/horus/bootloader/boot_menu.cpp +++ b/radio/src/targets/horus/bootloader/boot_menu.cpp @@ -95,12 +95,6 @@ static void bootloaderDrawBackground() void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) { - // shows current layer on LCD - lcdRefresh(); - - // swap back & front buffers - lcdNextLayer(); - bootloaderDrawBackground(); if (st == ST_START) { diff --git a/radio/src/targets/horus/lcd_driver.cpp b/radio/src/targets/horus/lcd_driver.cpp index 6275ca903..cf5e8755d 100644 --- a/radio/src/targets/horus/lcd_driver.cpp +++ b/radio/src/targets/horus/lcd_driver.cpp @@ -51,7 +51,9 @@ uint8_t currentLayer = LCD_FIRST_LAYER; BitmapBuffer lcdBuffer1(BMP_RGB565, LCD_W, LCD_H, (uint16_t *)LCD_FIRST_FRAME_BUFFER); BitmapBuffer lcdBuffer2(BMP_RGB565, LCD_W, LCD_H, (uint16_t *)LCD_SECOND_FRAME_BUFFER); -BitmapBuffer * lcd = &lcdBuffer1; + +BitmapBuffer * lcdFront = &lcdBuffer1; +BitmapBuffer * lcd = &lcdBuffer2; inline void LCD_NRST_LOW() { @@ -63,11 +65,6 @@ inline void LCD_NRST_HIGH() LCD_GPIO_NRST->BSRRL = LCD_GPIO_PIN_NRST; } -inline bool coordsWithinScreen(coord_t x, coord_t y, coord_t w, coord_t h) -{ - return x >= 0 && y >= 0 && x + w <= LCD_W && y + h <= LCD_H; -} - static void LCD_AF_GPIOConfig() { GPIO_InitTypeDef GPIO_InitStructure; @@ -262,8 +259,10 @@ void LCD_LayerInit() /* Pixel Format configuration*/ LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_RGB565; + /* Alpha constant (255 totally opaque) */ LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255; + /* Default Color configuration (configure A,R,G,B component values) */ LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0; LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0; @@ -294,26 +293,15 @@ void LCD_LayerInit() /* Initialize LTDC layer 1 */ LTDC_LayerInit(LTDC_Layer1, <DC_Layer_InitStruct); - /* Configure Layer 2 */ - LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA; - LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA; - - /* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */ - LTDC_Layer_InitStruct.LTDC_CFBStartAdress = (uint32_t)LCD_SECOND_FRAME_BUFFER; - - /* Initialize LTDC layer 2 */ - LTDC_LayerInit(LTDC_Layer2, <DC_Layer_InitStruct); - /* LTDC configuration reload */ LTDC_ReloadConfig(LTDC_IMReload); + // Enable layer and reload LTDC_LayerCmd(LTDC_Layer1, ENABLE); - LTDC_LayerCmd(LTDC_Layer2, ENABLE); - LTDC_ReloadConfig(LTDC_IMReload); /* dithering activation */ - LTDC_DitherCmd(ENABLE); + LTDC_DitherCmd(ENABLE); // ???? } void LCD_Init(void) @@ -331,49 +319,28 @@ void LCD_Init(void) void LCD_SetLayer(uint32_t layer) { if (layer == LCD_FIRST_LAYER) { - lcd = &lcdBuffer1; + lcdFront = &lcdBuffer1; + lcd = &lcdBuffer2; } else { - lcd = &lcdBuffer2; + lcdFront = &lcdBuffer2; + lcd = &lcdBuffer1; } currentLayer = layer; } -/** - * @brief Configure the transparency. - * @param transparency: specifies the transparency, - * This parameter must range from 0x00 to 0xFF. - * @retval None - */ -void LCD_SetTransparency(uint8_t transparency) -{ - if (currentLayer == LCD_FIRST_LAYER) { - LTDC_LayerAlpha(LTDC_Layer1, transparency); - } - else { - LTDC_LayerAlpha(LTDC_Layer2, transparency); - } - LTDC_ReloadConfig(LTDC_IMReload); -} - void lcdInit() { - /* Initialize the LCD */ + // Clear buffers first + memset(LCD_FIRST_FRAME_BUFFER, 0, sizeof(LCD_FIRST_FRAME_BUFFER)); + memset(LCD_SECOND_FRAME_BUFFER, 0, sizeof(LCD_SECOND_FRAME_BUFFER)); + + // Initialize the LCD LCD_Init(); LCD_LayerInit(); - /* Enable LCD display */ + // Enable LCD display LTDC_Cmd(ENABLE); - - /* Set Background layer */ - memset(LCD_FIRST_FRAME_BUFFER, 0, sizeof(LCD_FIRST_FRAME_BUFFER)); - LCD_SetLayer(LCD_FIRST_LAYER); - LCD_SetTransparency(0); - - /* Set Foreground layer */ - memset(LCD_SECOND_FRAME_BUFFER, 0, sizeof(LCD_SECOND_FRAME_BUFFER)); - LCD_SetLayer(LCD_SECOND_LAYER); - LCD_SetTransparency(255); } void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) @@ -637,25 +604,26 @@ uint16_t* lcdGetScratchBuffer() return (uint16_t*)LCD_SCRATCH_FRAME_BUFFER; } -void lcdRefresh() -{ - if (currentLayer == LCD_FIRST_LAYER) { - LTDC_LayerAlpha(LTDC_Layer1, 255); - LTDC_LayerAlpha(LTDC_Layer2, 0); - } - else { - LTDC_LayerAlpha(LTDC_Layer1, 0); - LTDC_LayerAlpha(LTDC_Layer2, 255); - } - LTDC_ReloadConfig(LTDC_IMReload); -} - -void lcdNextLayer() +static void lcdSwitchLayers() { if (currentLayer == LCD_FIRST_LAYER) { + LTDC_Layer1->CFBAR = (uint32_t)LCD_SECOND_FRAME_BUFFER; LCD_SetLayer(LCD_SECOND_LAYER); } else { + LTDC_Layer1->CFBAR = (uint32_t)LCD_FIRST_FRAME_BUFFER; LCD_SetLayer(LCD_FIRST_LAYER); } + + // reload shadow registers on vertical blank + LTDC->SRCR = LTDC_SRCR_VBR; + + // wait for reload + // TODO: replace through some smarter mechanism without busy wait + while ((LTDC->CDSR & LTDC_CDSR_VSYNCS) == 0); +} + +void lcdRefresh() +{ + lcdSwitchLayers(); } diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 2b96aa06d..c06cc7ce6 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -89,24 +89,6 @@ Adc Adc0; FATFS g_FATFS_Obj; -void lcdInit() -{ -} - -void lcdCopy(void * dest, void * src) -{ - -} - -void lcdNextLayer() -{ - -} - -void toplcdOff() -{ -} - uint64_t simuTimerMicros(void) { #if SIMPGMSPC_USE_QT diff --git a/radio/src/targets/simu/simulcd.cpp b/radio/src/targets/simu/simulcd.cpp index c92ace74d..754743f6c 100644 --- a/radio/src/targets/simu/simulcd.cpp +++ b/radio/src/targets/simu/simulcd.cpp @@ -28,6 +28,12 @@ pixel_t scratchBuf[DISPLAY_BUFFER_SIZE]; BitmapBuffer _lcd(BMP_RGB565, LCD_W, LCD_H, displayBuf); BitmapBuffer * lcd = &_lcd; +BitmapBuffer * lcdFront = &_lcd; + +void lcdInit() {} +void lcdCopy(void *dest, void *src) {} +void lcdNextLayer() {} +void toplcdOff() {} uint16_t * lcdGetScratchBuffer() { diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index fdf289100..1c558559e 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit fdf289100013928330c08be5c74a05419e836ec5 +Subproject commit 1c558559eba805233b1876c43dd8ffb46673191e From fbc765d0ced9ba2ea38ae538283b442193487984 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Sat, 22 May 2021 14:29:59 +0200 Subject: [PATCH 090/114] integer arithmetic is not floating point arithmetic :) --- radio/src/gui/colorlcd/layouts/sliders.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/sliders.cpp b/radio/src/gui/colorlcd/layouts/sliders.cpp index 54dc081ac..0a31172b1 100644 --- a/radio/src/gui/colorlcd/layouts/sliders.cpp +++ b/radio/src/gui/colorlcd/layouts/sliders.cpp @@ -58,16 +58,17 @@ void MainView6POS::paint(BitmapBuffer * dc) void MainViewVerticalSlider::paint(BitmapBuffer * dc) { - // The ticks - int delta = (height() - TRIM_SQUARE_SIZE) / SLIDER_TICKS_COUNT; - coord_t y = TRIM_SQUARE_SIZE / 2; - for (uint8_t i = 0; i <= SLIDER_TICKS_COUNT; i++) { - if (i == 0 || i == SLIDER_TICKS_COUNT / 2 || i == SLIDER_TICKS_COUNT) - dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR); - else - dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR); - y += delta; - } + // The ticks + int delta = 4; + int sliderTicksCount = (height() - TRIM_SQUARE_SIZE) / delta; + coord_t y = TRIM_SQUARE_SIZE / 2; + for (uint8_t i = 0; i <= sliderTicksCount; i++) { + if (i == 0 || i == sliderTicksCount / 2 || i == sliderTicksCount) + dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR); + else + dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR); + y += delta; + } // The square y = divRoundClosest((height() - TRIM_SQUARE_SIZE) * (-value + RESX), 2 * RESX); From fae79a5785bec8deb4a2f3c04a8a48a1ba3a1f3f Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 09:45:23 +0200 Subject: [PATCH 091/114] Do not forward main menu events to parent window --- radio/src/gui/colorlcd/view_main_menu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/gui/colorlcd/view_main_menu.h b/radio/src/gui/colorlcd/view_main_menu.h index b9045dc9c..5fc8c1c20 100644 --- a/radio/src/gui/colorlcd/view_main_menu.h +++ b/radio/src/gui/colorlcd/view_main_menu.h @@ -55,7 +55,6 @@ public: parent->deleteLater(); return; } - Window::onEvent(event); } #endif From aff9b3f1e4b091f62fb3d8c36195721f79e034d9 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 10:06:00 +0200 Subject: [PATCH 092/114] Fixed refresh in main view menu --- radio/src/gui/colorlcd/select_fab_carousel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/select_fab_carousel.cpp b/radio/src/gui/colorlcd/select_fab_carousel.cpp index f1abe1d3c..61869d711 100644 --- a/radio/src/gui/colorlcd/select_fab_carousel.cpp +++ b/radio/src/gui/colorlcd/select_fab_carousel.cpp @@ -21,7 +21,7 @@ #include "select_fab_carousel.h" SelectFabCarousel::SelectFabCarousel(Window* parent): - FormGroup(parent, {}, OPAQUE | FORM_FORWARD_FOCUS | NO_SCROLLBAR) + FormGroup(parent, {}, FORM_FORWARD_FOCUS | NO_SCROLLBAR) { setPageWidth(FAB_BUTTON_SIZE + SELECT_BUTTON_BORDER); setHeight(FAB_BUTTON_SIZE + 2 * PAGE_LINE_HEIGHT + SELECT_BUTTON_BORDER / 2); From d44e1005f1fcd5baa5eb183b866b5a2c6a9c3034 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 11:52:19 +0200 Subject: [PATCH 093/114] Added double buffering simulation to "simu" --- radio/src/gui/colorlcd/lcd.h | 1 - radio/src/simu.cpp | 13 ++- radio/src/targets/simu/simpgmspace.cpp | 45 -------- radio/src/targets/simu/simulcd.cpp | 149 ++++++++++++++++++------- radio/src/targets/simu/simulcd.h | 1 + 5 files changed, 123 insertions(+), 86 deletions(-) diff --git a/radio/src/gui/colorlcd/lcd.h b/radio/src/gui/colorlcd/lcd.h index 18f6e23a3..090698b0b 100644 --- a/radio/src/gui/colorlcd/lcd.h +++ b/radio/src/gui/colorlcd/lcd.h @@ -39,7 +39,6 @@ #define DISPLAY_BUFFER_SIZE (DISPLAY_PIXELS_COUNT) extern coord_t lcdNextPos; -void lcdNextLayer(); inline void lcdClear() { diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index adbe4788a..2ba72bef6 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -86,7 +86,7 @@ FXIMPLEMENT(OpenTxSim, FXMainWindow, OpenTxSimMap, ARRAYNUMBER(OpenTxSimMap)) OpenTxSim::OpenTxSim(FXApp* a): FXMainWindow(a, "OpenTX Simu", nullptr, nullptr, DECOR_ALL, 20, 90, 0, 0) { - memset(displayBuf, 0, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); + lcdInit(); bmp = new FXPPMImage(getApp(), nullptr, IMAGE_OWNED|IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP, W2, H2); #if defined(SIMU_AUDIO) @@ -500,8 +500,17 @@ void OpenTxSim::setPixel(int x, int y, FXColor color) void OpenTxSim::refreshDisplay() { - if (simuLcdRefresh) { + static bool lightEnabled = (bool)isBacklightEnabled(); + + if ((bool(isBacklightEnabled()) != lightEnabled) || simuLcdRefresh) { + simuLcdRefresh = false; + + if (bool(isBacklightEnabled()) != lightEnabled) { + lightEnabled = (bool)isBacklightEnabled(); + TRACE("backlight %s", lightEnabled ? "ON" : "OFF"); + } + FXColor offColor = isBacklightEnabled() ? BL_COLOR : FXRGB(200, 200, 200); #if LCD_DEPTH == 1 FXColor onColor = FXRGB(0, 0, 0); diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index c06cc7ce6..eb032971b 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -410,40 +410,12 @@ void stopAudioThread() } #endif // #if defined(SIMU_AUDIO) -bool simuLcdRefresh = true; -pixel_t simuLcdBuf[DISPLAY_BUFFER_SIZE]; - #if !defined(COLORLCD) void lcdSetRefVolt(uint8_t val) { } #endif -#if defined(PCBTARANIS) -void lcdOff() -{ -} -#endif - -void lcdRefresh() -{ - static bool lightEnabled = (bool)isBacklightEnabled(); - - if (bool(isBacklightEnabled()) != lightEnabled || memcmp(simuLcdBuf, displayBuf, DISPLAY_BUFFER_SIZE * sizeof(pixel_t))) { -#if defined(LCD_VERTICAL_INVERT) - auto src = (pixel_t*)displayBuf + DISPLAY_BUFFER_SIZE - 1; - auto dst = simuLcdBuf; - auto end = dst + DISPLAY_BUFFER_SIZE; - - while (dst != end) { *(dst++) = *(src--); } -#else - memcpy(simuLcdBuf, displayBuf, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); -#endif - lightEnabled = (bool)isBacklightEnabled(); - simuLcdRefresh = true; - } -} - void telemetryPortInit(uint8_t baudrate) { } @@ -509,23 +481,6 @@ void boardInit() { } -pixel_t simuLcdBackupBuf[DISPLAY_BUFFER_SIZE]; -void lcdStoreBackupBuffer() -{ - memcpy(simuLcdBackupBuf, displayBuf, sizeof(simuLcdBackupBuf)); -} - -int lcdRestoreBackupBuffer() -{ - memcpy(displayBuf, simuLcdBackupBuf, sizeof(displayBuf)); - return 1; -} - -uint16_t* lcdGetBackupBuffer() -{ - return (uint16_t*)simuLcdBackupBuf; -} - uint32_t pwrCheck() { // TODO: ability to simulate shutdown warning for a "soft" simulator restart diff --git a/radio/src/targets/simu/simulcd.cpp b/radio/src/targets/simu/simulcd.cpp index 754743f6c..9f3a94815 100644 --- a/radio/src/targets/simu/simulcd.cpp +++ b/radio/src/targets/simu/simulcd.cpp @@ -20,41 +20,100 @@ #include "lcd.h" #include "simulcd.h" +#include #if defined(COLORLCD) -pixel_t displayBuf[DISPLAY_BUFFER_SIZE]; +pixel_t displayBuf1[DISPLAY_BUFFER_SIZE]; +pixel_t displayBuf2[DISPLAY_BUFFER_SIZE]; + pixel_t scratchBuf[DISPLAY_BUFFER_SIZE]; +pixel_t simuLcdBuf[DISPLAY_BUFFER_SIZE]; +pixel_t simuLcdBackupBuf[DISPLAY_BUFFER_SIZE]; -BitmapBuffer _lcd(BMP_RGB565, LCD_W, LCD_H, displayBuf); -BitmapBuffer * lcd = &_lcd; -BitmapBuffer * lcdFront = &_lcd; +BitmapBuffer _lcd1(BMP_RGB565, LCD_W, LCD_H, displayBuf1); +BitmapBuffer _lcd2(BMP_RGB565, LCD_W, LCD_H, displayBuf2); -void lcdInit() {} -void lcdCopy(void *dest, void *src) {} -void lcdNextLayer() {} -void toplcdOff() {} +BitmapBuffer * lcd = &_lcd1; +BitmapBuffer * lcdFront = &_lcd2; -uint16_t * lcdGetScratchBuffer() +bool simuLcdRefresh = true; + +void lcdInit() { - return static_cast(scratchBuf); + _lcd1.clear(); + _lcd2.clear(); } -void DMAFillRect(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) +void toplcdOff() {} + +#if !defined(lcdOff) +void lcdOff() {} +#endif + +void lcdRefresh() +{ + // Mark screen dirty for async refresh + simuLcdRefresh = true; + + pixel_t* lcdData = lcd->getData(); +#if defined(LCD_VERTICAL_INVERT) + auto src = lcdData + DISPLAY_BUFFER_SIZE - 1; + auto dst = simuLcdBuf; + auto end = dst + DISPLAY_BUFFER_SIZE; + + while (dst != end) { + *(dst++) = *(src--); + } +#else + memcpy(simuLcdBuf, lcdData, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); +#endif + + // Swap back & front buffers + std::swap(lcd, lcdFront); +} + +void lcdCopy(void *dest, void *src) +{ + memcpy(dest, src, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); +} + +uint16_t *lcdGetScratchBuffer() { return static_cast(scratchBuf); } + +void lcdStoreBackupBuffer() +{ + memcpy(simuLcdBackupBuf, lcd->getData(), + DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); +} + +int lcdRestoreBackupBuffer() +{ + memcpy(lcd->getData(), simuLcdBackupBuf, + DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); + return 1; +} + +uint16_t *lcdGetBackupBuffer() { return (uint16_t *)simuLcdBackupBuf; } + +void DMAFillRect(uint16_t *dest, uint16_t destw, uint16_t desth, uint16_t x, + uint16_t y, uint16_t w, uint16_t h, uint16_t color) { #if defined(LCD_VERTICAL_INVERT) x = destw - (x + w); y = desth - (y + h); #endif - for (int i=0; i> 12; - uint8_t red = ((((*q >> 8) & 0x0f) << 1) * alpha + (*p >> 11) * (0x0f-alpha)) / 0x0f; - uint8_t green = ((((*q >> 4) & 0x0f) << 2) * alpha + ((*p >> 5) & 0x3f) * (0x0f-alpha)) / 0x0f; - uint8_t blue = ((((*q >> 0) & 0x0f) << 1) * alpha + ((*p >> 0) & 0x1f) * (0x0f-alpha)) / 0x0f; + uint8_t red = + ((((*q >> 8) & 0x0f) << 1) * alpha + (*p >> 11) * (0x0f - alpha)) / + 0x0f; + uint8_t green = ((((*q >> 4) & 0x0f) << 2) * alpha + + ((*p >> 5) & 0x3f) * (0x0f - alpha)) / + 0x0f; + uint8_t blue = ((((*q >> 0) & 0x0f) << 1) * alpha + + ((*p >> 0) & 0x1f) * (0x0f - alpha)) / + 0x0f; *p = (red << 11) + (green << 5) + (blue << 0); - p++; q++; + p++; + q++; } } } // 'src' has A8/L8? // 'dest' has RGB565 -void DMACopyAlphaMask(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, const uint8_t * src, uint16_t srcw, uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h, uint16_t fg_color) +void DMACopyAlphaMask(uint16_t *dest, uint16_t destw, uint16_t desth, + uint16_t x, uint16_t y, const uint8_t *src, uint16_t srcw, + uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, + uint16_t h, uint16_t fg_color) { #if defined(LCD_VERTICAL_INVERT) x = destw - (x + w); @@ -105,25 +177,26 @@ void DMACopyAlphaMask(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t #endif RGB_SPLIT(fg_color, red, green, blue); - - for (coord_t line=0; line> 4;// convert to 4 bits (stored in 8bit for DMA) + for (coord_t line = 0; line < h; line++) { + uint16_t *p = dest + (y + line) * destw + x; + const uint8_t *q = src + (srcy + line) * srcw + srcx; + for (coord_t col = 0; col < w; col++) { + uint16_t opacity = *q >> 4; // convert to 4 bits (stored in 8bit for DMA) uint8_t bgWeight = OPACITY_MAX - opacity; RGB_SPLIT(*p, bgRed, bgGreen, bgBlue); uint16_t r = (bgRed * bgWeight + red * opacity) / OPACITY_MAX; uint16_t g = (bgGreen * bgWeight + green * opacity) / OPACITY_MAX; uint16_t b = (bgBlue * bgWeight + blue * opacity) / OPACITY_MAX; *p = RGB_JOIN(r, g, b); - p++; q++; + p++; + q++; } } } -void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format) +void DMABitmapConvert(uint16_t *dest, const uint8_t *src, uint16_t w, + uint16_t h, uint32_t format) { if (format == DMA2D_ARGB4444) { for (int row = 0; row < h; ++row) { @@ -133,10 +206,9 @@ void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t src += 4; } } - } - else { + } else { for (int row = 0; row < h; ++row) { - for(int col = 0; col < w; ++col) { + for (int col = 0; col < w; ++col) { *dest = RGB(src[1], src[2], src[3]); ++dest; src += 4; @@ -144,4 +216,5 @@ void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t } } } + #endif diff --git a/radio/src/targets/simu/simulcd.h b/radio/src/targets/simu/simulcd.h index 58205311b..9fc6733fa 100644 --- a/radio/src/targets/simu/simulcd.h +++ b/radio/src/targets/simu/simulcd.h @@ -26,6 +26,7 @@ extern int g_snapshot_idx; extern bool simuLcdRefresh; + extern pixel_t simuLcdBuf[DISPLAY_BUFFER_SIZE]; extern pixel_t displayBuf[DISPLAY_BUFFER_SIZE]; From 05f396082a821644336c5b9849656a0c445f7074 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 15:36:37 +0200 Subject: [PATCH 094/114] Fixed "simu" for b/w radios --- radio/src/targets/simu/simulcd.cpp | 82 +++++++++++++++++++----------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/radio/src/targets/simu/simulcd.cpp b/radio/src/targets/simu/simulcd.cpp index 9f3a94815..a6ba55205 100644 --- a/radio/src/targets/simu/simulcd.cpp +++ b/radio/src/targets/simu/simulcd.cpp @@ -22,43 +22,35 @@ #include "simulcd.h" #include -#if defined(COLORLCD) - -pixel_t displayBuf1[DISPLAY_BUFFER_SIZE]; -pixel_t displayBuf2[DISPLAY_BUFFER_SIZE]; - -pixel_t scratchBuf[DISPLAY_BUFFER_SIZE]; pixel_t simuLcdBuf[DISPLAY_BUFFER_SIZE]; pixel_t simuLcdBackupBuf[DISPLAY_BUFFER_SIZE]; -BitmapBuffer _lcd1(BMP_RGB565, LCD_W, LCD_H, displayBuf1); -BitmapBuffer _lcd2(BMP_RGB565, LCD_W, LCD_H, displayBuf2); - -BitmapBuffer * lcd = &_lcd1; -BitmapBuffer * lcdFront = &_lcd2; - bool simuLcdRefresh = true; -void lcdInit() -{ - _lcd1.clear(); - _lcd2.clear(); -} - void toplcdOff() {} #if !defined(lcdOff) void lcdOff() {} #endif +void lcdCopy(void *dest, void *src) +{ + memcpy(dest, src, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); +} + +uint16_t *lcdGetBackupBuffer() { return (uint16_t *)simuLcdBackupBuf; } + +#if !defined(COLORLCD) + +void lcdInit() {} + void lcdRefresh() { // Mark screen dirty for async refresh simuLcdRefresh = true; - pixel_t* lcdData = lcd->getData(); #if defined(LCD_VERTICAL_INVERT) - auto src = lcdData + DISPLAY_BUFFER_SIZE - 1; + auto src = displayBuf + DISPLAY_BUFFER_SIZE - 1; auto dst = simuLcdBuf; auto end = dst + DISPLAY_BUFFER_SIZE; @@ -66,17 +58,21 @@ void lcdRefresh() *(dst++) = *(src--); } #else - memcpy(simuLcdBuf, lcdData, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); + memcpy(simuLcdBuf, displayBuf, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); #endif - - // Swap back & front buffers - std::swap(lcd, lcdFront); } -void lcdCopy(void *dest, void *src) -{ - memcpy(dest, src, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); -} +#else + +pixel_t displayBuf1[DISPLAY_BUFFER_SIZE]; +pixel_t displayBuf2[DISPLAY_BUFFER_SIZE]; +pixel_t scratchBuf[DISPLAY_BUFFER_SIZE]; + +BitmapBuffer _lcd1(BMP_RGB565, LCD_W, LCD_H, displayBuf1); +BitmapBuffer _lcd2(BMP_RGB565, LCD_W, LCD_H, displayBuf2); + +BitmapBuffer * lcd = &_lcd1; +BitmapBuffer * lcdFront = &_lcd2; uint16_t *lcdGetScratchBuffer() { return static_cast(scratchBuf); } @@ -93,7 +89,34 @@ int lcdRestoreBackupBuffer() return 1; } -uint16_t *lcdGetBackupBuffer() { return (uint16_t *)simuLcdBackupBuf; } +void lcdRefresh() +{ + // Mark screen dirty for async refresh + simuLcdRefresh = true; + + pixel_t* lcdData = lcd->getData(); + +#if defined(LCD_VERTICAL_INVERT) + auto src = lcdData + DISPLAY_BUFFER_SIZE - 1; + auto dst = simuLcdBuf; + auto end = dst + DISPLAY_BUFFER_SIZE; + + while (dst != end) { + *(dst++) = *(src--); + } +#else + memcpy(simuLcdBuf, lcdData, DISPLAY_BUFFER_SIZE * sizeof(pixel_t)); +#endif + + // Swap back & front buffers + std::swap(lcd, lcdFront); +} + +void lcdInit() +{ + _lcd1.clear(); + _lcd2.clear(); +} void DMAFillRect(uint16_t *dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) @@ -216,5 +239,4 @@ void DMABitmapConvert(uint16_t *dest, const uint8_t *src, uint16_t w, } } } - #endif From bfe960bee7ec4af27f61fba72504d99a2ebaa88d Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 16:03:10 +0200 Subject: [PATCH 095/114] Added missing header file for memcpy() --- radio/src/targets/simu/simulcd.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/targets/simu/simulcd.cpp b/radio/src/targets/simu/simulcd.cpp index a6ba55205..0620565b9 100644 --- a/radio/src/targets/simu/simulcd.cpp +++ b/radio/src/targets/simu/simulcd.cpp @@ -20,6 +20,7 @@ #include "lcd.h" #include "simulcd.h" +#include #include pixel_t simuLcdBuf[DISPLAY_BUFFER_SIZE]; From 20f5f3c4d12fae354bd72913eeea7feb5b3a2956 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 18:33:56 +0200 Subject: [PATCH 096/114] ltdc: wait auf LTDC_CDSR_VSYNCS raising edge after register reload command --- radio/src/targets/horus/lcd_driver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/targets/horus/lcd_driver.cpp b/radio/src/targets/horus/lcd_driver.cpp index cf5e8755d..b3df5a2a6 100644 --- a/radio/src/targets/horus/lcd_driver.cpp +++ b/radio/src/targets/horus/lcd_driver.cpp @@ -621,6 +621,7 @@ static void lcdSwitchLayers() // wait for reload // TODO: replace through some smarter mechanism without busy wait while ((LTDC->CDSR & LTDC_CDSR_VSYNCS) == 0); + while ((LTDC->CDSR & LTDC_CDSR_VSYNCS) == 1); } void lcdRefresh() From f97843c746c773af17b1b0f1399b9b7c98684623 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 19:09:42 +0200 Subject: [PATCH 097/114] bootloader: display fork version --- radio/src/stamp.cpp | 3 ++- .../src/targets/common/arm/stm32/bootloader/bin_files.cpp | 8 ++++++-- radio/src/targets/common/arm/stm32/bootloader/bin_files.h | 1 + radio/src/targets/common/arm/stm32/bootloader/boot.cpp | 1 - radio/src/targets/horus/bootloader/boot_menu.cpp | 5 ++++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index 5ed727836..ad8e716ab 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -85,7 +85,8 @@ const char * getFirmwareVersion(const char * buffer) } for (int i = 0; i < 1024; i++) { - if (memcmp(buffer + i, "edgetx-", 7) == 0) { + if ((memcmp(buffer + i, "edgetx-", 7) == 0) + || memcmp(buffer + i, "opentx-", 7) == 0) { return buffer + i; } } diff --git a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp index 49e27e33a..4498fd55d 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp @@ -121,15 +121,19 @@ void extractFirmwareVersion(VersionTag* tag) if (!vers || (vers[0] == 'n' && vers[1] == 'o')) { // "no version found" memcpy(tag->flavour, "unknown", sizeof("unknown")); tag->version = "unknown"; + return; } - // skip "opentx-" - vers += sizeof("opentx-") - 1; + tag->fork = vers; + + // skip 'edgetx-' / 'opentx-' + vers += sizeof("edgetx-") - 1; char* fl = tag->flavour; while(*vers != '-') *(fl++) = *(vers++); + // skip '-' tag->version = ++vers; } diff --git a/radio/src/targets/common/arm/stm32/bootloader/bin_files.h b/radio/src/targets/common/arm/stm32/bootloader/bin_files.h index dc9e01e2b..408cab4f9 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/bin_files.h +++ b/radio/src/targets/common/arm/stm32/bootloader/bin_files.h @@ -72,6 +72,7 @@ struct VersionTag { char flavour[8]; const char* version; + const char* fork; }; // Can be called right after openBinFile() to extract the version information diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index c75efe9fe..417d32cf2 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -435,7 +435,6 @@ int main() state = ST_FLASHING; } } - else if (state == ST_FLASHING) { // commit to flashing if (!unlocked && (memoryType == MEM_FLASH)) { diff --git a/radio/src/targets/horus/bootloader/boot_menu.cpp b/radio/src/targets/horus/bootloader/boot_menu.cpp index a9a0e5aa3..a74604aba 100644 --- a/radio/src/targets/horus/bootloader/boot_menu.cpp +++ b/radio/src/targets/horus/bootloader/boot_menu.cpp @@ -150,7 +150,6 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) lcd->drawBitmapPattern(356, 158, LBM_ERROR, BL_RED); } else if (st == ST_FLASH_CHECK) { - bootloaderDrawFilename(str, 0, true); if (opt == FC_ERROR) { @@ -159,8 +158,12 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str) } else if (opt == FC_OK) { VersionTag tag; + memset(&tag, 0, sizeof(tag)); extractFirmwareVersion(&tag); + lcd->drawText(168, 138, "Fork:", RIGHT | BL_FOREGROUND); + lcd->drawSizedText(174, 138, tag.fork, 6, BL_FOREGROUND); + lcd->drawText(168, 158, "Version:", RIGHT | BL_FOREGROUND); lcd->drawText(174, 158, tag.version, BL_FOREGROUND); From 2fead2bc393dca4e00c209ccc6187ce010ec32dc Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 20:24:35 +0200 Subject: [PATCH 098/114] Use the register reload interrupt instead of polling VSYNCS in CDSR --- radio/src/targets/horus/lcd_driver.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/radio/src/targets/horus/lcd_driver.cpp b/radio/src/targets/horus/lcd_driver.cpp index b3df5a2a6..0be902b46 100644 --- a/radio/src/targets/horus/lcd_driver.cpp +++ b/radio/src/targets/horus/lcd_driver.cpp @@ -222,15 +222,15 @@ void LCD_Init_LTDC() // init ltdc LTDC_Init(<DC_InitStruct); -#if 0 - LTDC_ITConfig(LTDC_IER_LIE, ENABLE); + LTDC_ITConfig(LTDC_IER_RRIE, ENABLE); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = LTDC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = LTDC_IRQ_PRIO; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pr e-emption priority. */; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); +#if 0 DMA2D_ITConfig(DMA2D_CR_TCIE, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA2D_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = DMA_SCREEN_IRQ_PRIO; @@ -299,9 +299,6 @@ void LCD_LayerInit() // Enable layer and reload LTDC_LayerCmd(LTDC_Layer1, ENABLE); LTDC_ReloadConfig(LTDC_IMReload); - - /* dithering activation */ - LTDC_DitherCmd(ENABLE); // ???? } void LCD_Init(void) @@ -313,6 +310,10 @@ void LCD_Init(void) /* Configure the LCD Control pins */ LCD_AF_GPIOConfig(); + // Enable LTDC IRQ in NVIC + NVIC_EnableIRQ(LTDC_IRQn); + NVIC_SetPriority(LTDC_IRQn, 7); + LCD_Init_LTDC(); } @@ -604,6 +605,15 @@ uint16_t* lcdGetScratchBuffer() return (uint16_t*)LCD_SCRATCH_FRAME_BUFFER; } +static volatile uint8_t _frameBufferAddressReloaded = 0; + +extern "C" void LTDC_IRQHandler(void) +{ + // clear interrupt flag + LTDC->ICR = LTDC_ICR_CRRIF; + _frameBufferAddressReloaded = 1; +} + static void lcdSwitchLayers() { if (currentLayer == LCD_FIRST_LAYER) { @@ -616,12 +626,12 @@ static void lcdSwitchLayers() } // reload shadow registers on vertical blank + _frameBufferAddressReloaded = 0; LTDC->SRCR = LTDC_SRCR_VBR; // wait for reload // TODO: replace through some smarter mechanism without busy wait - while ((LTDC->CDSR & LTDC_CDSR_VSYNCS) == 0); - while ((LTDC->CDSR & LTDC_CDSR_VSYNCS) == 1); + while(_frameBufferAddressReloaded == 0); } void lcdRefresh() From cee24fe013045cc15734b629a97c36b9a60902cd Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 20:57:34 +0200 Subject: [PATCH 099/114] Fixed warning screen triggering watchdog --- radio/src/gui/colorlcd/fullscreen_dialog.cpp | 2 +- radio/src/telemetry/multi.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index 6e8742086..3182a766d 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -145,7 +145,7 @@ void FullScreenDialog::runForever() checkBacklight(); WDG_RESET(); - RTOS_WAIT_MS(20); + RTOS_WAIT_MS(1); MainWindow::instance()->run(false); } diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 7e7a3d639..303cdb244 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -234,8 +234,11 @@ static void processMultiStatusPacket(const uint8_t * data, uint8_t module, uint8 } if (getMultiModuleStatus(module).requiresFailsafeCheck) { getMultiModuleStatus(module).requiresFailsafeCheck = false; - if (getMultiModuleStatus(module).supportsFailsafe() && g_model.moduleData[module].failsafeMode == FAILSAFE_NOT_SET) + + if (getMultiModuleStatus(module).supportsFailsafe() && + g_model.moduleData[module].failsafeMode == FAILSAFE_NOT_SET) { ALERT(STR_FAILSAFEWARN, STR_NO_FAILSAFE, AU_ERROR); + } } if (wasBinding && !status.isBinding() && getMultiBindStatus(module) == MULTI_BIND_INITIATED) From 6b9abe0670e403b68c87b9155cd493fdfc9e15fb Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 07:58:57 +0200 Subject: [PATCH 100/114] Remove obsoleted code --- radio/src/gui/colorlcd/CMakeLists.txt | 8 +- radio/src/gui/colorlcd/draw_functions.cpp | 33 ++ radio/src/gui/colorlcd/menus.h | 247 -------- .../src/gui/colorlcd/model_custom_scripts.cpp | 174 ------ radio/src/gui/colorlcd/model_select_old.cpp | 528 ------------------ .../colorlcd/radio_ghost_module_config.cpp | 1 - radio/src/gui/colorlcd/view_text.cpp | 73 --- radio/src/lua/api_general.cpp | 8 +- radio/src/lua/interface.cpp | 4 + radio/src/main.cpp | 2 +- radio/src/opentx.cpp | 6 + radio/src/opentx.h | 5 +- radio/src/sdcard.cpp | 2 + radio/src/stubs.cpp | 46 -- 14 files changed, 54 insertions(+), 1083 deletions(-) delete mode 100644 radio/src/gui/colorlcd/model_custom_scripts.cpp delete mode 100644 radio/src/gui/colorlcd/model_select_old.cpp delete mode 100644 radio/src/gui/colorlcd/view_text.cpp delete mode 100644 radio/src/stubs.cpp diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index b7000a10e..79af1169c 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -95,15 +95,9 @@ endif() if(LUA STREQUAL YES) set(SRC ${SRC} lua/widgets.cpp) - # TODO set(GUI_SRC ${GUI_SRC} model_custom_scripts.cpp) endif() -set(SRC - ${SRC} - stubs.cpp - storage/modelslist.cpp - ) - +set(SRC ${SRC} storage/modelslist.cpp) option(WINDOWS_INSPECT_BORDERS "Draw bounding boxes around windows" OFF) if(WINDOWS_INSPECT_BORDERS) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index 8b028ea6f..fed04986b 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -117,9 +117,42 @@ void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char } } + WDG_RESET(); lcdRefresh(); } +void drawFatalErrorScreen(const char * message) +{ + lcd->clear(); + lcd->drawText(LCD_W/2, LCD_H/2-20, message, FONT(XL)|CENTERED|ALARM_COLOR); + + WDG_RESET(); + lcdRefresh(); +} + +void runFatalErrorScreen(const char * message) +{ + while (true) { + backlightEnable(100); + drawFatalErrorScreen(message); + + uint8_t refresh = false; + while (true) { + uint32_t pwr_check = pwrCheck(); + if (pwr_check == e_power_off) { + boardOff(); + return; // only happens in SIMU, required for proper shutdown + } + else if (pwr_check == e_power_press) { + refresh = true; + } + else if (pwr_check == e_power_on && refresh) { + break; + } + } + } +} + void drawCurveRef(BitmapBuffer * dc, coord_t x, coord_t y, const CurveRef & curve, LcdFlags flags) { if (curve.value != 0) { diff --git a/radio/src/gui/colorlcd/menus.h b/radio/src/gui/colorlcd/menus.h index e539f06e2..218d1a954 100644 --- a/radio/src/gui/colorlcd/menus.h +++ b/radio/src/gui/colorlcd/menus.h @@ -23,32 +23,8 @@ #include "keys.h" -#define MIXES_2ND_COLUMN 140 - -extern int menuVerticalPosition; -extern int menuHorizontalPosition; -extern int menuVerticalOffset; extern uint8_t menuCalibrationState; -// Temporary no highlight - -typedef bool (*MenuHandlerFunc)(event_t event); - -extern MenuHandlerFunc menuHandlers[5]; -extern uint8_t menuVerticalPositions[4]; -extern uint8_t menuLevel; -extern event_t menuEvent; - -void chainMenu(MenuHandlerFunc newMenu); -void pushMenu(MenuHandlerFunc newMenu); -void popMenu(); -void abortPopMenu(); - -inline bool isModelMenuDisplayed() -{ - return menuVerticalPositions[0] == 0; -} - enum MenuIcons { ICON_OPENTX, #if defined(HARDWARE_TOUCH) @@ -100,188 +76,6 @@ enum MenuIcons { MENUS_ICONS_COUNT }; -enum EnumTabModel { - MENU_MODEL_SETUP, - CASE_HELI(MENU_MODEL_HELI) - CASE_FLIGHT_MODES(MENU_MODEL_FLIGHT_MODES) - MENU_MODEL_INPUTS, - MENU_MODEL_MIXES, - MENU_MODEL_OUTPUTS, - MENU_MODEL_CURVES, - CASE_GVARS(MENU_MODEL_GVARS) - MENU_MODEL_LOGICAL_SWITCHES, - MENU_MODEL_SPECIAL_FUNCTIONS, -#if defined(LUA_MODEL_SCRIPTS) - MENU_MODEL_CUSTOM_SCRIPTS, -#endif - MENU_MODEL_TELEMETRY, - MENU_MODEL_PAGES_COUNT -}; - -const uint8_t MODEL_ICONS[MENU_MODEL_PAGES_COUNT + 1] = { - ICON_MODEL, - ICON_MODEL_SETUP, - CASE_HELI(ICON_MODEL_HELI) - CASE_FLIGHT_MODES(ICON_MODEL_FLIGHT_MODES) - ICON_MODEL_INPUTS, - ICON_MODEL_MIXER, - ICON_MODEL_OUTPUTS, - ICON_MODEL_CURVES, - CASE_GVARS(ICON_MODEL_GVARS) - ICON_MODEL_LOGICAL_SWITCHES, - ICON_MODEL_SPECIAL_FUNCTIONS, -#if defined(LUA_MODEL_SCRIPTS) - ICON_MODEL_LUA_SCRIPTS, -#endif - ICON_MODEL_TELEMETRY -}; - -const uint8_t STATS_ICONS[] = { - ICON_STATS, - ICON_STATS_THROTTLE_GRAPH, - ICON_STATS_DEBUG, - ICON_STATS_ANALOGS, -#if defined(DEBUG_TRACE_BUFFER) - ICON_STATS_TIMERS -#endif -}; - -const uint8_t MONITOR_ICONS[] = { - ICON_MONITOR, - ICON_MONITOR_CHANNELS1, - ICON_MONITOR_CHANNELS2, - ICON_MONITOR_CHANNELS3, - ICON_MONITOR_CHANNELS4, - ICON_MONITOR_LOGICAL_SWITCHES -}; - -bool menuModelSetup(event_t event); -bool menuModelFailsafe(event_t event); -bool menuModelHeli(event_t event); -bool menuModelFlightModesAll(event_t event); -bool menuModelExposAll(event_t event); -bool menuModelMixAll(event_t event); -bool menuModelLimits(event_t event); -bool menuModelCurvesAll(event_t event); -bool menuModelCurveOne(event_t event); -bool menuModelGVars(event_t event); -bool menuModelLogicalSwitches(event_t event); -bool menuModelSpecialFunctions(event_t event); -bool menuModelCustomScripts(event_t event); -bool menuModelTelemetryFrsky(event_t event); -bool menuModelSensor(event_t event); -bool menuModelExpoOne(event_t event); - -extern const MenuHandlerFunc menuTabModel[MENU_MODEL_PAGES_COUNT]; - -enum EnumTabRadio { - MENU_RADIO_SETUP, - MENU_RADIO_SD_MANAGER, - MENU_RADIO_TOOLS, - MENU_RADIO_SPECIAL_FUNCTIONS, - MENU_RADIO_TRAINER, - MENU_RADIO_HARDWARE, - MENU_RADIO_VERSION, - MENU_RADIO_PAGES_COUNT -}; - -const uint8_t RADIO_ICONS[MENU_RADIO_PAGES_COUNT + 1] = { - ICON_RADIO, - ICON_RADIO_SETUP, - ICON_RADIO_SD_MANAGER, - ICON_RADIO_TOOLS, - ICON_RADIO_GLOBAL_FUNCTIONS, - ICON_RADIO_TRAINER, - ICON_RADIO_HARDWARE, - ICON_RADIO_VERSION -}; - -bool menuRadioSetup(event_t event); -bool menuRadioSdManager(event_t event); -bool menuRadioTools(event_t event); -bool menuRadioSpecialFunctions(event_t event); -bool menuRadioTrainer(event_t event); -bool menuRadioVersion(event_t event); -bool menuRadioHardware(event_t event); -bool menuRadioCalibration(event_t event); - -extern const MenuHandlerFunc menuTabGeneral[MENU_RADIO_PAGES_COUNT]; - -enum MenuRadioIndexes -{ - e_StatsGraph, - e_StatsDebug, - e_StatsAnalogs, -#if defined(DEBUG_TRACE_BUFFER) - e_StatsTraces, -#endif -}; - -bool menuStatsGraph(event_t event); -bool menuStatsDebug(event_t event); -bool menuStatsAnalogs(event_t event); -bool menuStatsTraces(event_t event); - -enum EnumTabMonitors -{ - e_MonChannelsFirst, - e_MonChannels1 = e_MonChannelsFirst, - e_MonChannels2, - e_MonChannels3, - e_MonChannels4, - e_MonLogicalSwitches, - e_MonTabChannelsPagesCount -}; - -extern const MenuHandlerFunc menuTabMonitors[e_MonTabChannelsPagesCount]; -extern uint8_t lastMonitorPage; -extern void drawSingleMixerBar(coord_t, coord_t, coord_t, coord_t, uint8_t); -extern void drawSingleOutputBar(coord_t, coord_t, coord_t, coord_t, uint8_t); - -extern const MenuHandlerFunc menuTabScreensSetup[1+MAX_CUSTOM_SCREENS] ; - -bool menuFirstCalib(event_t event); -bool menuMainView(event_t event); -bool menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomFunctionsContext & functionsContext); -bool menuModelSelect(event_t event); -bool menuAboutView(event_t event); -bool menuMainViewChannelsMonitor(event_t event); -bool menuTextView(event_t event); -bool menuScreensTheme(event_t event); -bool menuRadioGhostModuleConfig(event_t event); -bool menuRadioPowerMeter(event_t event); - -extern int8_t checkIncDec_Ret; // global helper vars - -#define EDIT_SELECT_FIELD 0 -#define EDIT_MODIFY_FIELD 1 -#define EDIT_MODIFY_STRING 2 -extern int8_t s_editMode; // global editmode - -// checkIncDec flags -#define EE_GENERAL 0x01 -#define EE_MODEL 0x02 -#define NO_INCDEC_MARKS 0x04 -#define INCDEC_SWITCH 0x08 -#define INCDEC_SOURCE 0x10 -#define INCDEC_REP10 0x40 -#define NO_DBLKEYS 0x80 - -// mawrow special values -//#define READONLY_ROW ((uint8_t)-1) -//#define TITLE_ROW READONLY_ROW -//#define ORPHAN_ROW ((uint8_t)-2) -//#define HIDDEN_ROW ((uint8_t)-3) -//#define NAVIGATION_LINE_BY_LINE 0x40 -//#define CURSOR_ON_LINE() (menuHorizontalPosition<0) - -extern uint8_t s_currIdxSubMenu; - -extern const char * warningText; -extern const char * warningInfoText; -extern uint8_t warningInfoLength; -extern uint8_t warningResult; -extern uint8_t warningType; #define COPY_MODE 1 #define MOVE_MODE 2 @@ -302,48 +96,7 @@ void deleteMix(uint8_t idx); void insertMix(uint8_t idx); void copyMix(uint8_t source, uint8_t dest, int8_t ch); -#define MENU_X 80 -#define MENU_W LCD_W-(2*MENU_X) -#define POPUP_X 120 -#define POPUP_Y 70 -#define WARNING_LINE_LEN 32 -#define WARNING_LINE_X (POPUP_X+66) -#define WARNING_LINE_Y (POPUP_Y+9) - -void copySelection(char * dst, const char * src, uint8_t size); - -void showMessageBox(const char * title); -void runPopupWarning(event_t event); - -extern void (* popupFunc)(event_t event); -extern uint8_t warningInfoFlags; - -#define DISPLAY_WARNING(evt) (*popupFunc)(evt) -#define POPUP_INPUT(s, func) (warningText = s, popupFunc = func) -#define POPUP_MENU_MAX_LINES 12 -#define MENU_MAX_DISPLAY_LINES 9 -#define MENU_LINE_LENGTH (LEN_MODEL_NAME+12) - -extern const char * popupMenuItems[POPUP_MENU_MAX_LINES]; -extern uint16_t popupMenuItemsCount; -extern uint16_t popupMenuOffset; -enum { - MENU_OFFSET_INTERNAL, - MENU_OFFSET_EXTERNAL -}; -extern uint8_t popupMenuOffsetType; -extern uint8_t popupMenuSelectedItem; -const char * runPopupMenu(event_t event); -extern void (*popupMenuHandler)(const char * result); -void pushMenuTextView(const char * filename); -void pushModelNotes(); -void readModelNotes(); - typedef int (*FnFuncP) (int x); void drawFunction(FnFuncP fn, int x, int y, int width); -void onSourceLongEnterPress(const char *result); - -uint8_t switchToMix(uint8_t source); - #endif // _MENUS_H_ diff --git a/radio/src/gui/colorlcd/model_custom_scripts.cpp b/radio/src/gui/colorlcd/model_custom_scripts.cpp deleted file mode 100644 index 5385ddb6e..000000000 --- a/radio/src/gui/colorlcd/model_custom_scripts.cpp +++ /dev/null @@ -1,174 +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 "opentx.h" - -void onModelCustomScriptMenu(const char *result) -{ - ScriptData &sd = g_model.scriptsData[s_currIdx]; - - if (result == STR_UPDATE_LIST) { - if (!sdListFiles(SCRIPTS_MIXES_PATH, SCRIPTS_EXT, sizeof(sd.file), nullptr)) { - POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); - } - } - else { - // The user choosed a lua file in the list - copySelection(sd.file, result, sizeof(sd.file)); - memset(sd.inputs, 0, sizeof(sd.inputs)); - storageDirty(EE_MODEL); - LUA_LOAD_MODEL_SCRIPT(s_currIdx); - } -} - -enum menuModelCustomScriptItems { - ITEM_MODEL_CUSTOMSCRIPT_FILE, - ITEM_MODEL_CUSTOMSCRIPT_NAME, - ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL, -}; - -#define SCRIPT_ONE_2ND_COLUMN_POS (120) -#define SCRIPT_ONE_3RD_COLUMN_POS (240) - -bool menuModelCustomScriptOne(event_t event) -{ - ScriptData &sd = g_model.scriptsData[s_currIdx]; - - // drawStringWithIndex(lcdLastRightPos+FW, 0, "LUA", s_currIdx+1, 0); - - SUBMENU(STR_MENUCUSTOMSCRIPTS, ICON_MODEL_LUA_SCRIPTS, 3+scriptInputsOutputs[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); - - int8_t sub = menuVerticalPosition; - - for (int k=0; k0 ? BLINK|INVERS : INVERS) : 0); - - if (i == ITEM_MODEL_CUSTOMSCRIPT_FILE) { - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SCRIPT); - if (ZEXIST(sd.file)) - lcdDrawSizedText(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.file, sizeof(sd.file), attr); - else - lcdDrawTextAtIndex(SCRIPT_ONE_2ND_COLUMN_POS, y, STR_VCSWFUNC, 0, attr); - if (attr) s_editMode = 0; - if (attr && event==EVT_KEY_FIRST(KEY_ENTER) && !READ_ONLY()) { - killEvents(KEY_ENTER); - if (sdListFiles(SCRIPTS_MIXES_PATH, SCRIPTS_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { - POPUP_MENU_START(onModelCustomScriptMenu); - } - else { - POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); - } - } - } - else if (i == ITEM_MODEL_CUSTOMSCRIPT_NAME) { - lcdDrawText(MENUS_MARGIN_LEFT, y, TR_NAME); - editName(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.name, sizeof(sd.name), event, attr); - } - else if (i == ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL) { - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_INPUTS); - } - else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInputsOutputs[s_currIdx].inputsCount) { - int inputIdx = i-ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL-1; - lcdDrawSizedText(INDENT_WIDTH, y, scriptInputsOutputs[s_currIdx].inputs[inputIdx].name, 10, 0); - if (scriptInputsOutputs[s_currIdx].inputs[inputIdx].type == INPUT_TYPE_VALUE) { - lcdDrawNumber(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx].value+ \ - scriptInputsOutputs[s_currIdx].inputs[inputIdx].def, attr|LEFT); - if (attr) { - CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx].value, \ - scriptInputsOutputs[s_currIdx].inputs[inputIdx].min-scriptInputsOutputs[s_currIdx].inputs[inputIdx].def, \ - scriptInputsOutputs[s_currIdx].inputs[inputIdx].max-scriptInputsOutputs[s_currIdx].inputs[inputIdx].def); - } - } - else { - drawSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx].source, attr); - if (attr) { - CHECK_INCDEC_MODELSOURCE(event, g_model.scriptsData[s_currIdx].inputs[inputIdx].source, 0, MIXSRC_LAST_TELEM); - } - } - } - } - - if (scriptInputsOutputs[s_currIdx].outputsCount > 0) { - lcdDrawSolidVerticalLine(SCRIPT_ONE_3RD_COLUMN_POS-4, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H+5, DEFAULT_COLOR); - // lcdDrawText(SCRIPT_ONE_3RD_COLUMN_POS, FH+1, STR_OUTPUTS); - - for (int i=0; i= 0) { - s_currIdx = sub; - pushMenu(menuModelCustomScriptOne); - } - - for (int i=0, scriptIndex=0; idrawBitmap(x+1, y+1, model->getBuffer()); - if (current) { - lcd->drawBitmapPattern(x+66, y+43, LBM_ACTIVE_MODEL, TITLE_BGCOLOR); - } - if (selected) { - lcdDrawSolidRect(x, y, MODELCELL_WIDTH+2, MODELCELL_HEIGHT+2, 1, TITLE_BGCOLOR); - drawShadow(x, y, MODELCELL_WIDTH+2, MODELCELL_HEIGHT+2); - if (selectMode == MODE_MOVE_MODEL && modelselModelMoveBackground) { - lcd->drawMask(x+MODELCELL_WIDTH+2-modelselModelMoveBackground->width(), y, modelselModelMoveBackground, TITLE_BGCOLOR); - lcd->drawMask(x+MODELCELL_WIDTH+2-modelselModelMoveBackground->width()+12, y+5, modelselModelMoveIcon, DEFAULT_BGCOLOR); - } - } -} - -uint16_t categoriesVerticalOffset = 0; -uint16_t categoriesVerticalPosition = 0; -#define MODEL_INDEX() (menuVerticalPosition*2+menuHorizontalPosition) - -void setCurrentModel(unsigned int index) -{ - std::list::iterator it = currentCategory->begin(); - std::advance(it, index); - currentModel = *it; - menuVerticalPosition = index / 2; - menuHorizontalPosition = index & 1; - menuVerticalOffset = limit(menuVerticalPosition-2, menuVerticalOffset, min(menuVerticalPosition, max(0, (currentCategory->size()-7)/2))); -} - -void setCurrentCategory(unsigned int index) -{ - currentCategoryIndex = index; - const std::list& cats = modelslist.getCategories(); - std::list::const_iterator it = cats.begin(); - std::advance(it, index); - currentCategory = *it; - categoriesVerticalPosition = index; - categoriesVerticalOffset = limit(categoriesVerticalPosition-4, categoriesVerticalOffset, min(categoriesVerticalPosition, max(0, cats.size()-5))); - if (currentCategory->size() > 0) - setCurrentModel(0); - else - currentModel = nullptr; -} - -#if defined(LUA) -#define MAX_WIZARD_NAME_LEN (sizeof(WIZARD_PATH)+20) -#define WIZARD_SPACING 40 -#define WIZARD_LEFT_SPACING 30 -#define WIZARD_ICON_X 80 -#define WIZARD_ICON_Y 110 -#define WIZARD_TEXT_Y 195 - -uint8_t getWizardCount() -{ - uint8_t wizCnt=0; - DIR dir; - static FILINFO fno; - - FRESULT res = f_opendir(&dir, WIZARD_PATH); - if (res == FR_OK) { - for (;;) { - res = f_readdir(&dir, &fno); - if (res != FR_OK || fno.fname[0] == 0) { - break; - } - if (fno.fattrib & AM_DIR) { - wizCnt++; - } - } - } - f_closedir(&dir); - return wizCnt; -} - -bool menuModelWizard(event_t event) -{ - static uint8_t wizardSelected = 0; - static uint8_t wizardCnt = getWizardCount(); - bool executeMe = false; - uint8_t first = 0; - DIR dir; - static FILINFO fno; - char wizpath[MAX_WIZARD_NAME_LEN]; - - if (wizardCnt == 0) { - chainMenu(menuModelSelect); - return false; - } - - switch(event) { - case 0: - // no need to refresh the screen - return false; - - case EVT_KEY_FIRST(KEY_EXIT): - chainMenu(menuModelSelect); - return false; - - case EVT_KEY_BREAK(KEY_ENTER): - executeMe = true; - break; - - case EVT_ROTARY_RIGHT: - if (wizardSelected < wizardCnt-1) { - wizardSelected++; - } - if (wizardSelected > 3) { - first = wizardSelected - 3; - } - break; - - case EVT_ROTARY_LEFT: - if (wizardSelected != 0) { - wizardSelected--; - } - if(wizardSelected < first) - { - first = wizardSelected; - } - break; - } - strcpy(wizpath, WIZARD_PATH); - strcpy(&wizpath[sizeof(WIZARD_PATH)-1], "/"); - lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, DEFAULT_BGCOLOR); - lcd->drawBitmap(0, 0, modelselWizardBackground); - FRESULT res = f_opendir(&dir, WIZARD_PATH); - if (res == FR_OK) { - for (uint8_t wizidx=0;;wizidx++) { - res = f_readdir(&dir, &fno); - if (res != FR_OK || fno.fname[0] == 0) { - break; - } - if (fno.fattrib & AM_DIR) { - if((wizidx >= first) && (wizidx < (first+4))) { - uint16_t x = WIZARD_LEFT_SPACING + (wizidx - first) * (WIZARD_SPACING + WIZARD_ICON_X); - strcpy(&wizpath[sizeof(WIZARD_PATH)], fno.fname); - strcpy(&wizpath[sizeof(WIZARD_PATH) + strlen(fno.fname)], "/icon.png"); - BitmapBuffer * background = BitmapBuffer::load(wizpath); - lcd->drawBitmap(x, WIZARD_ICON_Y, background); - if(wizidx == wizardSelected ) { - if (wizardSelected < 5) { - lcdDrawRect(x, WIZARD_ICON_Y, 85, 130, 2, SOLID, MAINVIEW_GRAPHICS_COLOR_INDEX); - lcdDrawRect(x+5, WIZARD_TEXT_Y, 75, 4, 2, SOLID, MAINVIEW_GRAPHICS_COLOR_INDEX); - } - if (executeMe) { - strcpy(&wizpath[sizeof(WIZARD_PATH)+strlen(fno.fname)], "/wizard.lua"); - if (isFileAvailable(wizpath)) { - wizpath[sizeof(WIZARD_PATH) + strlen(fno.fname)] = 0; - f_chdir(wizpath); - luaExec(WIZARD_NAME); - } - } - } - delete background; - } - } - } - f_closedir(&dir); - } - return true; -} -#endif - -void onDeleteModelConfirm(const char * result) -{ - if (result == STR_OK) { - if (deleteMode == MODE_DELETE_CATEGORY) { - modelslist.removeCategory(currentCategory); - modelslist.save(); - setCurrentCategory(currentCategoryIndex > 0 ? currentCategoryIndex-1 : currentCategoryIndex); - } - else if (deleteMode == MODE_DELETE_MODEL){ - int modelIndex = MODEL_INDEX(); - modelslist.removeModel(currentCategory, currentModel); - s_copyMode = 0; - pushEvent(EVT_REFRESH); - if (modelIndex > 0) { - modelIndex--; - } - setCurrentModel(modelIndex); - } - } -} - -void onModelSelectMenu(const char * result) -{ - if (result == STR_SELECT_MODEL) { - if (!g_eeGeneral.disableRssiPoweroffAlarm) { - if (!confirmModelChange()) - return; - } - - // we store the latest changes if any - storageFlushCurrentModel(); - storageCheck(true); - memcpy(g_eeGeneral.currModelFilename, currentModel->modelFilename, LEN_MODEL_FILENAME); - modelslist.setCurrentModel(currentModel); - modelslist.setCurrentCategory(currentCategory); - loadModel(g_eeGeneral.currModelFilename, true); - storageDirty(EE_GENERAL); - storageCheck(true); - chainMenu(menuMainView); - } - else if (result == STR_DELETE_MODEL) { - POPUP_CONFIRMATION(STR_DELETEMODEL, onDeleteModelConfirm); - SET_WARNING_INFO(currentModel->modelName, LEN_MODEL_NAME, 0); - deleteMode = MODE_DELETE_MODEL; - } - else if (result == STR_CREATE_MODEL) { - if (!g_eeGeneral.disableRssiPoweroffAlarm) { - if (!confirmModelChange()) - return; - } - storageCheck(true); - modelslist.addModel(currentCategory, createModel()); - selectMode = MODE_SELECT_MODEL; - setCurrentModel(currentCategory->size() - 1); - modelslist.setCurrentModel(currentModel); - modelslist.setCurrentCategory(currentCategory); - modelslist.onNewModelCreated(currentModel, &g_model); -#if defined(LUA) - chainMenu(menuModelWizard); -#endif - } - else if (result == STR_DUPLICATE_MODEL) { - char duplicatedFilename[LEN_MODEL_FILENAME+1]; - memcpy(duplicatedFilename, currentModel->modelFilename, sizeof(duplicatedFilename)); - if (findNextFileIndex(duplicatedFilename, LEN_MODEL_FILENAME, MODELS_PATH)) { - sdCopyFile(currentModel->modelFilename, MODELS_PATH, duplicatedFilename, MODELS_PATH); - ModelCell * dup_model = modelslist.addModel(currentCategory, duplicatedFilename); - dup_model->fetchRfData(); - setCurrentModel(currentCategory->size() - 1); - } - else { - POPUP_WARNING(STR_INVALID_FILE); - } - } - else if (result == STR_MOVE_MODEL) { - selectMode = MODE_MOVE_MODEL; - } - else if (result == STR_CREATE_CATEGORY) { - currentCategory = modelslist.createCategory(); - setCurrentCategory(modelslist.getCategories().size() - 1); - } - else if (result == STR_RENAME_CATEGORY) { - selectMode = MODE_RENAME_CATEGORY; - s_editMode = EDIT_MODIFY_STRING; - editNameCursorPos = 0; - } - else if (result == STR_DELETE_CATEGORY) { - if (currentCategory->size() > 0){ - POPUP_WARNING(STR_DELETE_ERROR); - SET_WARNING_INFO(STR_CAT_NOT_EMPTY, sizeof(TR_CAT_NOT_EMPTY), 0); - } - else { - POPUP_CONFIRMATION(STR_DELETEMODEL, onDeleteModelConfirm); - SET_WARNING_INFO(currentCategory->name, LEN_MODEL_FILENAME, 0); - deleteMode = MODE_DELETE_CATEGORY; - } - } -} - -void initModelsList() -{ - modelslist.load(); - - categoriesVerticalOffset = 0; - bool found = false; - int index = 0; - const std::list& cats = modelslist.getCategories(); - for (std::list::const_iterator it = cats.begin(); it != cats.end(); ++it, ++index) { - if (*it == modelslist.getCurrentCategory()) { - setCurrentCategory(index); - found = true; - break; - } - } - if (!found) { - setCurrentCategory(0); - } - - menuVerticalOffset = 0; - found = false; - index = 0; - for (ModelsCategory::iterator it = currentCategory->begin(); it != currentCategory->end(); ++it, ++index) { - if (*it == modelslist.getCurrentModel()) { - setCurrentModel(index); - found = true; - break; - } - } - if (!found) { - setCurrentModel(0); - } -} - -bool menuModelSelect(event_t event) -{ - const std::list& cats = modelslist.getCategories(); - switch (event) { - case 0: - // no need to refresh the screen - return false; - - case EVT_ENTRY: - selectMode = MODE_SELECT_MODEL; - initModelsList(); - break; - - case EVT_KEY_BREAK(KEY_ENTER): - if (selectMode == MODE_MOVE_MODEL) - selectMode = MODE_SELECT_MODEL; - break; - - case EVT_KEY_FIRST(KEY_EXIT): - switch (selectMode) { - case MODE_MOVE_MODEL: - selectMode = MODE_SELECT_MODEL; - break; - case MODE_SELECT_MODEL: - chainMenu(menuMainView); - return false; - } - break; - - case EVT_KEY_FIRST(KEY_PGUP): -#if defined(PCBX10) - case EVT_KEY_LONG(KEY_PGDN): -#endif - if (selectMode == MODE_SELECT_MODEL) { - if (categoriesVerticalPosition == 0) - categoriesVerticalPosition = cats.size() - 1; - else - categoriesVerticalPosition -= 1; - setCurrentCategory(categoriesVerticalPosition); - } - else if (selectMode == MODE_MOVE_MODEL && categoriesVerticalPosition > 0) { - ModelsCategory * previous_category = currentCategory; - ModelCell * model = currentModel; - categoriesVerticalPosition -= 1; - setCurrentCategory(categoriesVerticalPosition); - modelslist.moveModel(model, previous_category, currentCategory); - setCurrentModel(currentCategory->size() - 1); - } - killEvents(event); - break; - -#if defined(PCBX12S) - case EVT_KEY_FIRST(KEY_PGDN): -#elif defined(PCBX10) - case EVT_KEY_BREAK(KEY_PGDN): -#endif - if (selectMode == MODE_SELECT_MODEL) { - categoriesVerticalPosition += 1; - if (categoriesVerticalPosition >= cats.size()) - categoriesVerticalPosition = 0; - setCurrentCategory(categoriesVerticalPosition); - } - else if (selectMode == MODE_MOVE_MODEL && categoriesVerticalPosition < cats.size()-1) { - ModelsCategory * previous_category = currentCategory; - ModelCell * model = currentModel; - categoriesVerticalPosition += 1; - setCurrentCategory(categoriesVerticalPosition); - modelslist.moveModel(model, previous_category, currentCategory); - setCurrentModel(currentCategory->size()-1); - } - break; - - case EVT_KEY_LONG(KEY_ENTER): - if (selectMode == MODE_SELECT_MODEL) { - killEvents(event); - if (currentModel && currentModel != modelslist.getCurrentModel()) { - POPUP_MENU_ADD_ITEM(STR_SELECT_MODEL); - } - POPUP_MENU_ADD_ITEM(STR_CREATE_MODEL); - if (currentModel) { - POPUP_MENU_ADD_ITEM(STR_DUPLICATE_MODEL); - POPUP_MENU_ADD_ITEM(STR_MOVE_MODEL); - } - // POPUP_MENU_ADD_SD_ITEM(STR_BACKUP_MODEL); - if (currentModel && currentModel != modelslist.getCurrentModel()) { - POPUP_MENU_ADD_ITEM(STR_DELETE_MODEL); - } - // POPUP_MENU_ADD_ITEM(STR_RESTORE_MODEL); - POPUP_MENU_ADD_ITEM(STR_CREATE_CATEGORY); - POPUP_MENU_ADD_ITEM(STR_RENAME_CATEGORY); - if (cats.size() > 1) { - POPUP_MENU_ADD_ITEM(STR_DELETE_CATEGORY); - } - POPUP_MENU_START(onModelSelectMenu); - } - break; - - } - - lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, DEFAULT_BGCOLOR); - lcd->drawBitmap(0, 0, modelselIconBitmap); - - // Categories - int index = 0; - coord_t y = 97; - drawVerticalScrollbar(CATEGORIES_WIDTH-1, y-1, 5*(FH+7)-5, categoriesVerticalOffset, cats.size(), 5); - for (std::list::const_iterator it = cats.begin(); it != cats.end(); ++it, ++index) { - if (index >= categoriesVerticalOffset && index < categoriesVerticalOffset+5) { - if (index != categoriesVerticalOffset) { - lcdDrawSolidHorizontalLine(1, y-4, CATEGORIES_WIDTH-10, LINE_COLOR); - } - if (selectMode == MODE_RENAME_CATEGORY && currentCategory == *it) { - lcdDrawSolidFilledRect(0, y-INVERT_VERT_MARGIN+1, CATEGORIES_WIDTH-2, INVERT_LINE_HEIGHT, DEFAULT_BGCOLOR); - editName(MENUS_MARGIN_LEFT, y, currentCategory->name, LEN_MODEL_FILENAME, event, 1, 0); - if (s_editMode == 0 || event == EVT_KEY_BREAK(KEY_EXIT)) { - modelslist.save(); - selectMode = MODE_SELECT_MODEL; - pushEvent(EVT_REFRESH); - } - } - else { - drawCategory(y, (*it)->name, currentCategory==*it); - } - y += FH+7; - } - } - - // Models - index = 0; - y = 5; - for (ModelsCategory::iterator it = currentCategory->begin(); it != currentCategory->end(); ++it, ++index) { - if (index >= menuVerticalOffset*2 && index < (menuVerticalOffset+4)*2) { - bool selected = ((selectMode==MODE_SELECT_MODEL || selectMode==MODE_MOVE_MODEL) && index==menuVerticalPosition*2+menuHorizontalPosition); - bool current = !strncmp((*it)->modelFilename, g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME); - if (index & 1) { - drawModel(MODELS_LEFT + MODELS_COLUMN_WIDTH, y, *it, current, selected); - y += 66; - } - else { - drawModel(MODELS_LEFT, y, *it, current, selected); - } - if (selected) { - lcd->drawBitmap(5, LCD_H-FH, modelselModelNameBitmap); - lcdDrawText(22, LCD_H-FH-1, (*it)->modelFilename, FONT(XS)|DEFAULT_COLOR); - } - } - } - - // Navigation - if (currentModel) { - if (selectMode == MODE_SELECT_MODEL) { - if (navigate(event, index, 4, 2) != 0) { - setCurrentModel(MODEL_INDEX()); - pushEvent(EVT_REFRESH); - } - } - else if (selectMode == MODE_MOVE_MODEL) { - int8_t direction = navigate(event, index, 4, 2, false); - if (direction) { - modelslist.moveModel(currentCategory, currentModel, direction); - setCurrentModel(MODEL_INDEX()); - pushEvent(EVT_REFRESH); - } - } - } - drawVerticalScrollbar(DEFAULT_SCROLLBAR_X + 4, 7, LCD_H - 15, menuVerticalOffset, (index + 1) / 2, 4); - - // Footer - lcd->drawBitmap(5, LCD_H-FH-20, modelselSdFreeBitmap); - uint32_t size = sdGetSize() / 100; - lcdDrawNumber(22, LCD_H-FH-21, size, PREC1|FONT(XS), 0, nullptr, "GB"); - lcd->drawBitmap(70, LCD_H-FH-20, modelselModelQtyBitmap); - lcdDrawNumber(92, LCD_H-FH-21, modelslist.getModelsCount(),FONT(XS)); - - return true; -} diff --git a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp index 368c0c195..951cba9e7 100644 --- a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp +++ b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp @@ -128,7 +128,6 @@ void RadioGhostModuleConfig::onEvent(event_t event) break; case EVT_KEY_LONG(KEY_EXIT): - menuVerticalOffset = 0; memclear(&reusableBuffer.ghostMenu, sizeof(reusableBuffer.ghostMenu)); reusableBuffer.ghostMenu.buttonAction = GHST_BTN_NONE; reusableBuffer.ghostMenu.menuAction = GHST_MENU_CTRL_CLOSE; diff --git a/radio/src/gui/colorlcd/view_text.cpp b/radio/src/gui/colorlcd/view_text.cpp deleted file mode 100644 index e09f62699..000000000 --- a/radio/src/gui/colorlcd/view_text.cpp +++ /dev/null @@ -1,73 +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 "opentx.h" - -bool menuTextView(event_t event) -{ - static int lines_count; - - drawMenuTemplate(STR_TEXT_VIEWER, ICON_OPENTX, nullptr, OPTION_MENU_NO_SCROLLBAR); - - switch (event) { - case EVT_ENTRY: - menuVerticalOffset = 0; - lines_count = 0; - sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, lines_count); - break; - - case EVT_ROTARY_LEFT: - if (menuVerticalOffset == 0) - break; - else - menuVerticalOffset--; - sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, lines_count); - break; - - case EVT_ROTARY_RIGHT: - if (menuVerticalOffset + TEXT_VIEWER_LINES >= lines_count) - break; - else - ++menuVerticalOffset; - sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, lines_count); - break; - - case EVT_KEY_FIRST(KEY_EXIT): - menuVerticalOffset = 0; - popMenu(); - break; - } - - for (int i = 0; i < TEXT_VIEWER_LINES; i++) { - lcd->drawTextMaxWidth(MENUS_MARGIN_LEFT, MENU_HEADER_HEIGHT + i * FH, reusableBuffer.viewText.lines[i], 0, LCD_W - 2 * MENUS_MARGIN_LEFT); - } - - drawVerticalScrollbar(LCD_W-5, 50, 195, menuVerticalOffset, lines_count, TEXT_VIEWER_LINES); - - return true; -} - -void pushMenuTextView(const char *filename) -{ - if (strlen(filename) < TEXT_FILENAME_MAXLEN) { - strcpy(reusableBuffer.viewText.filename, filename); - pushMenu(menuTextView); - } -} diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 7a29f9075..e1981d297 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1227,6 +1227,7 @@ Run function (key pressed) @status current Introduced in 2.2.0 */ +#if 0 static int luaPopupWarning(lua_State * L) { event_t event = luaL_checkinteger(L, 2); @@ -1242,6 +1243,7 @@ static int luaPopupWarning(lua_State * L) } return 1; } +#endif /*luadoc @function popupConfirmation(title, event) deprecated, please replace by @@ -1262,6 +1264,7 @@ Run function (key pressed) @status current Introduced in 2.2.0, changed to (title, message, event) in 2.3.8 */ +#if 0 static int luaPopupConfirmation(lua_State * L) { warningType = WARNING_TYPE_CONFIRM; @@ -1288,6 +1291,7 @@ static int luaPopupConfirmation(lua_State * L) } return 1; } +#endif /*luadoc @function defaultStick(channel) @@ -1768,8 +1772,8 @@ const luaL_Reg opentxLib[] = { { "playTone", luaPlayTone }, { "playHaptic", luaPlayHaptic }, // { "popupInput", luaPopupInput }, - { "popupWarning", luaPopupWarning }, - { "popupConfirmation", luaPopupConfirmation }, + // { "popupWarning", luaPopupWarning }, + // { "popupConfirmation", luaPopupConfirmation }, { "defaultStick", luaDefaultStick }, { "defaultChannel", luaDefaultChannel }, { "getRSSI", luaGetRSSI }, diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index f30f1ba60..1046364f4 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -773,6 +773,7 @@ void displayLuaError(const char * title) } } +#if !defined(COLORLCD) void displayAcknowledgeLuaError(event_t event) { warningResult = false; @@ -781,6 +782,7 @@ void displayAcknowledgeLuaError(event_t event) warningText = nullptr; } } +#endif void luaError(lua_State * L, uint8_t error, bool acknowledge) { @@ -819,9 +821,11 @@ void luaError(lua_State * L, uint8_t error, bool acknowledge) } if (acknowledge) { +#if !defined(COLORLCD) warningText = errorTitle; warningType = WARNING_TYPE_INFO; popupFunc = displayAcknowledgeLuaError; +#endif } else { displayLuaError(errorTitle); diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 66610cf3e..414e5f642 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -84,7 +84,7 @@ void handleUsbConnection() #if defined(STM32) && !defined(SIMU) if (!usbStarted() && usbPlugged()) { if (getSelectedUsbMode() == USB_UNSELECTED_MODE) { - if (g_eeGeneral.USBMode == USB_UNSELECTED_MODE && popupMenuItemsCount == 0) { + if (g_eeGeneral.USBMode == USB_UNSELECTED_MODE) { openUsbMenu(); } else { diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 0dd4f9597..6ca52d587 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -780,6 +780,9 @@ void checkAll() checkMultiLowPower(); #endif +#if defined(COLORLCD) + #warning "KEYSTUCK Message Not Yet Implemented" +#else if (!waitKeysReleased()) { showMessageBox(STR_KEYSTUCK); tmr10ms_t tgtime = get_tmr10ms() + 500; @@ -788,6 +791,7 @@ void checkAll() WDG_RESET(); } } +#endif #if defined(EXTERNAL_ANTENNA) && defined(INTERNAL_MODULE_PXX1) checkExternalAntenna(); @@ -2067,6 +2071,8 @@ uint32_t pwrCheck() event_t evt = getEvent(false); DISPLAY_WARNING(evt); LED_ERROR_BEGIN(); + + WDG_RESET(); lcdRefresh(); if (warningResult) { diff --git a/radio/src/opentx.h b/radio/src/opentx.h index b2b3558d0..3dcce843b 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1008,10 +1008,7 @@ union ReusableBuffer #if defined(EEPROM_RLC) && LCD_W < 212 uint16_t eepromfree; #endif -#if defined(SDCARD) - char menu_bss[POPUP_MENU_MAX_LINES][MENU_LINE_LENGTH]; - char mainname[45]; // because reused for SD backup / restore, max backup filename 44 chars: "/MODELS/MODEL0134353-2014-06-19-04-51-27.bin" -#else +#if !defined(SDCARD) char mainname[LEN_MODEL_NAME]; #endif } modelsel; diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp index be6370a08..398fa477e 100644 --- a/radio/src/sdcard.cpp +++ b/radio/src/sdcard.cpp @@ -210,6 +210,7 @@ const char * getBasename(const char * path) return path; } +#if !defined(LIBOPENUI) bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen, const char * selection, uint8_t flags) { static uint16_t lastpopupMenuOffset = 0; @@ -427,6 +428,7 @@ void sdReadTextFile(const char * filename, char lines[TEXT_VIEWER_LINES][LCD_COL lines_count = current_line; } } +#endif // !LIBOPENUI #if defined(SDCARD) const char * sdCopyFile(const char * srcPath, const char * destPath) diff --git a/radio/src/stubs.cpp b/radio/src/stubs.cpp deleted file mode 100644 index a4583d329..000000000 --- a/radio/src/stubs.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include "opentx.h" - -const char *warningText = NULL; -const char *warningInfoText; -uint8_t warningInfoLength; -uint8_t warningType; -uint8_t warningResult = 0; -uint8_t warningInfoFlags; -void (*popupFunc)(uint16_t event) = NULL; -const char *popupMenuItems[POPUP_MENU_MAX_LINES]; -uint16_t popupMenuItemsCount = 0; -uint16_t popupMenuOffset = 0; -uint8_t popupMenuOffsetType = 0; -void (*popupMenuHandler)(const char * result); -uint8_t noHighlightCounter; - -void runPopupWarning(uint16_t event) -{ -} - -void drawFatalErrorScreen(const char * message) -{ -} - -void showMessageBox(const char * title) -{ - -} - -bool menuFirstCalib(event_t event) -{ - return false; -} - -void drawAlertBox(const char * title, const char * text, const char * action) -{ - -} - -uint8_t menuLevel; -int menuVerticalOffset; - -void runFatalErrorScreen(char const*) -{ - -} From 51e6c48bbe38d7782498f443c7187096a6fdd022 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 08:01:53 +0200 Subject: [PATCH 101/114] re-enabled rambackupRestore() --- radio/src/opentx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 6ca52d587..86becb0f8 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1848,7 +1848,7 @@ void opentxInit() if (globalData.unexpectedShutdown) { // SDCARD not available, try to restore last model from RAM TRACE("rambackupRestore"); -// rambackupRestore(); + rambackupRestore(); } else { storageReadAll(); From cb8a23cb5e1135c61f9ed57e8a9c63b1295ca027 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 10:08:45 +0200 Subject: [PATCH 102/114] Added confirmation dialog and use it to confirm shutdown on receiver still connected --- radio/src/gui/colorlcd/draw_functions.cpp | 46 ++++++-- radio/src/gui/colorlcd/fullscreen_dialog.cpp | 118 ++++++++++++++----- radio/src/gui/colorlcd/fullscreen_dialog.h | 5 +- radio/src/opentx.cpp | 20 +++- radio/src/opentx.h | 52 ++++---- 5 files changed, 177 insertions(+), 64 deletions(-) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index fed04986b..65f07c39b 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -88,31 +88,54 @@ void drawSleepBitmap() lcdRefresh(); } +// +// TODO: move shutdown animation to Theme +// #define SHUTDOWN_CIRCLE_DIAMETER 150 void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char * message) { if (totalDuration == 0) return; - static const BitmapBuffer * shutdown = BitmapBuffer::loadBitmap(OpenTxTheme::instance()->getFilePath("shutdown.bmp")); + static const BitmapBuffer* shutdown = nullptr; + if (!shutdown) { + shutdown = BitmapBuffer::loadBitmap( + OpenTxTheme::instance()->getFilePath("shutdown.bmp")); + } lcd->reset(); if (shutdown) { OpenTxTheme::instance()->drawBackground(lcd); - lcd->drawBitmap((LCD_W - shutdown->width()) / 2, (LCD_H - shutdown->height()) / 2, shutdown); + lcd->drawBitmap((LCD_W - shutdown->width()) / 2, + (LCD_H - shutdown->height()) / 2, shutdown); int quarter = duration / (totalDuration / 5); - if (quarter >= 1) lcd->drawBitmapPattern(LCD_W/2, (LCD_H-SHUTDOWN_CIRCLE_DIAMETER)/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, 0, SHUTDOWN_CIRCLE_DIAMETER/2); - if (quarter >= 2) lcd->drawBitmapPattern(LCD_W/2, LCD_H/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER/2, SHUTDOWN_CIRCLE_DIAMETER/2); - if (quarter >= 3) lcd->drawBitmapPattern((LCD_W-SHUTDOWN_CIRCLE_DIAMETER)/2, LCD_H/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER, SHUTDOWN_CIRCLE_DIAMETER/2); - if (quarter >= 4) lcd->drawBitmapPattern((LCD_W-SHUTDOWN_CIRCLE_DIAMETER)/2, (LCD_H-SHUTDOWN_CIRCLE_DIAMETER)/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER*3/2, SHUTDOWN_CIRCLE_DIAMETER/2); - } - else { + if (quarter >= 1) + lcd->drawBitmapPattern(LCD_W / 2, (LCD_H - SHUTDOWN_CIRCLE_DIAMETER) / 2, + LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, 0, + SHUTDOWN_CIRCLE_DIAMETER / 2); + if (quarter >= 2) + lcd->drawBitmapPattern(LCD_W / 2, LCD_H / 2, LBM_SHUTDOWN_CIRCLE, + DEFAULT_COLOR, SHUTDOWN_CIRCLE_DIAMETER / 2, + SHUTDOWN_CIRCLE_DIAMETER / 2); + if (quarter >= 3) + lcd->drawBitmapPattern((LCD_W - SHUTDOWN_CIRCLE_DIAMETER) / 2, LCD_H / 2, + LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, + SHUTDOWN_CIRCLE_DIAMETER, + SHUTDOWN_CIRCLE_DIAMETER / 2); + if (quarter >= 4) + lcd->drawBitmapPattern((LCD_W - SHUTDOWN_CIRCLE_DIAMETER) / 2, + (LCD_H - SHUTDOWN_CIRCLE_DIAMETER) / 2, + LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, + SHUTDOWN_CIRCLE_DIAMETER * 3 / 2, + SHUTDOWN_CIRCLE_DIAMETER / 2); + } else { lcd->clear(); int quarter = duration / (totalDuration / 5); for (int i = 1; i <= 4; i++) { if (quarter >= i) { - lcd->drawSolidFilledRect(LCD_W / 2 - 70 + 24 * i, LCD_H / 2 - 10, 20, 20, DEFAULT_BGCOLOR); + lcd->drawSolidFilledRect(LCD_W / 2 - 70 + 24 * i, LCD_H / 2 - 10, 20, + 20, DEFAULT_BGCOLOR); } } } @@ -123,8 +146,9 @@ void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char void drawFatalErrorScreen(const char * message) { - lcd->clear(); - lcd->drawText(LCD_W/2, LCD_H/2-20, message, FONT(XL)|CENTERED|ALARM_COLOR); + lcd->reset(); + lcd->clear(COLOR2FLAGS(BLACK)); + lcd->drawText(LCD_W/2, LCD_H/2-20, message, FONT(XL)|CENTERED|COLOR2FLAGS(WHITE)); WDG_RESET(); lcdRefresh(); diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index 3182a766d..4236c7523 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -23,23 +23,23 @@ #include "opentx.h" #include "libopenui.h" -FullScreenDialog::FullScreenDialog(uint8_t type, std::string title, std::string message, std::string action, const std::function & confirmHandler): - FormGroup(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE), - type(type), - title(std::move(title)), - message(std::move(message)), - action(std::move(action)), - confirmHandler(confirmHandler) +FullScreenDialog::FullScreenDialog( + uint8_t type, std::string title, std::string message, std::string action, + const std::function& confirmHandler) : + FormGroup(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE), + type(type), + title(std::move(title)), + message(std::move(message)), + action(std::move(action)), + confirmHandler(confirmHandler) { Layer::push(this); #if defined(HARDWARE_TOUCH) - new FabButton(this, LCD_W - 50, LCD_H - 50, ICON_NEXT, - [=]() -> uint8_t { - if (confirmHandler) - confirmHandler(); - return 0; - }); + new FabButton(this, LCD_W - 50, LCD_H - 50, ICON_NEXT, [=]() -> uint8_t { + if (confirmHandler) confirmHandler(); + return 0; + }); #endif bringToTop(); @@ -50,34 +50,58 @@ void FullScreenDialog::paint(BitmapBuffer * dc) { OpenTxTheme::instance()->drawBackground(dc); - dc->drawFilledRect(0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT, SOLID, FOCUS_COLOR, OPACITY(8)); + dc->drawFilledRect(0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT, SOLID, + FOCUS_COLOR, OPACITY(8)); - if (type == WARNING_TYPE_ALERT || type == WARNING_TYPE_ASTERISK) - dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->asterisk); - else if (type == WARNING_TYPE_INFO) - dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->busy); - else // confirmation - dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->question); + if (type == WARNING_TYPE_ALERT || type == WARNING_TYPE_ASTERISK) { + dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, + OpenTxTheme::instance()->asterisk); + } + else if (type == WARNING_TYPE_INFO) { + dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, + OpenTxTheme::instance()->busy); + } + else { // confirmation + dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, + OpenTxTheme::instance()->question); + } if (type == WARNING_TYPE_ALERT) { -#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ) - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, STR_WARNING, ALARM_COLOR|FONT(XL)); - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, title.c_str(), ALARM_COLOR|FONT(XL)); +#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || \ + defined(TRANSLATIONS_CZ) + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, STR_WARNING, + ALARM_COLOR | FONT(XL)); + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, + title.c_str(), ALARM_COLOR | FONT(XL)); #else - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), ALARM_COLOR|FONT(XL)); - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, STR_WARNING, ALARM_COLOR|FONT(XL)); + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), + ALARM_COLOR | FONT(XL)); + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP + ALERT_TITLE_LINE_HEIGHT, + STR_WARNING, ALARM_COLOR | FONT(XL)); #endif - } - else if (!title.empty()) { - dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), ALARM_COLOR|FONT(XL)); + } else if (!title.empty()) { + dc->drawText(ALERT_TITLE_LEFT, ALERT_TITLE_TOP, title.c_str(), + ALARM_COLOR | FONT(XL)); } if (!message.empty()) { - dc->drawText(ALERT_MESSAGE_LEFT, ALERT_MESSAGE_TOP, message.c_str(), FONT(BOLD)); + dc->drawText(ALERT_MESSAGE_LEFT, ALERT_MESSAGE_TOP, message.c_str(), + FONT(BOLD)); } if (!action.empty()) { - dc->drawText(LCD_W / 2, ALERT_ACTION_TOP, action.c_str(), CENTERED | FONT(BOLD)); + dc->drawText(LCD_W / 2, ALERT_ACTION_TOP, action.c_str(), + CENTERED | FONT(BOLD)); + } else if (type == WARNING_TYPE_CONFIRM) { + + LcdFlags flags = FONT(BOLD); + int w = getTextWidth(STR_OK, flags); + + dc->drawText(ALERT_MESSAGE_LEFT, ALERT_ACTION_TOP, + STR_OK, flags); + + dc->drawText(ALERT_MESSAGE_LEFT + w + 20, ALERT_ACTION_TOP, + STR_EXIT, flags); } } @@ -152,9 +176,41 @@ void FullScreenDialog::runForever() deleteLater(); } +void FullScreenDialog::runForeverNoPwrCheck() +{ + running = true; + + while (running) { + checkBacklight(); + WDG_RESET(); + + RTOS_WAIT_MS(1); + MainWindow::instance()->run(false); + } + + deleteLater(); +} + void raiseAlert(const char * title, const char * msg, const char * action, uint8_t sound) { AUDIO_ERROR_MESSAGE(sound); - auto dialog = new FullScreenDialog(WARNING_TYPE_ALERT, title ? title : "", msg ? msg : "", action ? action : ""); + auto dialog = new FullScreenDialog(WARNING_TYPE_ALERT, title ? title : "", + msg ? msg : "", action ? action : ""); dialog->runForever(); } + +// POPUP_CONFIRMATION +bool confirmationDialog(const char* title, const char* msg, bool checkPwr) +{ + bool confirmed = false; + auto dialog = new FullScreenDialog(WARNING_TYPE_CONFIRM, title ? title : "", + msg ? msg : "", "", + [&confirmed]() { confirmed = true; }); + if (checkPwr) { + dialog->runForever(); + } else { + dialog->runForeverNoPwrCheck(); + } + + return confirmed; +} diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.h b/radio/src/gui/colorlcd/fullscreen_dialog.h index aeb1b9140..c97fc81a7 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.h +++ b/radio/src/gui/colorlcd/fullscreen_dialog.h @@ -34,7 +34,9 @@ enum DialogType { class FullScreenDialog : public FormGroup { public: - FullScreenDialog(uint8_t type, std::string title, std::string message = "", std::string action = "", const std::function & confirmHandler = nullptr); + FullScreenDialog(uint8_t type, std::string title, std::string message = "", + std::string action = "", + const std::function& confirmHandler = nullptr); #if defined(DEBUG_WINDOWS) std::string getName() const override @@ -69,6 +71,7 @@ class FullScreenDialog : public FormGroup } void runForever(); + void runForeverNoPwrCheck(); protected: uint8_t type; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 86becb0f8..7ec619735 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2058,9 +2058,12 @@ uint32_t pwrCheck() { #if !defined(COLORLCD) + lcdRefreshWait(); lcdClear(); + POPUP_CONFIRMATION(STR_MODEL_SHUTDOWN, nullptr); + #if defined(SHUTDOWN_CONFIRMATION) if (TELEMETRY_STREAMING() && !g_eeGeneral.disableRssiPoweroffAlarm) { SET_WARNING_INFO(STR_MODEL_STILL_POWERED, sizeof(TR_MODEL_STILL_POWERED), 0); @@ -2068,6 +2071,7 @@ uint32_t pwrCheck() #else SET_WARNING_INFO(STR_MODEL_STILL_POWERED, sizeof(TR_MODEL_STILL_POWERED), 0); #endif + event_t evt = getEvent(false); DISPLAY_WARNING(evt); LED_ERROR_BEGIN(); @@ -2085,8 +2089,22 @@ uint32_t pwrCheck() LED_ERROR_END(); return e_power_on; } -#endif +#else // COLORLCD + + // TODO: abort dialog condition (here, RSSI lost) + if (confirmationDialog(STR_MODEL_SHUTDOWN, STR_MODEL_STILL_POWERED, false)) { + pwr_check_state = PWR_CHECK_OFF; + return e_power_off; + } else { + // shutdown has been cancelled + pwr_check_state = PWR_CHECK_PAUSED; + LED_ERROR_END(); + return e_power_on; + } + +#endif // COLORLCD } + haptic.play(15, 3, PLAY_NOW); pwr_check_state = PWR_CHECK_OFF; return e_power_off; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 3dcce843b..18c2c7bcb 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -460,29 +460,41 @@ uint16_t evalChkSum(); void alert(const char * title, const char * msg, uint8_t sound); #if !defined(GUI) + #define RAISE_ALERT(...) #define ALERT(...) -#elif defined(COLORLCD) - void raiseAlert(const char * title, const char * msg, const char * info, uint8_t sound); - inline void RAISE_ALERT(const char * title, const char * msg, const char * info, uint8_t sound) - { - raiseAlert(title, msg, info, sound); - } - inline void ALERT(const char * title, const char * msg, uint8_t sound) - { - raiseAlert(title, msg, "", sound); - } -#else - inline void RAISE_ALERT(const char * title, const char * msg, const char * info, uint8_t sound) - { - showAlertBox(title, msg, info, sound); - } - inline void ALERT(const char * title, const char * msg, uint8_t sound) - { - alert(title, msg, sound); - } -#endif +#elif defined(COLORLCD) + +bool confirmationDialog(const char *title, const char *msg, bool checkPwr = true); + +void raiseAlert(const char *title, const char *msg, const char *info, + uint8_t sound); + +inline void RAISE_ALERT(const char *title, const char *msg, const char *info, + uint8_t sound) +{ + raiseAlert(title, msg, info, sound); +} +inline void ALERT(const char *title, const char *msg, uint8_t sound) +{ + raiseAlert(title, msg, "", sound); +} + +#else // !COLORLCD && GUI + +inline void RAISE_ALERT(const char *title, const char *msg, const char *info, + uint8_t sound) +{ + showAlertBox(title, msg, info, sound); +} + +inline void ALERT(const char *title, const char *msg, uint8_t sound) +{ + alert(title, msg, sound); +} + +#endif // !COLORLCD && GUI enum PerOutMode { e_perout_mode_normal = 0, From bcdafb1b42eee9142dc8a9f684de196874b8f063 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 10:48:43 +0200 Subject: [PATCH 103/114] Fix b/w compilation targets --- radio/src/opentx.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 18c2c7bcb..44880f5bb 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1020,7 +1020,10 @@ union ReusableBuffer #if defined(EEPROM_RLC) && LCD_W < 212 uint16_t eepromfree; #endif -#if !defined(SDCARD) +#if defined(SDCARD) && !defined(COLORLCD) + char menu_bss[POPUP_MENU_MAX_LINES][MENU_LINE_LENGTH]; + char mainname[45]; // because reused for SD backup / restore, max backup filename 44 chars: "/MODELS/MODEL0134353-2014-06-19-04-51-27.bin" +#elif !defined(COLORLCD) char mainname[LEN_MODEL_NAME]; #endif } modelsel; From 273ab9bfeee80a880a7dffb9142841dcf2d4b812 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 11:16:53 +0200 Subject: [PATCH 104/114] Fix minor compilation issues --- radio/src/targets/simu/simpgmspace.cpp | 2 ++ radio/src/tests/gtests.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index eb032971b..a6317dc61 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -186,7 +186,9 @@ void simuStart(bool tests, const char * sdPath, const char * settingsPath) return; stopPulses(); +#if !defined(COLORLCD) menuLevel = 0; +#endif simu_start_mode = (tests ? 0 : OPENTX_START_NO_SPLASH | OPENTX_START_NO_CALIBRATION | OPENTX_START_NO_CHECKS); simu_shutdown = false; diff --git a/radio/src/tests/gtests.cpp b/radio/src/tests/gtests.cpp index 2deb948ea..53022b8b9 100644 --- a/radio/src/tests/gtests.cpp +++ b/radio/src/tests/gtests.cpp @@ -163,7 +163,9 @@ int main(int argc, char **argv) #if defined(EEPROM_SIZE) eeprom = (uint8_t *)malloc(EEPROM_SIZE); #endif +#if !defined(COLORLCD) menuLevel = 0; +#endif InitGoogleTest(&argc, argv); // use --verbose option to revert to gtest's default output format From 4fe4c1a385139be55efda26ffea82de6bb31612f Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 12:59:02 +0200 Subject: [PATCH 105/114] Added confirmation dialog on power down and USB connected. --- radio/src/opentx.cpp | 15 ++++++++++++--- radio/src/translations.cpp | 1 + radio/src/translations.h | 1 + radio/src/translations/cn.h.txt | 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 | 1 + radio/src/translations/se.h.txt | 1 + radio/src/translations/tw.h.txt | 1 + 16 files changed, 27 insertions(+), 3 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 7ec619735..99278dc3d 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2053,7 +2053,8 @@ uint32_t pwrCheck() #if defined(SHUTDOWN_CONFIRMATION) while (1) #else - while ((TELEMETRY_STREAMING() && !g_eeGeneral.disableRssiPoweroffAlarm)) + while (usbPlugged() || + (TELEMETRY_STREAMING() && !g_eeGeneral.disableRssiPoweroffAlarm)) #endif { @@ -2091,8 +2092,16 @@ uint32_t pwrCheck() } #else // COLORLCD - // TODO: abort dialog condition (here, RSSI lost) - if (confirmationDialog(STR_MODEL_SHUTDOWN, STR_MODEL_STILL_POWERED, false)) { + const char* message = nullptr; + if (usbPlugged()) { + message = STR_USB_STILL_CONNECTED; + } + else { + message = STR_MODEL_STILL_POWERED; + } + + // TODO: abort dialog condition (here, RSSI lost / USB connected) + if (confirmationDialog(STR_MODEL_SHUTDOWN, message, false)) { pwr_check_state = PWR_CHECK_OFF; return e_power_off; } else { diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index bfb415b13..05c129587 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -188,6 +188,7 @@ const char STR_MEMORYWARNING[] = TR_MEMORYWARNING; const char STR_ALARMWARNING[] = TR_ALARMWARNING; const char STR_RSSI_SHUTDOWN_ALARM[] = TR_RSSI_SHUTDOWN_ALARM; const char STR_MODEL_STILL_POWERED[] = TR_MODEL_STILL_POWERED; +const char STR_USB_STILL_CONNECTED[] = TR_USB_STILL_CONNECTED; const char STR_MODEL_SHUTDOWN[] = TR_MODEL_SHUTDOWN; const char STR_PRESS_ENTER_TO_CONFIRM[] = TR_PRESS_ENTER_TO_CONFIRM; const char STR_THROTTLEREVERSE[] = TR_THROTTLEREVERSE; diff --git a/radio/src/translations.h b/radio/src/translations.h index 2c698c3d2..0de4687ae 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -309,6 +309,7 @@ extern const char STR_MEMORYWARNING[]; extern const char STR_ALARMWARNING[]; extern const char STR_RSSI_SHUTDOWN_ALARM[]; extern const char STR_MODEL_STILL_POWERED[]; +extern const char STR_USB_STILL_CONNECTED[]; extern const char STR_MODEL_SHUTDOWN[]; extern const char STR_PRESS_ENTER_TO_CONFIRM[]; extern const char STR_THROTTLEREVERSE[]; diff --git a/radio/src/translations/cn.h.txt b/radio/src/translations/cn.h.txt index 4a2cc6617..ca945f4c8 100644 --- a/radio/src/translations/cn.h.txt +++ b/radio/src/translations/cn.h.txt @@ -451,6 +451,7 @@ #define TR_ALARMWARNING "静音" #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "关机时检查RSSI") #define TR_MODEL_STILL_POWERED "模型未断电" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "关机 ?" #define TR_PRESS_ENTER_TO_CONFIRM "按ENTER键确认" #define TR_THROTTLE_LABEL "油门" diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index f15a00813..a866cb937 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -536,6 +536,7 @@ #define TR_ALARMWARNING TR3("Vypnutý zvuk", "Upozornit na vypnutý zvuk", "Upozornit na vyp. zvuk") #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi při vyp.", "Hlídat Rssi při vypnutí") #define TR_MODEL_STILL_POWERED "Model stále spuštěn" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Vypnout ?" #define TR_PRESS_ENTER_TO_CONFIRM "Zmáčkni enter pro potvrzení" #define TR_THROTTLE_LABEL "Plyn" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 8bfc59c6f..a6bd8d297 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -542,6 +542,7 @@ #define TR_RSSI_SHUTDOWN_ALARM TR(INDENT "RSSI-Chk aus?", INDENT "Prüfe RSSI bei Ausschalten") #define TR_FLYSKY_TELEMETRY TR("FlySky RSSI #", "Use FlySky RSSI value without rescalling") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Gas-Kontrolle" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 249e07bd3..9f02dc4e0 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -540,6 +540,7 @@ #define TR_ALARMWARNING "Sound off" #define TR_RSSI_SHUTDOWN_ALARM TR("RSSI shutdown", "Check RSSI on shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Throttle" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 17cffb04c..b0d630ff0 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -539,6 +539,7 @@ #define TR_ALARMWARNING "Sin sonido" #define TR_RSSI_SHUTDOWN_ALARM TR("Apagado Rssi", "Check Rssi al apagar") #define TR_MODEL_STILL_POWERED "Modelo aun encendido" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Apagar ?" #define TR_PRESS_ENTER_TO_CONFIRM "Enter para confirmar" #define TR_THROTTLE_LABEL "Potencia" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 452971fee..db6a8287d 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -553,6 +553,7 @@ #define TR_ALARMWARNING "Sound Off" #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "Check Rssi on Shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Throttle" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 8e9912197..96eccac8f 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -560,6 +560,7 @@ #define TR_RSSI_SHUTDOWN_ALARM TR("RSSI extinct.", "Vérif RSSI à l'extinction") #define TR_FLYSKY_TELEMETRY TR("FlySky RSSI #", "Use FlySky RSSI value without rescalling") #define TR_MODEL_STILL_POWERED TR("Modèle allumé", "Modèle encore allumé") +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Eteindre ?" #define TR_PRESS_ENTER_TO_CONFIRM "Presser [Enter] pour confirmer" #define TR_THROTTLE_LABEL "Gaz" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 0668d3c6b..f6f4adac2 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -564,6 +564,7 @@ #define TR_ALARMWARNING INDENT "Spegni suono" #define TR_RSSI_SHUTDOWN_ALARM TR(INDENT "RSSI Shut.", INDENT "Control. RSSI al Shutdown") #define TR_MODEL_STILL_POWERED "Ricevente ancora connessa" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown?" #define TR_PRESS_ENTER_TO_CONFIRM "Premi [ENT] per confermare" #define TR_THROTTLE_LABEL "Motore" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index e8e626ee3..fc39d9eb2 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -541,6 +541,7 @@ #define TR_ALARMWARNING TR("Al Geluid uit?", "Al het geluid uit?") #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "Check Rssi on Shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Gas" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 4eff1c65e..933ad87ee 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -560,6 +560,7 @@ #define TR_ALARMWARNING "Wyłącz dźwięk" #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "Check Rssi on Shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Gaz " diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 4ec39d8a0..abd610af5 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -557,6 +557,7 @@ #define TR_ALARMWARNING "Som Off" #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "Check Rssi on Shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Throttle" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index ba8e0892a..abf63efbe 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -562,6 +562,7 @@ #define TR_ALARMWARNING "Ljud Av" #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "Check Rssi on Shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_THROTTLE_LABEL "Gas" diff --git a/radio/src/translations/tw.h.txt b/radio/src/translations/tw.h.txt index 4e6ad979c..ea30246bd 100644 --- a/radio/src/translations/tw.h.txt +++ b/radio/src/translations/tw.h.txt @@ -451,6 +451,7 @@ #define TR_ALARMWARNING "靜音" #define TR_RSSI_SHUTDOWN_ALARM TR("Rssi Shutdown", "關機時檢查RSSI") #define TR_MODEL_STILL_POWERED "模型未斷電" +#define TR_USB_STILL_CONNECTED "USB still connected" #define TR_MODEL_SHUTDOWN "關機 ?" #define TR_PRESS_ENTER_TO_CONFIRM "按ENTER鍵確認" #define TR_THROTTLE_LABEL "油門" From 0bb9994ac54f771c12d573ce995bd1f57c6f18c6 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 15:06:39 +0200 Subject: [PATCH 106/114] Allow disabling USB connection by discarding the pop-up menu --- .../src/gui/colorlcd/layouts/topbar_impl.cpp | 11 ++- radio/src/main.cpp | 73 +++++++++++++++---- radio/src/opentx.cpp | 2 +- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp index 70cbd56dc..e45e68def 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp @@ -90,11 +90,16 @@ void TopbarImpl::paint(BitmapBuffer * dc) // USB icon if (usbPlugged()) { - dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, MENU_COLOR); - } + LcdFlags flags = MENU_COLOR; + if (getSelectedUsbMode() == USB_UNSELECTED_MODE) { + flags = MENU_TITLE_DISABLE_COLOR; + } + + dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, flags); + } // Logs - if (isFunctionActive(FUNCTION_LOGS) && !usbPlugged() && BLINK_ON_PHASE) { + else if (isFunctionActive(FUNCTION_LOGS) && BLINK_ON_PHASE) { dc->drawBitmapPattern(LCD_W - 98, 6, LBM_DOT, MENU_COLOR); } diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 414e5f642..f80aac096 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -30,30 +30,49 @@ uint8_t currentBacklightBright = 0; uint8_t requiredBacklightBright = 0; uint8_t mainRequestFlags = 0; +static bool _usbDisabled = false; + #if defined(LIBOPENUI) +static Menu* _usbMenu = nullptr; + +void closeUsbMenu() +{ + if (_usbMenu && !usbPlugged()) { + + // USB has been unplugged meanwhile + _usbMenu->deleteLater(); + } +} + void openUsbMenu() { - static Menu * menu = nullptr; - if (menu) - return; - menu = new Menu(MainWindow::instance()); - menu->setCloseHandler([]() { - menu = nullptr; + if (_usbMenu || _usbDisabled) return; + + _usbMenu = new Menu(MainWindow::instance()); + + _usbMenu->setCloseHandler([]() { + _usbMenu = nullptr; + if (usbPlugged() && (getSelectedUsbMode() == USB_UNSELECTED_MODE)) { + _usbDisabled = true; + } }); - menu->setTitle("USB"); - menu->addLine(STR_USB_JOYSTICK, [] { + + _usbMenu->setTitle("USB"); + _usbMenu->addLine(STR_USB_JOYSTICK, [] { setSelectedUsbMode(USB_JOYSTICK_MODE); }); - menu->addLine(STR_USB_MASS_STORAGE, [] { + _usbMenu->addLine(STR_USB_MASS_STORAGE, [] { setSelectedUsbMode(USB_MASS_STORAGE_MODE); }); #if defined(DEBUG) - menu->addLine(STR_USB_SERIAL, [] { + _usbMenu->addLine(STR_USB_SERIAL, [] { setSelectedUsbMode(USB_SERIAL_MODE); }); #endif } + #elif defined(STM32) + void onUSBConnectMenu(const char *result) { if (result == STR_USB_MASS_STORAGE) { @@ -65,6 +84,9 @@ void onUSBConnectMenu(const char *result) else if (result == STR_USB_SERIAL) { setSelectedUsbMode(USB_SERIAL_MODE); } + else if (result == STR_EXIT) { + _disableUsb = true; + } } void openUsbMenu() @@ -77,12 +99,32 @@ void openUsbMenu() POPUP_MENU_TITLE(STR_SELECT_MODE); POPUP_MENU_START(onUSBConnectMenu); } + +void closeUsbMenu() +{ +} + #endif void handleUsbConnection() { #if defined(STM32) && !defined(SIMU) - if (!usbStarted() && usbPlugged()) { + + static bool _pluggedUsb = false; + + if (_pluggedUsb && !usbPlugged()) { + TRACE("USB unplugged"); + closeUsbMenu(); + _pluggedUsb = false; + } + else if (!_pluggedUsb && usbPlugged()) { + TRACE("USB plugged"); + _pluggedUsb = true; + _usbDisabled = false; + } + + if (!_usbDisabled && !usbStarted() && usbPlugged()) { + if (getSelectedUsbMode() == USB_UNSELECTED_MODE) { if (g_eeGeneral.USBMode == USB_UNSELECTED_MODE) { openUsbMenu(); @@ -423,7 +465,7 @@ void perMain() checkSpeakerVolume(); - if (!usbPlugged()) { + if (!usbPlugged() || (getSelectedUsbMode() == USB_UNSELECTED_MODE)) { checkEeprom(); logsWrite(); } @@ -458,14 +500,17 @@ void perMain() #endif #if defined(STM32) - if (!usbPlugged() && SD_CARD_PRESENT() && !sdMounted()) { + if ((!usbPlugged() || (getSelectedUsbMode() == USB_UNSELECTED_MODE)) + && SD_CARD_PRESENT() && !sdMounted()) { sdMount(); } #endif #if !defined(EEPROM) // In case the SD card is removed during the session - if (!usbPlugged() && !SD_CARD_PRESENT() && !globalData.unexpectedShutdown) { + if ((!usbPlugged() || (getSelectedUsbMode() == USB_UNSELECTED_MODE)) + && !SD_CARD_PRESENT() && !globalData.unexpectedShutdown) { + drawFatalErrorScreen(STR_NO_SDCARD); return; } diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 99278dc3d..710ac0a9b 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2053,7 +2053,7 @@ uint32_t pwrCheck() #if defined(SHUTDOWN_CONFIRMATION) while (1) #else - while (usbPlugged() || + while ((usbPlugged() && getSelectedUsbMode() != USB_UNSELECTED_MODE) || (TELEMETRY_STREAMING() && !g_eeGeneral.disableRssiPoweroffAlarm)) #endif { From b96faad9086f428f1af05290d7850b9266a28b5a Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 15:59:38 +0200 Subject: [PATCH 107/114] Clean-up + fix + debug --- radio/src/main.cpp | 19 +++++++++++++++++-- radio/src/targets/horus/lcd_driver.cpp | 2 -- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/radio/src/main.cpp b/radio/src/main.cpp index f80aac096..09f2004a0 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -52,20 +52,27 @@ void openUsbMenu() _usbMenu->setCloseHandler([]() { _usbMenu = nullptr; + }); + + _usbMenu->setCancelHandler([]() { if (usbPlugged() && (getSelectedUsbMode() == USB_UNSELECTED_MODE)) { + TRACE("disable USB"); _usbDisabled = true; } }); _usbMenu->setTitle("USB"); _usbMenu->addLine(STR_USB_JOYSTICK, [] { + TRACE("USB set joystick"); setSelectedUsbMode(USB_JOYSTICK_MODE); }); _usbMenu->addLine(STR_USB_MASS_STORAGE, [] { + TRACE("USB mass storage"); setSelectedUsbMode(USB_MASS_STORAGE_MODE); }); #if defined(DEBUG) _usbMenu->addLine(STR_USB_SERIAL, [] { + TRACE("USB serial"); setSelectedUsbMode(USB_SERIAL_MODE); }); #endif @@ -85,7 +92,7 @@ void onUSBConnectMenu(const char *result) setSelectedUsbMode(USB_SERIAL_MODE); } else if (result == STR_EXIT) { - _disableUsb = true; + _usbDisabled = true; } } @@ -133,21 +140,29 @@ void handleUsbConnection() setSelectedUsbMode(g_eeGeneral.USBMode); } } - else { + + // Mode might have been selected in previous block + // so re-evaluate the condition + if (getSelectedUsbMode() != USB_UNSELECTED_MODE) { + if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE) { opentxClose(false); usbPluggedIn(); } + usbStart(); + TRACE("USB started"); } } if (usbStarted() && !usbPlugged()) { usbStop(); + TRACE("USB stopped"); if (getSelectedUsbMode() == USB_MASS_STORAGE_MODE) { opentxResume(); pushEvent(EVT_ENTRY); } + TRACE("reset selected USB mode"); setSelectedUsbMode(USB_UNSELECTED_MODE); } #endif // defined(STM32) && !defined(SIMU) diff --git a/radio/src/targets/horus/lcd_driver.cpp b/radio/src/targets/horus/lcd_driver.cpp index 0be902b46..4d7399a18 100644 --- a/radio/src/targets/horus/lcd_driver.cpp +++ b/radio/src/targets/horus/lcd_driver.cpp @@ -422,7 +422,6 @@ void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_ srcy = srch - (srcy + h); #endif - TRACE("------"); DMA2D_DeInit(); DMA2D_InitTypeDef DMA2D_InitStruct; @@ -473,7 +472,6 @@ void DMACopyAlphaMask(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t srcy = srch - (srcy + h); #endif - TRACE("++++++"); DMA2D_DeInit(); DMA2D_InitTypeDef DMA2D_InitStruct; From 6eb441d26610b7d14a8ab0f6f345fee8176368dc Mon Sep 17 00:00:00 2001 From: olliw42 Date: Thu, 20 May 2021 13:45:38 +0200 Subject: [PATCH 108/114] better/correct handling of long button presses --- radio/src/gui/colorlcd/tabsgroup.cpp | 2 +- radio/src/gui/colorlcd/view_main.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index 240ff1ba5..b6058da55 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -173,7 +173,7 @@ void TabsGroup::onEvent(event_t event) uint8_t current = header.carousel.getCurrentIndex() + 1; setCurrentTab(current >= tabs.size() ? 0 : current); } -#if defined(KEYS_GPIO_REG_UP) +#if defined(KEYS_GPIO_REG_DGUP) else if (event == EVT_KEY_BREAK(KEY_PGUP)) { #else else if (event == EVT_KEY_LONG(KEY_PGDN)) { diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 6706775c7..6b652f619 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -257,12 +257,12 @@ bool ViewMain::onTouchEnd(coord_t x, coord_t y) void ViewMain::onEvent(event_t event) { switch (event) { - case EVT_KEY_BREAK(KEY_MODEL): + case EVT_KEY_LONG(KEY_MODEL): killEvents(event); new ModelMenu(); break; - case EVT_KEY_BREAK(KEY_RADIO): + case EVT_KEY_LONG(KEY_RADIO): killEvents(event); new RadioMenu(); break; @@ -272,7 +272,7 @@ void ViewMain::onEvent(event_t event) new ScreenMenu(); break; - case EVT_KEY_BREAK(KEY_ENTER): + case EVT_KEY_LONG(KEY_ENTER): killEvents(event); openMenu(); break; @@ -284,7 +284,7 @@ void ViewMain::onEvent(event_t event) //TODO: these need to go away! // -> board code should map the keys as required -#if defined(KEYS_GPIO_REG_UP) +#if defined(KEYS_GPIO_REG_PGUP) case EVT_KEY_BREAK(KEY_PGUP): #else case EVT_KEY_LONG(KEY_PGDN): From 6b0da2b9c50ea3d44c998f2df62610d51ad37606 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Thu, 20 May 2021 15:07:01 +0200 Subject: [PATCH 109/114] ups, killevents missing --- radio/src/gui/colorlcd/tabsgroup.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index b6058da55..aad7b059c 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -170,6 +170,7 @@ void TabsGroup::onEvent(event_t event) TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); if (event == EVT_KEY_BREAK(KEY_PGDN)) { + killEvents(event); uint8_t current = header.carousel.getCurrentIndex() + 1; setCurrentTab(current >= tabs.size() ? 0 : current); } From a186ba2fdca52d68984a7ad46233d7c47920e4ff Mon Sep 17 00:00:00 2001 From: olliw42 Date: Thu, 20 May 2021 15:24:25 +0200 Subject: [PATCH 110/114] it should be break & long, not only break --- radio/src/gui/colorlcd/tabsgroup.cpp | 6 +++++- radio/src/gui/colorlcd/view_main.cpp | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index aad7b059c..1ef642cae 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -169,13 +169,17 @@ void TabsGroup::onEvent(event_t event) { TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); +#if defined(KEYS_GPIO_REG_DGUP) + if (event == EVT_KEY_BREAK(KEY_PGDN) || event == EVT_KEY_LONG(KEY_PGDN)) { +#else if (event == EVT_KEY_BREAK(KEY_PGDN)) { +#endif killEvents(event); uint8_t current = header.carousel.getCurrentIndex() + 1; setCurrentTab(current >= tabs.size() ? 0 : current); } #if defined(KEYS_GPIO_REG_DGUP) - else if (event == EVT_KEY_BREAK(KEY_PGUP)) { + else if (event == EVT_KEY_BREAK(KEY_PGUP) || event == EVT_KEY_LONG(KEY_PGUP)) { #else else if (event == EVT_KEY_LONG(KEY_PGDN)) { #endif diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 6b652f619..0e6c57f94 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -278,6 +278,9 @@ void ViewMain::onEvent(event_t event) break; case EVT_KEY_BREAK(KEY_PGDN): +#if defined(KEYS_GPIO_REG_PGUP) + case EVT_KEY_LONG(KEY_PGDN): +#endif killEvents(event); nextMainView(); break; @@ -286,6 +289,7 @@ void ViewMain::onEvent(event_t event) // -> board code should map the keys as required #if defined(KEYS_GPIO_REG_PGUP) case EVT_KEY_BREAK(KEY_PGUP): + case EVT_KEY_LONG(KEY_PGUP): #else case EVT_KEY_LONG(KEY_PGDN): #endif From 09630ed4ffee250ccc6507a3eedd8cbc5e122288 Mon Sep 17 00:00:00 2001 From: olliw42 Date: Thu, 20 May 2021 23:01:27 +0200 Subject: [PATCH 111/114] change to short i.e. first correct DGUP to PGUP (thx to raphaelcoeffic) --- radio/src/gui/colorlcd/tabsgroup.cpp | 10 +++++----- radio/src/gui/colorlcd/view_main.cpp | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index 1ef642cae..3484d1187 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -169,8 +169,8 @@ void TabsGroup::onEvent(event_t event) { TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); -#if defined(KEYS_GPIO_REG_DGUP) - if (event == EVT_KEY_BREAK(KEY_PGDN) || event == EVT_KEY_LONG(KEY_PGDN)) { +#if defined(KEYS_GPIO_REG_PGUP) + if (event == EVT_KEY_FIRST(KEY_PGDN)) { #else if (event == EVT_KEY_BREAK(KEY_PGDN)) { #endif @@ -178,8 +178,8 @@ void TabsGroup::onEvent(event_t event) uint8_t current = header.carousel.getCurrentIndex() + 1; setCurrentTab(current >= tabs.size() ? 0 : current); } -#if defined(KEYS_GPIO_REG_DGUP) - else if (event == EVT_KEY_BREAK(KEY_PGUP) || event == EVT_KEY_LONG(KEY_PGUP)) { +#if defined(KEYS_GPIO_REG_PGUP) + else if (event == EVT_KEY_FIRST(KEY_PGUP)) { #else else if (event == EVT_KEY_LONG(KEY_PGDN)) { #endif @@ -187,7 +187,7 @@ void TabsGroup::onEvent(event_t event) uint8_t current = header.carousel.getCurrentIndex(); setCurrentTab(current == 0 ? tabs.size() - 1 : current - 1); } - else if (event == EVT_KEY_LONG(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) { + else if (event == EVT_KEY_FIRST(KEY_EXIT)) { killEvents(event); ViewMain::instance()->setFocus(SET_FOCUS_DEFAULT); deleteLater(); diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 0e6c57f94..17fd8f729 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -257,29 +257,30 @@ bool ViewMain::onTouchEnd(coord_t x, coord_t y) void ViewMain::onEvent(event_t event) { switch (event) { - case EVT_KEY_LONG(KEY_MODEL): + case EVT_KEY_FIRST(KEY_MODEL): killEvents(event); new ModelMenu(); break; - case EVT_KEY_LONG(KEY_RADIO): + case EVT_KEY_FIRST(KEY_RADIO): killEvents(event); new RadioMenu(); break; - case EVT_KEY_LONG(KEY_TELEM): + case EVT_KEY_FIRST(KEY_TELEM): killEvents(event); new ScreenMenu(); break; - case EVT_KEY_LONG(KEY_ENTER): + case EVT_KEY_FIRST(KEY_ENTER): killEvents(event); openMenu(); break; - case EVT_KEY_BREAK(KEY_PGDN): #if defined(KEYS_GPIO_REG_PGUP) - case EVT_KEY_LONG(KEY_PGDN): + case EVT_KEY_FIRST(KEY_PGDN): +#else + case EVT_KEY_BREAK(KEY_PGDN): #endif killEvents(event); nextMainView(); @@ -288,8 +289,7 @@ void ViewMain::onEvent(event_t event) //TODO: these need to go away! // -> board code should map the keys as required #if defined(KEYS_GPIO_REG_PGUP) - case EVT_KEY_BREAK(KEY_PGUP): - case EVT_KEY_LONG(KEY_PGUP): + case EVT_KEY_FIRST(KEY_PGUP): #else case EVT_KEY_LONG(KEY_PGDN): #endif From efdf76a9f5ee9acbb090a7b0fe35be5b6b84626c Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 23 May 2021 09:04:19 +0200 Subject: [PATCH 112/114] Updated libopenui And fix the view main menu issue with this PR. --- radio/src/gui/colorlcd/select_fab_carousel.cpp | 10 +++------- radio/src/thirdparty/libopenui | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/radio/src/gui/colorlcd/select_fab_carousel.cpp b/radio/src/gui/colorlcd/select_fab_carousel.cpp index 61869d711..e188caab7 100644 --- a/radio/src/gui/colorlcd/select_fab_carousel.cpp +++ b/radio/src/gui/colorlcd/select_fab_carousel.cpp @@ -36,14 +36,10 @@ void SelectFabCarousel::setMaxButtons(uint8_t max) void SelectFabCarousel::addButton(uint8_t icon, const char* title, std::function pressHandler) { - coord_t y_pos = 0;//SELECT_BUTTON_BORDER; - coord_t x_pos = pageWidth * buttons;// + SELECT_BUTTON_BORDER / 2; + coord_t y_pos = 0; + coord_t x_pos = pageWidth * buttons; buttons++; - /*auto button =*/ new SelectFabButton(this, x_pos, y_pos, icon, title, pressHandler); + new SelectFabButton(this, x_pos, y_pos, icon, title, pressHandler); setInnerWidth(pageWidth * buttons); - - // y_pos += button->width() + SELECT_BUTTON_BORDER; - // setHeight(y_pos); - // setInnerHeight(y_pos); } diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 1c558559e..1930a0308 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 1c558559eba805233b1876c43dd8ffb46673191e +Subproject commit 1930a03088dbb155528f0c6cb524e30e93799626 From d83f8e12fae5589f59ad5949187a1177370fd3ee Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 17:50:47 +0200 Subject: [PATCH 113/114] Catch touch-end in MessageDialog Resolves #72 --- radio/src/gui/colorlcd/message_dialog.cpp | 17 +++++++++++++---- radio/src/thirdparty/libopenui | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/radio/src/gui/colorlcd/message_dialog.cpp b/radio/src/gui/colorlcd/message_dialog.cpp index 3b26161f0..2c1cfe992 100644 --- a/radio/src/gui/colorlcd/message_dialog.cpp +++ b/radio/src/gui/colorlcd/message_dialog.cpp @@ -20,11 +20,20 @@ #include "message_dialog.h" #include "static.h" -MessageDialog::MessageDialog(Window * parent, const char * title, const char * message, const char * info): - Dialog(parent, title, {50, 73, LCD_W - 100, LCD_H - 146}) +MessageDialog::MessageDialog(Window* parent, const char* title, + const char* message, const char* info) : + Dialog(parent, title, {50, 73, LCD_W - 100, LCD_H - 146}) { - messageWidget = new StaticText(this, {0, coord_t(height() - PAGE_LINE_HEIGHT) / 2, width(), PAGE_LINE_HEIGHT}, message, 0, CENTERED); - infoWidget = new StaticText(this, {0, 30 + coord_t(height() - PAGE_LINE_HEIGHT) / 2, width(), PAGE_LINE_HEIGHT}, info, 0, CENTERED); + messageWidget = new StaticText( + this, + {0, coord_t(height() - PAGE_LINE_HEIGHT) / 2, width(), PAGE_LINE_HEIGHT}, + message, 0, CENTERED); + + infoWidget = new StaticText(this, + {0, 30 + coord_t(height() - PAGE_LINE_HEIGHT) / 2, + width(), PAGE_LINE_HEIGHT}, + info, 0, CENTERED); + setCloseWhenClickOutside(true); } #if defined(HARDWARE_KEYS) diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 1930a0308..c072dca43 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 1930a03088dbb155528f0c6cb524e30e93799626 +Subproject commit c072dca43c232ab23c95035ec7b879cf84a64810 From 5f23d35e2c2ff3a7f12423eb90c9d98d0dd69e3e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 24 May 2021 19:41:55 +0200 Subject: [PATCH 114/114] SetupTopBarWidgetsPage: forward touch-slide to children windows Resolves #73 --- radio/src/gui/colorlcd/topbar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index 5c935ec9b..fe18dd59f 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -88,6 +88,7 @@ bool SetupTopBarWidgetsPage::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) { + Window::onTouchSlide(x, y, startX, startY, slideX, slideY); return true; }