From 8d78db4a6e49076a6247abd0a58f4ab4ec866209 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 18 Sep 2019 11:58:04 +0200 Subject: [PATCH 001/257] Flysky telem quick fix (#6801) Flysky telem quick fix --- radio/src/telemetry/flysky_ibus.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index d4b00c995..a38354605 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -45,9 +45,10 @@ struct FlySkySensor { #define TX_RSSI_ID 300 // Pseudo id outside 1 byte range of FlySky sensors #define FS_ID_TEMP 0x01 -#define FS_ID_SNR 0xfa -#define FS_ID_NOISE 0xfb -#define FS_ID_RSSI 0xfc +#define FS_ID_SNR 0xFA +#define FS_ID_NOISE 0xFB +#define FS_ID_RSSI 0xFC +#define FS_ID_ERR 0xFE const FlySkySensor flySkySensors[] = { @@ -66,7 +67,7 @@ const FlySkySensor flySkySensors[] = { // RX RSSI (0xfc) {FS_ID_RSSI, ZSTR_RSSI, UNIT_DB, 0}, // RX error rate - {0xfe, ZSTR_RX_QUALITY, UNIT_RAW, 0}, + {FS_ID_ERR, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // 0xff is an unused sensor slot // Pseudo sensor for TRSSI {TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_RAW, 0}, @@ -91,6 +92,10 @@ static void processFlySkySensor(const uint8_t *packet) } if (id == FS_ID_SNR) { + if(value>0) { + value+=20; + telemetryStreaming = TELEMETRY_TIMEOUT10ms; + } telemetryData.rssi.set(value); } @@ -99,7 +104,9 @@ static void processFlySkySensor(const uint8_t *packet) if (sensor->id == id) { // The Noise and Signal sensors that are specified in dB send the absolute value if (id == FS_ID_NOISE || id == FS_ID_RSSI) - value = -value; + value = 135 - value; + else if (id == FS_ID_ERR) // ERR RATE + value = 100 - value; else if (id == FS_ID_TEMP) // Temperature sensors have 40 degree offset value -= 400; @@ -122,7 +129,6 @@ void processFlySkyPacket(const uint8_t *packet) int index = 1 + (4 * sensor); processFlySkySensor(packet+index); } - telemetryStreaming = TELEMETRY_TIMEOUT10ms; } void processFlySkyTelemetryData(uint8_t data) From 8ea8cadd038b28963edfb7370fee09d0438f787a Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 18 Sep 2019 11:58:44 +0200 Subject: [PATCH 002/257] Display RSSI when adjusting multi freq (#6802) --- radio/src/gui/128x64/model_setup.cpp | 3 +++ radio/src/gui/212x64/model_setup.cpp | 3 +++ radio/src/gui/480x272/model_setup.cpp | 1 + 3 files changed, 7 insertions(+) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index b59ab5baf..b89afc152 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -1427,6 +1427,9 @@ void menuModelSetup(event_t event) } else { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); + lcdDrawText(MODEL_SETUP_2ND_COLUMN+23, y, "RSSI(", LEFT); + lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT); + lcdDrawText(lcdLastRightPos, y, ")", LEFT); } } } diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 979a27401..4637d8634 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -1253,6 +1253,9 @@ void menuModelSetup(event_t event) } else { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); + lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT); + lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT); + lcdDrawText(lcdLastRightPos, y, ")", LEFT); } } } diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 288d2178e..c759bfb77 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1562,6 +1562,7 @@ bool menuModelSetup(event_t event) } else { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); + lcdDrawNumber(LCD_W-10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")"); } } } From a7bec62dcf7683bea8749c45480726d8d43c36e8 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 18 Sep 2019 17:53:15 +0200 Subject: [PATCH 003/257] RXID should be ignored in D8, like on the radio (#6804) --- companion/src/modelslist.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/companion/src/modelslist.cpp b/companion/src/modelslist.cpp index b106a2896..50950872c 100644 --- a/companion/src/modelslist.cpp +++ b/companion/src/modelslist.cpp @@ -727,7 +727,7 @@ void TreeModel::refresh() protocol = moduleData.protocol; // These are the only RXs that allow nominating RX # but changing RX or copying models can leave residual configuration which can cause issues // if (protocol == PULSES_PXX_XJT_X16 || protocol == PULSES_PXX_XJT_LR12 || protocol == PULSES_PXX_R9M || protocol == PULSES_DSMX || protocol == PULSES_MULTIMODULE) { - if (protocol != PULSES_OFF && moduleData.modelId > 0) { + if ((protocol != PULSES_OFF && protocol != PULSES_PXX_XJT_D8 ) && moduleData.modelId > 0) { if (!rxs.isEmpty()) { rxs.append(", "); } @@ -751,6 +751,9 @@ void TreeModel::refresh() bool TreeModel::isModelIdUnique(unsigned modelIdx, unsigned module, unsigned protocol) { int cnt = 0; + if (protocol== PULSES_PXX_XJT_D8) + return true; + for (auto const& model: radioData->models) { if (!model.isEmpty()) { const ModuleData& moduleData = model.moduleData[module]; From c60d3858d2ef86cf8edacd41c039fb8a668d26e7 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 18 Sep 2019 17:55:51 +0200 Subject: [PATCH 004/257] Allow longer toolsname on wide screens (#6805) --- radio/src/gui/480x272/radio_tools.cpp | 2 +- radio/src/gui/common/stdlcd/radio_tools.cpp | 6 ++---- radio/src/lua/interface.cpp | 4 ++-- radio/src/lua/lua_api.h | 7 ++++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/radio/src/gui/480x272/radio_tools.cpp b/radio/src/gui/480x272/radio_tools.cpp index 283799234..cf560fd71 100644 --- a/radio/src/gui/480x272/radio_tools.cpp +++ b/radio/src/gui/480x272/radio_tools.cpp @@ -49,7 +49,7 @@ void addRadioModuleTool(uint8_t index, const char * label, bool (* tool)(event_t #if defined(LUA) void addRadioScriptTool(uint8_t index, const char * path) { - char toolName[TOOL_NAME_MAXLEN + 1]; + char toolName[RADIO_TOOL_NAME_MAXLEN + 1]; const char * label; char * ext = (char *)getFileExtension(path); if (readToolName(toolName, path)) { diff --git a/radio/src/gui/common/stdlcd/radio_tools.cpp b/radio/src/gui/common/stdlcd/radio_tools.cpp index 9eb478507..1ac177c21 100644 --- a/radio/src/gui/common/stdlcd/radio_tools.cpp +++ b/radio/src/gui/common/stdlcd/radio_tools.cpp @@ -46,15 +46,13 @@ void addRadioModuleTool(uint8_t index, const char * label, void (* tool)(event_t } } -#define TOOL_NAME_MAXLEN 16 - #if defined(LUA) void addRadioScriptTool(uint8_t index, const char * path) { - char toolName[TOOL_NAME_MAXLEN + 1]; + char toolName[RADIO_TOOL_NAME_MAXLEN + 1]; if (!readToolName(toolName, path)) { - strAppendFilename(toolName, getBasename(path), TOOL_NAME_MAXLEN); + strAppendFilename(toolName, getBasename(path), RADIO_TOOL_NAME_MAXLEN); } if (addRadioTool(index, toolName)) { diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index f1bdbe0f6..73b71da62 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -1150,11 +1150,11 @@ bool readToolName(char * toolName, const char * filename) return false; uint8_t len = end - start; - if (len > TOOL_NAME_MAXLEN) + if (len > RADIO_TOOL_NAME_MAXLEN) return false; strncpy(toolName, start, len); - memclear(toolName + len, TOOL_NAME_MAXLEN + 1 - len); + memclear(toolName + len, RADIO_TOOL_NAME_MAXLEN + 1 - len); return true; } diff --git a/radio/src/lua/lua_api.h b/radio/src/lua/lua_api.h index 007e7b8f1..71a1cef01 100644 --- a/radio/src/lua/lua_api.h +++ b/radio/src/lua/lua_api.h @@ -171,7 +171,12 @@ void registerBitmapClass(lua_State * L); void luaSetInstructionsLimit(lua_State* L, int count); int luaLoadScriptFileToState(lua_State * L, const char * filename, const char * mode); -#define TOOL_NAME_MAXLEN 16 +#if LCD_W > 350 + #define RADIO_TOOL_NAME_MAXLEN 40 +#else + #define RADIO_TOOL_NAME_MAXLEN 16 +#endif + bool readToolName(char * toolName, const char * filename); bool isRadioScriptTool(const char * filename); From 70914e4615e7de12dfc3a224373c188579c26f87 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 20 Sep 2019 18:36:50 +0200 Subject: [PATCH 005/257] [X12S] Extra switches could not work --- radio/src/targets/horus/hal.h | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 10e169665..5c07cb7b5 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -195,23 +195,22 @@ // Index of all keys #if defined(PCBX12S) - #define KEYS_GPIOB_PINS (SWITCHES_GPIO_PIN_B_L | SWITCHES_GPIO_PIN_C_L | TRIMS_GPIO_PIN_LSD | TRIMS_GPIO_PIN_LSU) - #define KEYS_GPIOC_PINS (KEYS_GPIO_PIN_PGUP | KEYS_GPIO_PIN_ENTER | KEYS_GPIO_PIN_RIGHT | TRIMS_GPIO_PIN_RHL) - #define KEYS_GPIOD_PINS (SWITCHES_GPIO_PIN_C_H | TRIMS_GPIO_PIN_LHL | TRIMS_GPIO_PIN_LHR | TRIMS_GPIO_PIN_RSU) - #define KEYS_GPIOE_PINS (SWITCHES_GPIO_PIN_E_L) + #define KEYS_GPIOB_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15) + #define KEYS_GPIOC_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_13) + #define KEYS_GPIOD_PINS (GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_13) + #define KEYS_GPIOE_PINS (GPIO_Pin_3) #define KEYS_GPIOG_PINS (KEYS_GPIO_PIN_UP | SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L | SWITCHES_GPIO_PIN_H | TRIMS_GPIO_PIN_RVD) - #define KEYS_GPIOH_PINS (SWITCHES_GPIO_PIN_A_H | SWITCHES_GPIO_PIN_B_H | SWITCHES_GPIO_PIN_E_H | SWITCHES_GPIO_PIN_F | ROTARY_ENCODER_GPIO_PIN_A | ROTARY_ENCODER_GPIO_PIN_B) - #define KEYS_GPIOI_PINS (KEYS_GPIO_PIN_PGDN | KEYS_GPIO_PIN_LEFT | KEYS_GPIO_PIN_DOWN | SWITCHES_GPIO_PIN_A_L | TRIMS_GPIO_PIN_RHR) + #define KEYS_GPIOH_PINS (GPIO_Pin_9 | GPIO_Pin_12 | SWITCHES_GPIO_PIN_E_H | SWITCHES_GPIO_PIN_F | ROTARY_ENCODER_GPIO_PIN_A | ROTARY_ENCODER_GPIO_PIN_B) + #define KEYS_GPIOI_PINS (KEYS_GPIO_PIN_PGDN | KEYS_GPIO_PIN_LEFT | KEYS_GPIO_PIN_DOWN | SWITCHES_GPIO_PIN_A_L | GPIO_Pin_4) #define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_LVD | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RSD) #elif defined(PCBX10) - #define KEYS_GPIOB_PINS (SWITCHES_GPIO_PIN_B_L | SWITCHES_GPIO_PIN_C_L | TRIMS_GPIO_PIN_RSU | TRIMS_GPIO_PIN_RSD | TRIMS_GPIO_PIN_LHL | TRIMS_GPIO_PIN_LHR) - #define KEYS_GPIOC_PINS (TRIMS_GPIO_PIN_LHL) - #define KEYS_GPIOD_PINS (SWITCHES_GPIO_PIN_C_H | TRIMS_GPIO_PIN_RHL | TRIMS_GPIO_PIN_RHR | TRIMS_GPIO_PIN_LSD) - #define KEYS_GPIOE_PINS (SWITCHES_GPIO_PIN_E_L) + #define KEYS_GPIOB_PINS (GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_8 | GPIO_Pin_9) + #define KEYS_GPIOD_PINS (GPIO_Pin_11 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_13) + #define KEYS_GPIOE_PINS (GPIO_Pin_3) #define KEYS_GPIOG_PINS (SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L | SWITCHES_GPIO_PIN_H | TRIMS_GPIO_PIN_LVD) #define KEYS_GPIOH_PINS (GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15) #define KEYS_GPIOI_PINS (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_15) - #define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RVD | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_LSU) + #define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RVD | TRIMS_GPIO_PIN_RVU | GPIO_Pin_8) #endif // ADC From 0afa5ab2e642aa19202dc4426e9d13da67958f9f Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 21 Sep 2019 08:54:15 +0200 Subject: [PATCH 006/257] Add low power warning --- radio/src/opentx.cpp | 19 +++++++++++++++++++ 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 | 1 + radio/src/translations/se.h.txt | 1 + 14 files changed, 32 insertions(+) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 392b2e140..56839a019 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -838,6 +838,21 @@ void checkSDVersion() } #endif +#if defined(MULTIMODULE) +void checkMultiLowPower() +{ + if(isModuleMultimodule(EXTERNAL_MODULE) && g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode) { + ALERT("MULTI", STR_WARN_MULTI_LOWPOWER, AU_ERROR); + return; + } +#if defined(INTERNAL_MODULE_MULTI) + if(isModuleMultimodule(INTERNAL_MODULE) && g_model.moduleData[INTERNAL_MODULE].multi.lowPowerMode) { + ALERT("MULTI", STR_WARN_MULTI_LOWPOWER, AU_ERROR); + } +#endif +} +#endif + #if defined(STM32) static void checkRTCBattery() { @@ -901,6 +916,10 @@ void checkAll() readModelNotes(); } +#if defined(MULTIMODULE) + checkMultiLowPower(); +#endif + if (!waitKeysReleased()) { showMessageBox(STR_KEYSTUCK); tmr10ms_t tgtime = get_tmr10ms() + 500; diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 755842b55..953330f4b 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -354,6 +354,7 @@ const char STR_SWITCHWARN[] = TR_SWITCHWARN; const char STR_FAILSAFEWARN[] = TR_FAILSAFEWARN; const char STR_WRONG_SDCARDVERSION[] = TR_WRONG_SDCARDVERSION; const char STR_WARN_RTC_BATTERY_LOW[] = TR_WARN_RTC_BATTERY_LOW; +const char STR_WARN_MULTI_LOWPOWER[] = TR_WARN_MULTI_LOWPOWER; const char STR_BATTERY[] = TR_BATTERY; const char STR_WRONG_PCBREV[] = TR_WRONG_PCBREV; const char STR_EMERGENCY_MODE[] = TR_EMERGENCY_MODE; diff --git a/radio/src/translations.h b/radio/src/translations.h index f4ad4b962..070c11e66 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -549,6 +549,7 @@ extern const char STR_NIGHTLY_WARNING[]; extern const char STR_NIGHTLY_NOTSAFE[]; extern const char STR_WRONG_SDCARDVERSION[]; extern const char STR_WARN_RTC_BATTERY_LOW[]; +extern const char STR_WARN_MULTI_LOWPOWER[]; extern const char STR_BATTERY[]; extern const char STR_WRONG_PCBREV[]; extern const char STR_EMERGENCY_MODE[]; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 1484da893..9fafd94fc 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -734,6 +734,7 @@ #define TR_NIGHTLY_NOTSAFE "Verze není bezpečná k létání" #define TR_WRONG_SDCARDVERSION "Očekávaná ver.: " #define TR_WARN_RTC_BATTERY_LOW "Slabá RTC baterie" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATERIE" #define TR_WRONG_PCBREV "Jiná verze PCB/firmware" #define TR_EMERGENCY_MODE "NOUZOVÝ REŽIM" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 760f965ab..df30364ad 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -736,6 +736,7 @@ #define TR_NIGHTLY_NOTSAFE "Nicht für Flug geeignet" #define TR_WRONG_SDCARDVERSION TR("Erw. Version: ","Erwartete Version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Falsche PCB erkannt" #define TR_EMERGENCY_MODE "NOTFALL MODUS" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index cfc4b98c1..09c1cb550 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -736,6 +736,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index b566aaba5..357e61043 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -759,6 +759,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 1fbea278b..91d60c84d 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -753,6 +753,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 76d0e796b..89fa1520b 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -756,6 +756,7 @@ #define TR_NIGHTLY_NOTSAFE "Version de test uniq." #define TR_WRONG_SDCARDVERSION "Version requise: " #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "PCB incorrect détecté" #define TR_EMERGENCY_MODE "MODE SECOURS" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 12b11d4bd..d1ece77bc 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -754,6 +754,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index fa6923557..e51d46d90 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -742,6 +742,7 @@ TR_GYR_VSRCRAW #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Verwachte ver: ","Verwachte versie: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Verkeerde PCB gedetecteerd" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index c7972c62c..f3d48063d 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -754,6 +754,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index f45e2fb86..2397ce944 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -744,6 +744,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 6d9358d20..495745665 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -754,6 +754,7 @@ #define TR_SDCARDVERSIONWARN "SD Card Check" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" +#define TR_WARN_MULTI_LOWPOWER "Low Power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" From 87d4e0a9e1111e75794c74c098ed7f29a3d21eb0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 21 Sep 2019 11:20:03 +0200 Subject: [PATCH 007/257] Fix x10 compilation --- radio/src/targets/horus/hal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 5c07cb7b5..a81cbbafd 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -205,6 +205,7 @@ #define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_LVD | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RSD) #elif defined(PCBX10) #define KEYS_GPIOB_PINS (GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_8 | GPIO_Pin_9) + #define KEYS_GPIOC_PINS (GPIO_Pin_8) #define KEYS_GPIOD_PINS (GPIO_Pin_11 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_13) #define KEYS_GPIOE_PINS (GPIO_Pin_3) #define KEYS_GPIOG_PINS (SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L | SWITCHES_GPIO_PIN_H | TRIMS_GPIO_PIN_LVD) From 815981c5618dcaa8c4bdeae489bd1451708293fd Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 21 Sep 2019 15:55:48 +0200 Subject: [PATCH 008/257] Improve AFHDS2A RSSI --- radio/src/telemetry/flysky_ibus.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index a38354605..81190e5d1 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -90,13 +90,12 @@ static void processFlySkySensor(const uint8_t *packet) // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100 id = 0x100; } - - if (id == FS_ID_SNR) { - if(value>0) { - value+=20; - telemetryStreaming = TELEMETRY_TIMEOUT10ms; - } + + if (id == FS_ID_ERR) { // ERR RATE, displayed RQLy and used as RSSI + value = 100 - value; telemetryData.rssi.set(value); + if (value > 0) + telemetryStreaming = TELEMETRY_TIMEOUT10ms; } for (const FlySkySensor * sensor = flySkySensors; sensor->id; sensor++) { @@ -105,8 +104,11 @@ static void processFlySkySensor(const uint8_t *packet) // The Noise and Signal sensors that are specified in dB send the absolute value if (id == FS_ID_NOISE || id == FS_ID_RSSI) value = 135 - value; - else if (id == FS_ID_ERR) // ERR RATE - value = 100 - value; + else if (id == FS_ID_SNR) { + if(value>0) { + value+=20; + } + } else if (id == FS_ID_TEMP) // Temperature sensors have 40 degree offset value -= 400; From 6dc3db392eb1c7e230bba7d28cae21b19452c420 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 23 Sep 2019 00:00:40 +0200 Subject: [PATCH 009/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 68c996281..4b96009dd 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1539,3 +1539,4 @@ Piotr Wysocki Thomas Halenbeck (monthly) Sjoerd Dost Ralph Gustafson +Herbert Feix From d887185427599b05ac9d92a408831ce4a2f05c21 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 23 Sep 2019 09:15:24 +0200 Subject: [PATCH 010/257] [X10] PC.08 is unused --- radio/src/targets/horus/hal.h | 1 - radio/src/targets/horus/keys_driver.cpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index a81cbbafd..5c07cb7b5 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -205,7 +205,6 @@ #define KEYS_GPIOJ_PINS (SWITCHES_GPIO_PIN_D_H | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_LVD | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_RSD) #elif defined(PCBX10) #define KEYS_GPIOB_PINS (GPIO_Pin_12 | GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_8 | GPIO_Pin_9) - #define KEYS_GPIOC_PINS (GPIO_Pin_8) #define KEYS_GPIOD_PINS (GPIO_Pin_11 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_13) #define KEYS_GPIOE_PINS (GPIO_Pin_3) #define KEYS_GPIOG_PINS (SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L | SWITCHES_GPIO_PIN_H | TRIMS_GPIO_PIN_LVD) diff --git a/radio/src/targets/horus/keys_driver.cpp b/radio/src/targets/horus/keys_driver.cpp index 1a04427a4..52d862ad1 100644 --- a/radio/src/targets/horus/keys_driver.cpp +++ b/radio/src/targets/horus/keys_driver.cpp @@ -207,8 +207,10 @@ void keysInit() GPIO_InitStructure.GPIO_Pin = KEYS_GPIOB_PINS; GPIO_Init(GPIOB, &GPIO_InitStructure); +#if defined(KEYS_GPIOC_PINS) GPIO_InitStructure.GPIO_Pin = KEYS_GPIOC_PINS; GPIO_Init(GPIOC, &GPIO_InitStructure); +#endif GPIO_InitStructure.GPIO_Pin = KEYS_GPIOD_PINS; GPIO_Init(GPIOD, &GPIO_InitStructure); From 369f7b70543b66c22df7488e0bc84f4314ae20eb Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 23 Sep 2019 09:47:43 +0200 Subject: [PATCH 011/257] Cosmetics --- radio/src/telemetry/flysky_ibus.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index 81190e5d1..cebb60e78 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -90,7 +90,7 @@ static void processFlySkySensor(const uint8_t *packet) // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100 id = 0x100; } - + if (id == FS_ID_ERR) { // ERR RATE, displayed RQLy and used as RSSI value = 100 - value; telemetryData.rssi.set(value); @@ -104,11 +104,11 @@ static void processFlySkySensor(const uint8_t *packet) // The Noise and Signal sensors that are specified in dB send the absolute value if (id == FS_ID_NOISE || id == FS_ID_RSSI) value = 135 - value; - else if (id == FS_ID_SNR) { - if(value>0) { - value+=20; + else if (id == FS_ID_SNR) { + if (value > 0) { + value += 20; } - } + } else if (id == FS_ID_TEMP) // Temperature sensors have 40 degree offset value -= 400; From 3b171ca3aa2a8d6c515cb8090fe2e3f3831babc1 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 23 Sep 2019 10:10:07 +0200 Subject: [PATCH 012/257] Fix new switches (#6817) --- radio/src/switches.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index f10bc9497..1a405fb05 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -154,6 +154,15 @@ void getSwitchesPosition(bool startup) CHECK_2POS(SW_SH); #endif +#if defined(PCBX9DP) && PCBREV >= 2019 + CHECK_2POS(SW_SI); +#endif + +#if defined(PCBHORUS) || defined(PCBX7) + CHECK_2POS(SW_SI); + CHECK_2POS(SW_SJ); +#endif + #if defined(PCBX9E) CHECK_3POS(6, SW_SI); CHECK_3POS(7, SW_SJ); From 7478358e86858825522c7844c41e60fb2b13f91a Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 23 Sep 2019 10:12:58 +0200 Subject: [PATCH 013/257] Fix multi failsafe been inverted between hold and no pulse (#6815) --- radio/src/pulses/multi.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index babfc4bb1..a84bb04a1 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -59,18 +59,13 @@ static void sendFailsafeChannels(uint8_t port) for (int i = 0; i < MULTI_CHANS; i++) { int16_t failsafeValue = g_model.failsafeChannels[i]; int pulseValue; - if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) - failsafeValue = FAILSAFE_CHANNEL_HOLD; - if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) - failsafeValue = FAILSAFE_CHANNEL_NOPULSE; - - if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { - pulseValue = 0; - } - else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { + if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) { pulseValue = 2047; } + else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) { + pulseValue = 0; + } else { failsafeValue += 2 * PPM_CH_CENTER(g_model.moduleData[port].channelsStart + i) - 2 * PPM_CENTER; pulseValue = limit(1, (failsafeValue * 800 / 1000) + 1024, 2047); From 602a6a1f5d316711a1284fcebc255555340a9b15 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 23 Sep 2019 10:16:23 +0200 Subject: [PATCH 014/257] Cosmetics --- radio/src/mixer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 8905ca00d..ee4406201 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -341,8 +341,8 @@ getvalue_t getValue(mixsrc_t i) } #if defined(PCBTARANIS) || defined(PCBHORUS) - else if ((i >= MIXSRC_FIRST_SWITCH) && (i <= MIXSRC_LAST_SWITCH)) { - mixsrc_t sw = i-MIXSRC_FIRST_SWITCH; + else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_SWITCH) { + mixsrc_t sw = i - MIXSRC_FIRST_SWITCH; if (SWITCH_EXISTS(sw)) { return (switchState(3*sw) ? -1024 : (IS_CONFIG_3POS(sw) && switchState(3*sw+1) ? 0 : 1024)); } From d90bc4fe8dff1774030c2a8dbf5e6c520667bce4 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 23 Sep 2019 10:19:32 +0200 Subject: [PATCH 015/257] Cosmetics --- radio/src/opentx.cpp | 4 ++-- 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 +- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 56839a019..16419655d 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -841,12 +841,12 @@ void checkSDVersion() #if defined(MULTIMODULE) void checkMultiLowPower() { - if(isModuleMultimodule(EXTERNAL_MODULE) && g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode) { + if (isModuleMultimodule(EXTERNAL_MODULE) && g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode) { ALERT("MULTI", STR_WARN_MULTI_LOWPOWER, AU_ERROR); return; } #if defined(INTERNAL_MODULE_MULTI) - if(isModuleMultimodule(INTERNAL_MODULE) && g_model.moduleData[INTERNAL_MODULE].multi.lowPowerMode) { + if (isModuleMultimodule(INTERNAL_MODULE) && g_model.moduleData[INTERNAL_MODULE].multi.lowPowerMode) { ALERT("MULTI", STR_WARN_MULTI_LOWPOWER, AU_ERROR); } #endif diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 9fafd94fc..4c04844cb 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -734,7 +734,7 @@ #define TR_NIGHTLY_NOTSAFE "Verze není bezpečná k létání" #define TR_WRONG_SDCARDVERSION "Očekávaná ver.: " #define TR_WARN_RTC_BATTERY_LOW "Slabá RTC baterie" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATERIE" #define TR_WRONG_PCBREV "Jiná verze PCB/firmware" #define TR_EMERGENCY_MODE "NOUZOVÝ REŽIM" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index df30364ad..ffa5d7a91 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -736,7 +736,7 @@ #define TR_NIGHTLY_NOTSAFE "Nicht für Flug geeignet" #define TR_WRONG_SDCARDVERSION TR("Erw. Version: ","Erwartete Version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Falsche PCB erkannt" #define TR_EMERGENCY_MODE "NOTFALL MODUS" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 09c1cb550..784ce1b4c 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -736,7 +736,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 357e61043..74e8b6d16 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -759,7 +759,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 91d60c84d..4f2e48f8e 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -753,7 +753,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 89fa1520b..3b65b16d2 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -756,7 +756,7 @@ #define TR_NIGHTLY_NOTSAFE "Version de test uniq." #define TR_WRONG_SDCARDVERSION "Version requise: " #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "PCB incorrect détecté" #define TR_EMERGENCY_MODE "MODE SECOURS" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index d1ece77bc..89cf9aaa9 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -754,7 +754,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index e51d46d90..553740a1f 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -742,7 +742,7 @@ TR_GYR_VSRCRAW #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Verwachte ver: ","Verwachte versie: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Verkeerde PCB gedetecteerd" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index f3d48063d..02990fab7 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -754,7 +754,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 2397ce944..898b1b530 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -744,7 +744,7 @@ #define TR_NIGHTLY_NOTSAFE "Version not safe to fly" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 495745665..d9d9deb81 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -754,7 +754,7 @@ #define TR_SDCARDVERSIONWARN "SD Card Check" #define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") #define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low Power mode" +#define TR_WARN_MULTI_LOWPOWER "Low power mode" #define TR_BATTERY "BATTERY" #define TR_WRONG_PCBREV "Wrong PCB detected" #define TR_EMERGENCY_MODE "EMERGENCY MODE" From 38931d9cb61e8d90ab55da683b7f5b983678e814 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 23 Sep 2019 15:29:49 +0200 Subject: [PATCH 016/257] Bsongis/issue 6798 (#6818) * Avoid conversion of unused sensors * Allow conversion of R9M sensors * Conversion fixes in Companion --- .../src/firmwares/opentx/opentxeeprom.cpp | 29 ++++++++++++------- companion/src/firmwares/sensordata.cpp | 22 +++++--------- companion/src/firmwares/sensordata.h | 2 +- companion/src/modeledit/telemetry.cpp | 20 +++++-------- companion/src/modeledit/telemetry_sensor.ui | 13 ++------- .../conversions/conversions_218_219.cpp | 2 +- 6 files changed, 39 insertions(+), 49 deletions(-) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index f13881149..a81457e23 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -1935,16 +1935,25 @@ class SensorField: public TransformedField { void afterImport() override { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) { - sensor.id = _id; - sensor.subid = _subid; - if (model.moduleData[0].isPxx1Module() || model.moduleData[1].isPxx1Module()) - sensor.instance = (_instance & 0x1F) + (version <= 218 ? -1 : 0); // 5 bits instance - else - sensor.instance = _instance & 0x1F; - sensor.rxIdx = (_instance >> 5) & 0x03; // 2 bits Rx idx - sensor.moduleIdx = (_instance >> 7) & 0x1; // 1 bit module idx - sensor.ratio = _ratio; - sensor.offset = _offset; + if (strlen(sensor.label) == 0) { + sensor.clear(); + } + else { + sensor.id = _id; + sensor.subid = _subid; + if (model.moduleData[0].isPxx1Module() || model.moduleData[1].isPxx1Module()) { + sensor.instance = (_instance & 0x1F) + (version <= 218 ? -1 : 0); // 5 bits instance + sensor.rxIdx = 0x03; // 2 bits Rx idx + sensor.moduleIdx = 0x01; // 1 bit module idx + } + else { + sensor.instance = _instance & 0x1F; + sensor.rxIdx = (_instance >> 5) & 0x03; // 2 bits Rx idx + sensor.moduleIdx = (_instance >> 7) & 0x1; // 1 bit module idx + } + sensor.ratio = _ratio; + sensor.offset = _offset; + } } else { sensor.persistentValue = _id; diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index a88f3239a..8d677ed50 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -92,24 +92,16 @@ QString SensorData::nameToString(int index) const return RadioData::getElementName(tr("TELE"), index + 1, label); } -QString SensorData::getRxOrModName(const ModelData* model) const +QString SensorData::getOrigin(const ModelData * model) const { - if ((type != TELEM_TYPE_CUSTOM) || (!id && !instance)) + if (type != TELEM_TYPE_CUSTOM || !id) return QString(); - const ModuleData& module = model->moduleData[moduleIdx]; - - if (module.isPxx2Module()) { - if (module.access.receivers & (1 << rxIdx)) { - return QString(module.access.receiverName[rxIdx]); - } - - // receiver does not seem to be active + const ModuleData & module = model->moduleData[moduleIdx]; + if (module.isPxx2Module() && rxIdx <= 2 && module.access.receivers & (1 << rxIdx)) { + return QString(module.access.receiverName[rxIdx]); + } + else { return QString(); } - - if (moduleIdx) - return tr("Internal"); - - return tr("External"); } diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index 8e95aa7f6..a5cdb4957 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -148,7 +148,7 @@ class SensorData { void updateUnit(); QString unitString() const; QString nameToString(int index) const; - QString getRxOrModName(const ModelData* model) const; + QString getOrigin(const ModelData* model) const; void clear() { memset(this, 0, sizeof(SensorData)); } }; diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp index 39a314fa7..68be10638 100644 --- a/companion/src/modeledit/telemetry.cpp +++ b/companion/src/modeledit/telemetry.cpp @@ -653,9 +653,8 @@ void TelemetrySensorPanel::update() ui->id->hide(); ui->instanceLabel->hide(); ui->instance->hide(); - ui->rxLabel->hide(); - ui->moduleLabel->hide(); - ui->rxOrMod->hide(); + ui->originLabel->hide(); + ui->origin->hide(); ui->formula->show(); ui->formula->setCurrentIndex(sensor.formula); isConfigurable = (sensor.formula < SensorData::TELEM_FORMULA_CELL); @@ -679,13 +678,10 @@ void TelemetrySensorPanel::update() ui->id->show(); ui->instanceLabel->show(); ui->instance->show(); - - bool is_pxx2 = model->moduleData[sensor.moduleIdx].isPxx2Module(); - ui->rxLabel->setVisible(is_pxx2); - ui->moduleLabel->setVisible(!is_pxx2); - - ui->rxOrMod->setText(sensor.getRxOrModName(model)); - ui->rxOrMod->show(); + QString origin = sensor.getOrigin(model); + ui->originLabel->setVisible(!origin.isEmpty()); + ui->origin->setVisible(!origin.isEmpty()); + ui->origin->setText(origin); ui->formula->hide(); isConfigurable = sensor.unit < SensorData::UNIT_FIRST_VIRTUAL; @@ -755,7 +751,7 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model const SensorData& sensor = model->sensorData[-i-1]; if (sensor.isAvailable()) { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) - cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getRxOrModName(model)), i); + cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); else cb->addItem(QString("-%1").arg(sensor.label), i); } @@ -766,7 +762,7 @@ void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model const SensorData& sensor = model->sensorData[i-1]; if (sensor.isAvailable()) { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) - cb->addItem(QString("%1 (%2)").arg(sensor.label, sensor.getRxOrModName(model)), i); + cb->addItem(QString("%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); else cb->addItem(QString("%1").arg(sensor.label), i); } diff --git a/companion/src/modeledit/telemetry_sensor.ui b/companion/src/modeledit/telemetry_sensor.ui index f6007f6d6..7d08243e0 100644 --- a/companion/src/modeledit/telemetry_sensor.ui +++ b/companion/src/modeledit/telemetry_sensor.ui @@ -13,7 +13,7 @@ Form - + 0 @@ -121,21 +121,14 @@ - + Rx - - - Mod. - - - - - + 0 diff --git a/radio/src/storage/conversions/conversions_218_219.cpp b/radio/src/storage/conversions/conversions_218_219.cpp index 0f2c6de9c..f6076917d 100644 --- a/radio/src/storage/conversions/conversions_218_219.cpp +++ b/radio/src/storage/conversions/conversions_218_219.cpp @@ -290,7 +290,7 @@ void convertModelData_218_to_219(ModelData &model) for (uint8_t i=0; i 0 && (isModuleTypePXX1(oldModel.moduleData[0].type) || isModuleTypePXX1(oldModel.moduleData[1].type))) newModel.telemetrySensors[i].instance = 0xE0 + (oldModel.telemetrySensors[i].instance & 0x1F) - 1; else newModel.telemetrySensors[i].instance = oldModel.telemetrySensors[i].instance; From 77f23765ae5469b4e5b32e7b232d4a30ec696e7b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 10:20:48 +0200 Subject: [PATCH 017/257] No LR12 from internal module on X9D+ 2019 --- radio/src/gui/212x64/model_setup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 4637d8634..e3a7c66e5 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -776,7 +776,7 @@ void menuModelSetup(event_t event) } } else if (isModulePXX2(INTERNAL_MODULE)) { - g_model.moduleData[INTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].subType, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_LR12, EE_MODEL, isRfProtocolAvailable); + g_model.moduleData[INTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].subType, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_D16, EE_MODEL, isRfProtocolAvailable); } } #else @@ -786,7 +786,7 @@ void menuModelSetup(event_t event) } lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_ISRM_RF_PROTOCOLS, index, attr); if (attr) { - index = checkIncDec(event, index, 0, 3, EE_MODEL); + index = checkIncDec(event, index, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_D16 + 1 /* because of --- */, EE_MODEL); if (checkIncDec_Ret) { memclear(&g_model.moduleData[INTERNAL_MODULE], sizeof(ModuleData)); if (index > 0) { From c0c3680fe652a1c7ab6ab11738ec32b1f1c4a367 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 10:23:10 +0200 Subject: [PATCH 018/257] Bluetooth detection issue on QX7 (some samples, after bootloader) --- .../common/arm/stm32/bluetooth_driver.cpp | 18 +++++++++++------- .../common/arm/stm32/bootloader/CMakeLists.txt | 7 +++++++ .../common/arm/stm32/bootloader/boot.cpp | 4 ++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp b/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp index 2a9e0848b..1d861e1d6 100644 --- a/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp +++ b/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp @@ -20,6 +20,7 @@ #include "opentx.h" +#if !defined(BOOT) Fifo btTxFifo; Fifo btRxFifo; @@ -42,6 +43,7 @@ enum BluetoothWriteState }; volatile uint8_t bluetoothWriteState = BLUETOOTH_WRITE_IDLE; +#endif void bluetoothInit(uint32_t baudrate, bool enable) { @@ -65,6 +67,7 @@ void bluetoothInit(uint32_t baudrate, bool enable) GPIO_Init(BT_BCTS_GPIO, &GPIO_InitStructure); #endif +#if !defined(BOOT) GPIO_PinAFConfig(BT_USART_GPIO, BT_TX_GPIO_PinSource, BT_GPIO_AF); GPIO_PinAFConfig(BT_USART_GPIO, BT_RX_GPIO_PinSource, BT_GPIO_AF); @@ -90,17 +93,17 @@ void bluetoothInit(uint32_t baudrate, bool enable) bluetoothWriteState = BLUETOOTH_WRITE_IDLE; - if (enable) { - GPIO_ResetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); - } - else { - GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); - } - btRxFifo.clear(); btTxFifo.clear(); +#endif + + if (enable) + GPIO_ResetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); + else + GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); } +#if !defined(BOOT) void bluetoothDisable() { GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); // close bluetooth (recent modules will go to bootloader mode) @@ -165,3 +168,4 @@ uint8_t bluetoothIsWriting(void) { return bluetoothWriteState != BLUETOOTH_WRITE_IDLE; } +#endif // !BOOT diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt index 4141a766e..58b6b57f7 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -92,6 +92,13 @@ if(PCB STREQUAL X12S OR PCB STREQUAL X10 OR PCB STREQUAL X9E OR (PCB STREQUAL X9 ) endif() +if(PCB STREQUAL X7 OR PCB STREQUAL XLITE) + set(BOOTLOADER_SRC + ${BOOTLOADER_SRC} + ../../../../../targets/common/arm/stm32/bluetooth_driver.cpp + ) +endif() + if(NOT (PCB STREQUAL X10 OR PCB STREQUAL X12S)) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index e5adcd545..762f39253 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -245,6 +245,10 @@ int main() backlightInit(); backlightEnable(); +#if defined(PCBX7) || defined(PCBXLITE) + bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE, false); +#endif + #if defined(PCBTARANIS) i2cInit(); #endif From ec33074b0d3dfdd9cacbb5877e2f17d965055071 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 10:29:52 +0200 Subject: [PATCH 019/257] Comment added --- radio/src/targets/common/arm/stm32/bootloader/boot.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index 762f39253..a0878eb05 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -246,6 +246,7 @@ int main() backlightEnable(); #if defined(PCBX7) || defined(PCBXLITE) + // we shutdown the bluetooth module now to be sure it will be detected on firmware start bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE, false); #endif From 9442b31c3cd4788206fa018063b96ed13bb2be72 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 10:41:34 +0200 Subject: [PATCH 020/257] No LR12 from internal module on X10 Express --- 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 c759bfb77..69b9ae676 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -972,7 +972,7 @@ bool menuModelSetup(event_t event) } } else if (isModulePXX2(INTERNAL_MODULE)) { - g_model.moduleData[INTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].subType, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_LR12, EE_MODEL); + g_model.moduleData[INTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].subType, 0, MODULE_SUBTYPE_ISRM_PXX2_ACCST_D16, EE_MODEL); } } break; From a8a32792cc9e7c43d1dbb3f6fa6e92413d17500f Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 24 Sep 2019 10:47:13 +0200 Subject: [PATCH 021/257] A simple LUA event test utility --- radio/util/lua/lua_event_test.lua | 74 +++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 radio/util/lua/lua_event_test.lua diff --git a/radio/util/lua/lua_event_test.lua b/radio/util/lua/lua_event_test.lua new file mode 100644 index 000000000..13d46bcdc --- /dev/null +++ b/radio/util/lua/lua_event_test.lua @@ -0,0 +1,74 @@ +local toolName = "TNS|LUA event tests|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 virtual_next = 0 +local virtual_previous = 0 +local virtual_next_rept = 0 +local virtual_previous_rept = 0 +local virtual_page_next = 0 +local virtual_page_previous = 0 +local virtual_enter = 0 +local virtual_enter_long = 0 +local virtual_menu = 0 +local virtual_menu_long = 0 + +-- Init +local function init() + +end + +-- Main +local function run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + return 2 + elseif event == EVT_VIRTUAL_NEXT then + virtual_next = virtual_next + 1 + elseif event == EVT_VIRTUAL_PREVIOUS then + virtual_previous = virtual_previous + 1 + elseif event == EVT_VIRTUAL_NEXT_REPT then + virtual_next_rept = virtual_next_rept + 1 + elseif event == EVT_VIRTUAL_PREVIOUS_REPT then + virtual_previous_rept = virtual_previous_rept + 1 + elseif event == EVT_VIRTUAL_NEXT_PAGE then + virtual_page_next = virtual_page_next +1 + elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + virtual_page_previous = virtual_page_previous + 1 + elseif event == EVT_VIRTUAL_ENTER then + virtual_enter = virtual_enter + 1 + elseif event == EVT_VIRTUAL_MENU then + virtual_menu = virtual_menu + 1 + end + + lcd.clear() + lcd.drawScreenTitle("LUA EVENT TEST", 0, 0) + lcd.drawText(1, 10, "NEXT: "..virtual_next) + lcd.drawText(1, 20, "PREVIOUS: "..virtual_previous) + lcd.drawText(1, 40, "NEXT_REPT: "..virtual_next_rept) + lcd.drawText(1, 50, "PREVIOUS_REPT: "..virtual_previous_rept) + lcd.drawText(LCD_W/2, 10, "ENTER: "..virtual_enter) + lcd.drawText(LCD_W/2, 20, "MENU: "..virtual_menu) + lcd.drawText(LCD_W/2, 40, "NEXT_PAGE: "..virtual_page_next) + lcd.drawText(LCD_W/2, 50, "PREVIOUS_PAGE: "..virtual_page_previous) + return 0 +end + +return { init=init, run=run } + From 4223013bb6247569ca9b6c4ac3c76a97c7e12252 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 10:49:57 +0200 Subject: [PATCH 022/257] Compilation fix --- radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt index 58b6b57f7..f811d54aa 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -92,7 +92,7 @@ if(PCB STREQUAL X12S OR PCB STREQUAL X10 OR PCB STREQUAL X9E OR (PCB STREQUAL X9 ) endif() -if(PCB STREQUAL X7 OR PCB STREQUAL XLITE) +if(PCB STREQUAL X7 OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} ../../../../../targets/common/arm/stm32/bluetooth_driver.cpp From da167b0adc93f2378c55cce1c085c03de6a8e3f5 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 12:08:27 +0200 Subject: [PATCH 023/257] Cosmetics --- radio/src/translations/en.h.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 784ce1b4c..8134c7bfc 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -510,9 +510,9 @@ #define TR_INACTIVITYALARM INDENT "Inactivity" #define TR_MEMORYWARNING INDENT "Memory low" #define TR_ALARMWARNING INDENT "Sound off" -#define TR_RSSISHUTDOWNALARM TR(INDENT "Rssi Shutdown", INDENT "Check Rssi on Shutdown") +#define TR_RSSISHUTDOWNALARM TR(INDENT "Rssi Shutdown", INDENT "Check RSSI on shutdown") #define TR_MODEL_STILL_POWERED "Model still powered" -#define TR_MODEL_SHUTDOWN "Shutdown ?" +#define TR_MODEL_SHUTDOWN "Shutdown?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" #define TR_RENAVIG "RotEnc Navig" #define TR_THROTTLE_LABEL "Throttle" @@ -1083,7 +1083,7 @@ #define TR_BEEP_VOLUME "Beep volume" #define TR_WAV_VOLUME "Wav volume" -#define TR_BG_VOLUME TR("Bg volume", "Background Volume") +#define TR_BG_VOLUME TR("Bg volume", "Background volume") #define TR_TOP_BAR "Top bar" #define TR_FLASH_ERASE "Flash erase..." From ecc8c2a97b4ff7af6ef23ef6995684f1deb5f4dc Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 12:12:00 +0200 Subject: [PATCH 024/257] Unused string removal --- radio/src/translations/cz.h.txt | 4 ---- radio/src/translations/de.h.txt | 4 ---- radio/src/translations/en.h.txt | 4 ---- radio/src/translations/es.h.txt | 4 ---- radio/src/translations/fi.h.txt | 4 ---- radio/src/translations/fr.h.txt | 4 ---- radio/src/translations/it.h.txt | 4 ---- radio/src/translations/nl.h.txt | 4 ---- radio/src/translations/pl.h.txt | 4 ---- radio/src/translations/pt.h.txt | 4 ---- radio/src/translations/se.h.txt | 4 ---- 11 files changed, 44 deletions(-) diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 4c04844cb..89d99c619 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -51,9 +51,6 @@ #define LEN_VBEEPMODE TR("\005","\012") #define TR_VBEEPMODE TR("Tichý""Alarm""BezKl""Vše\0", "Tichý\0 ""Jen alarm\0""Bez kláves""Vše\0 ") -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "Ne REaREb" - #define LEN_VBLMODE TR("\005", "\007") #define TR_VBLMODE TR("Vyp\0 ""Kláv.""Páky\0""Vše\0 ""Zap\0 ", "Vypnuto""Klávesy""Páky\0 ""Vše\0 ""Zapnuto") @@ -512,7 +509,6 @@ #define TR_MODEL_STILL_POWERED "Model stále spuštěn" #define TR_MODEL_SHUTDOWN "Vypnout ?" #define TR_PRESS_ENTER_TO_CONFIRM "Zmáčkni enter pro potvrzení" -#define TR_RENAVIG "Navig. RotEnc" #define TR_THROTTLE_LABEL "Plyn" #define TR_THROTTLEREVERSE TR("ReversPlyn", INDENT"Revers plynu") #define TR_MINUTEBEEP TR("Minuta", "Oznamovat minuty") diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index ffa5d7a91..54fedd8c6 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Stumm""Alarm""NoKey""Alle\0" -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "AUSDGaDGb" - #define LEN_VBLMODE "\005" #define TR_VBLMODE "AUS\0 ""Taste""Stks\0""Beide""EIN\0 " // Anpassung @@ -514,7 +511,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG TR ("Rol", "Drehgeb. Navig.") #define TR_THROTTLE_LABEL "Gas-Kontrolle" #define TR_THROTTLEREVERSE TR("Gas invers", INDENT "Vollgas hinten?") //Änderung wg TH9x, Taranis #define TR_MINUTEBEEP TR("Min-Alarm", "Minuten-Alarm") diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 8134c7bfc..64c1358ba 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Quiet""Alarm""NoKey""All\0 " -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE TR("\004", "\010") #define TR_VBLMODE TR("OFF\0""Keys""Ctrl""Both""ON\0 ", "OFF\0 ""Keys\0 ""Controls""Both\0 ""ON\0 ") @@ -514,7 +511,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "RotEnc Navig" #define TR_THROTTLE_LABEL "Throttle" #define TR_THROTTLEREVERSE TR("T-Reverse", INDENT "Reverse") #define TR_MINUTEBEEP TR("Minute", "Minute call") diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 74e8b6d16..06eebe928 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Mudo ""Alarm""NoKey""Todo " -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE "\004" #define TR_VBLMODE "OFF ""Keys""Stks""Both""ON\0" @@ -534,7 +531,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "RotEnc Navig" #define TR_THROTTLE_LABEL "Throttle" #define TR_THROTTLEREVERSE TR("Invert_Acel", INDENT "Invertir Acel.") #define TR_MINUTEBEEP TR("Minuto", "Cada Minuto") diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 4f2e48f8e..da2db6387 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Äänet""Hälyt""EiNap""Kaikk" -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE TR("\004", "\010") #define TR_VBLMODE TR("OFF\0""Keys""Ctrl""Both""ON\0 ", "OFF\0 ""Keys\0 ""Controls""Both\0 ""ON\0 ") @@ -526,7 +523,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "RotEnc Navig" #define TR_THROTTLE_LABEL "Throttle" #define TR_THROTTLEREVERSE TR("T-Reverse", INDENT "Throttle reverse") #define TR_MINUTEBEEP TR("Minute", "Minute call") diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 3b65b16d2..3b93dac83 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Aucun""Alarm""NoKey""Tout\0" -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "NonREaREb" - #define LEN_VBLMODE TR("\004", "\011") #define TR_VBLMODE TR("OFF\0""Btns""Ctrl""Tous""ON\0","OFF\0 ""Touches\0 ""Controles""Tous\0 ""ON\0 ") @@ -532,7 +529,6 @@ #define TR_MODEL_STILL_POWERED TR("Modèle allumé", "Modèle encore allumé") #define TR_MODEL_SHUTDOWN "Eteindre ?" #define TR_PRESS_ENTER_TO_CONFIRM "Presser [Enter] pour confirmer" -#define TR_RENAVIG "Navig EncRot" #define TR_THROTTLE_LABEL "Gaz" #define TR_THROTTLEREVERSE TR("Inv. gaz", INDENT "Inversion gaz") #define TR_MINUTEBEEP TR("Bip min.", "Annonces minutes") diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 89cf9aaa9..3e779cf53 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE TR("\005", "\010") #define TR_VBEEPMODE TR("Silen""Avvis""Notst""Tutti","Silente ""Avvisi\0 ""No Tasti""Tutti\0 ") -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE TR("\005", "\006") #define TR_VBLMODE TR("OFF\0 ""Tasti""Stks\0""Tutti""ON\0 ", "Spenta""Tasti\0""Sticks""Tutti\0""Accesa") @@ -533,7 +530,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "Navig EncRot " #define TR_THROTTLE_LABEL "Motore" #define TR_THROTTLEREVERSE TR("Mot inv.", INDENT "Motore Inverso") #define TR_MINUTEBEEP "Minuto" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 553740a1f..3dedec93b 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Stil\0""Alarm""NoKey""Alles" -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "UITREaREb" - #define LEN_VBLMODE TR("\005", "\010") #define TR_VBLMODE TR("UIT\0 ""Keys\0""Stick""Beide""AAN\0 ", "UIT\0 ""Toetsen\0""Sticks\0 ""Beide\0 ""AAN\0 ") @@ -516,7 +513,6 @@ TR_GYR_VSRCRAW #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "Stappenschakelaar" #define TR_THROTTLE_LABEL "Gas" #define TR_THROTTLEREVERSE TR("Reverse", INDENT "Omgekeerd") #define TR_MINUTEBEEP TR("Min-Alarm", "Minuten-Alarm") diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 02990fab7..447578f1d 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Cichy""Alarm""BezPr""Wsz.\0" -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE TR("\004", "\010") #define TR_VBLMODE TR("Wył\0""Przy""Drąż""Oba\0""Zał\0", "Wyłącz ""Przycisk""Drązki\0 ""Oba\0 ""Włącz ") @@ -533,7 +530,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "Nawigacja potencjometrem" #define TR_THROTTLE_LABEL "Gaz " #define TR_THROTTLEREVERSE TR("OdwrGaz", INDENT "OdwrGaz") #define TR_MINUTEBEEP TR("Minuta", "PikCoMinutę") diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 898b1b530..a71168ba8 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Mudo ""Alarm""NoKey""Todo " -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "No REaREb" - #define LEN_VBLMODE "\004" #define TR_VBLMODE "OFF ""Chav""Stks""Tudo""ON\0" @@ -519,7 +516,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "RotEnc Navig" #define TR_THROTTLE_LABEL "Throttle" #define TR_THROTTLEREVERSE TR("Inverte Acel.", INDENT "Inverte Acel.") #define TR_MINUTEBEEP "Beep Minuto" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index d9d9deb81..db141c446 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -52,9 +52,6 @@ #define LEN_VBEEPMODE "\005" #define TR_VBEEPMODE "Tyst\0""Alarm""EjKnp""Alla\0" -#define LEN_VRENAVIG "\003" -#define TR_VRENAVIG "IngREaREb" - #define LEN_VBLMODE TR("\005", "\010") #define TR_VBLMODE TR("Av\0 ""Knapp""Spak\0""Allt\0""På\0 ", "Av\0 ""Knappar\0""Spakar\0 ""Allt\0 ""På\0 ") @@ -532,7 +529,6 @@ #define TR_MODEL_STILL_POWERED "Model still powered" #define TR_MODEL_SHUTDOWN "Shutdown ?" #define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" -#define TR_RENAVIG "RotEnk Navig" #define TR_THROTTLE_LABEL "Gas" #define TR_THROTTLEREVERSE TR("Inv.Gas", INDENT "Inverterad Gas") #define TR_MINUTEBEEP "Minutpip" From 4a618f13174bd15e6f64d99f46b3c757b8cf6dea Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 13:13:45 +0200 Subject: [PATCH 025/257] X9LiteS (#6820) --- .travis.yml | 1 + companion/src/firmwares/boards.cpp | 6 +++ companion/src/firmwares/boards.h | 3 +- .../src/firmwares/opentx/opentxinterface.cpp | 8 ++++ companion/src/simulation/simulatorwidget.cpp | 1 + radio/src/CMakeLists.txt | 6 +-- radio/src/gui/128x64/view_main.cpp | 44 ++++++++++++++++++- .../src/gui/common/stdlcd/radio_hardware.cpp | 4 +- radio/src/lua/CMakeLists.txt | 1 + radio/src/lua/api_general.cpp | 2 + radio/src/sdcard.h | 2 + radio/src/simu.cpp | 2 +- radio/src/switches.cpp | 7 ++- .../arm/stm32/bootloader/CMakeLists.txt | 2 +- radio/src/targets/simu/opentxsimulator.cpp | 2 + radio/src/targets/taranis/CMakeLists.txt | 27 ++++++++++-- radio/src/targets/taranis/board.h | 15 +++++-- radio/src/targets/taranis/hal.h | 31 ++++++++++++- radio/src/targets/taranis/keys_driver.cpp | 7 ++- radio/src/translations/untranslated.h | 3 ++ radio/util/build-firmware.py | 6 ++- tools/build-companion-nightly.sh | 3 ++ tools/build-companion-release.sh | 3 ++ tools/build-frsky.py | 15 +++++++ tools/commit-tests.sh | 9 ++++ 25 files changed, 191 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 582215347..cd3f1e948 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ env: # - FLAVOR=SKY9X # - FLAVOR=9XRPRO - FLAVOR=X9LITE + - FLAVOR=X9LITES - FLAVOR=X7 - FLAVOR=T12 - FLAVOR=XLITE diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 9f375411f..99094edf3 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -75,6 +75,8 @@ uint32_t Boards::getFourCC(Type board) return 0x3378746F; case BOARD_TARANIS_X9LITE: return 0x3C78746F; + case BOARD_TARANIS_X9LITES: + return 0x3E78746F; case BOARD_SKY9X: case BOARD_AR9X: case BOARD_9XRPRO: @@ -113,6 +115,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_TARANIS_XLITE: case BOARD_TARANIS_X7: case BOARD_TARANIS_X9LITE: + case BOARD_TARANIS_X9LITES: case BOARD_TARANIS_X9D: case BOARD_TARANIS_X9DP: case BOARD_TARANIS_X9DP_2019: @@ -149,6 +152,7 @@ int Boards::getFlashSize(Type board) case BOARD_TARANIS_XLITE: case BOARD_TARANIS_X7: case BOARD_TARANIS_X9LITE: + case BOARD_TARANIS_X9LITES: case BOARD_TARANIS_X9D: case BOARD_TARANIS_X9DP: case BOARD_TARANIS_X9DP_2019: @@ -505,6 +509,8 @@ QString Boards::getBoardName(Board::Type board) return "Taranis X9E"; case BOARD_TARANIS_X9LITE: return "Taranis X9-Lite"; + case BOARD_TARANIS_X9LITES: + return "Taranis X9-Lite S"; case BOARD_SKY9X: return "Sky9x"; case BOARD_9XRPRO: diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 06a7a0f04..7a60ad4f4 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -50,6 +50,7 @@ namespace Board { BOARD_TARANIS_XLITE, BOARD_TARANIS_XLITES, BOARD_TARANIS_X9LITE, + BOARD_TARANIS_X9LITES, BOARD_JUMPER_T12, }; @@ -239,7 +240,7 @@ inline bool IS_TARANIS_X7(Board::Type board) inline bool IS_TARANIS_X9LITE(Board::Type board) { - return board == Board::BOARD_TARANIS_X9LITE; + return board == Board::BOARD_TARANIS_X9LITE || board == Board::BOARD_TARANIS_X9LITES; } inline bool IS_TARANIS_X9(Board::Type board) diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 3ba4f2a7a..1ab1f3aba 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -78,6 +78,8 @@ const char * OpenTxEepromInterface::getName() return "OpenTX for FrSky Taranis X9E"; case BOARD_TARANIS_X7: return "OpenTX for FrSky Taranis X7"; + case BOARD_TARANIS_X9LITES: + return "OpenTX for FrSky Taranis X9-Lite S"; case BOARD_TARANIS_X9LITE: return "OpenTX for FrSky Taranis X9-Lite"; case BOARD_TARANIS_XLITE: @@ -1238,6 +1240,12 @@ void registerOpenTxFirmwares() firmware->addOption("autoupdate", Firmware::tr("Support for auto update on boot")); registerOpenTxFirmware(firmware); + /* FrSky X9-LiteS board */ + firmware = new OpenTxFirmware("opentx-x9lites", Firmware::tr("FrSky Taranis X9-Lite S"), BOARD_TARANIS_X9LITES); + addOpenTxTaranisOptions(firmware); + firmware->addOption("autoupdate", Firmware::tr("Support for auto update on boot")); + registerOpenTxFirmware(firmware); + /* FrSky X7 board */ firmware = new OpenTxFirmware("opentx-x7", Firmware::tr("FrSky Taranis X7 / X7S"), BOARD_TARANIS_X7); addOpenTxTaranisOptions(firmware); diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index 4858d7135..e5c7e2903 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -60,6 +60,7 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato switch(m_board) { case Board::BOARD_TARANIS_X9LITE: + case Board::BOARD_TARANIS_X9LITES: radioUiWidget = new SimulatedUIWidgetX9LITE(simulator, this); break; case Board::BOARD_TARANIS_X7: diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 4cc05489d..1f7c2c542 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -1,7 +1,7 @@ include(CMakeForceCompiler) include(Bitmaps) -set(PCB_TYPES X9LITE X7 XLITE XLITES X9D X9D+ X9E X10 X12S SKY9X 9XRPRO AR9X) +set(PCB_TYPES X9LITE X9LITES X7 XLITE XLITES X9D X9D+ X9E X10 X12S SKY9X 9XRPRO AR9X) set(GUI_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU NL) set(TTS_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU NL RU) @@ -86,7 +86,7 @@ set(FATFS_SRC if(PCB STREQUAL X12S OR PCB STREQUAL X10) include(targets/horus/CMakeLists.txt) -elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES) +elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES) include(targets/taranis/CMakeLists.txt) elseif(PCB STREQUAL SKY9X OR PCB STREQUAL 9XRPRO OR PCB STREQUAL AR9X) include(targets/sky9x/CMakeLists.txt) @@ -469,7 +469,7 @@ if(NOT MSVC) set(SRC ${SRC} bin_allocator.cpp) endif() - if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X10 OR PCB STREQUAL X12S) + if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL X9LITE OR PCB STREQUAL X9LITES OR PCB STREQUAL X10 OR PCB STREQUAL X12S) add_subdirectory(targets/common/arm/stm32/bootloader) include_directories(${CMAKE_CURRENT_BINARY_DIR}/targets/common/arm/stm32/bootloader) set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} bootloader) diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index 24b709fde..8f95220ae 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -297,6 +297,36 @@ void onMainViewMenu(const char *result) } } +void drawSmallSwitch(coord_t x, coord_t y, int width, unsigned int index) +{ + if (SWITCH_EXISTS(index)) { + int val = getValue(MIXSRC_FIRST_SWITCH+index); + + if (val >= 0) { + lcdDrawSolidHorizontalLine(x, y, width); + lcdDrawSolidHorizontalLine(x, y+2, width); + y += 4; + if (val > 0) { + lcdDrawSolidHorizontalLine(x, y, width); + lcdDrawSolidHorizontalLine(x, y+2, width); + y += 4; + } + } + + lcdDrawChar(width==5 ? x+1 : x, y, 'A'+index, SMLSIZE); + y += 7; + + if (val <= 0) { + lcdDrawSolidHorizontalLine(x, y, width); + lcdDrawSolidHorizontalLine(x, y+2, width); + if (val < 0) { + lcdDrawSolidHorizontalLine(x, y+4, width); + lcdDrawSolidHorizontalLine(x, y+6, width); + } + } + } +} + void menuMainView(event_t event) { uint8_t view = g_eeGeneral.view; @@ -472,7 +502,19 @@ void menuMainView(event_t event) doMainScreenGraphics(); // Switches -#if defined(PCBX9LITE) +#if defined(PCBX9LITES) + static const uint8_t x[NUM_SWITCHES-2] = {2*FW-2, 2*FW-2, 17*FW+1, 2*FW-2, 17*FW+1}; + static const uint8_t y[NUM_SWITCHES-2] = {4*FH+1, 5*FH+1, 5*FH+1, 6*FH+1, 6*FH+1}; + for (int i=0; iIDR + #define SWITCHES_GPIO_PIN_F GPIO_Pin_3 // PC.03 #elif defined(PCBX9LITE) // no SWF #elif defined(PCBX7) @@ -469,6 +474,11 @@ #define SWITCHES_GPIO_PIN_G_H GPIO_Pin_3 // PF.03 #define SWITCHES_GPIO_REG_G_L GPIOF->IDR #define SWITCHES_GPIO_PIN_G_L GPIO_Pin_4 // PF.04 +#elif defined(PCBX9LITES) + #define STORAGE_SWITCH_G + #define HARDWARE_SWITCH_G + #define SWITCHES_GPIO_REG_G GPIOC->IDR + #define SWITCHES_GPIO_PIN_G GPIO_Pin_2 // PC.02 #elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) // no SWG #else @@ -635,6 +645,13 @@ #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_10 | GPIO_Pin_13) #define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15) #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15) +#elif defined(PCBX9LITES) + #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) + #define KEYS_GPIOA_PINS (GPIO_Pin_5) + #define KEYS_GPIOB_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5) + #define KEYS_GPIOC_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_13) + #define KEYS_GPIOD_PINS (GPIO_Pin_8 | GPIO_Pin_9) + #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14) #elif defined(PCBX9LITE) #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) #define KEYS_GPIOA_PINS (GPIO_Pin_5) @@ -891,6 +908,14 @@ #define LED_RED_GPIO_PIN GPIO_Pin_5 // PC.05 #define LED_BLUE_GPIO GPIOB #define LED_BLUE_GPIO_PIN GPIO_Pin_1 // PB.01 +#elif defined(PCBX9LITES) + #define STATUS_LEDS + #define GPIO_LED_GPIO_ON GPIO_SetBits + #define GPIO_LED_GPIO_OFF GPIO_ResetBits + #define LED_RED_GPIO GPIOE + #define LED_RED_GPIO_PIN GPIO_Pin_5 // PE.05 + #define LED_BLUE_GPIO GPIOE + #define LED_BLUE_GPIO_PIN GPIO_Pin_6 // PE.06 #elif defined(PCBX9LITE) #define STATUS_LEDS #define GPIO_LED_GPIO_ON GPIO_SetBits @@ -1788,7 +1813,7 @@ #define BT_TX_GPIO_PinSource GPIO_PinSource14 #define BT_RX_GPIO_PinSource GPIO_PinSource9 #define BT_USART_IRQHandler USART6_IRQHandler -#elif defined(PCBX7) || defined(PCBXLITE) || (defined(PCBX9DP) && PCBREV >= 2019) +#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITES) || (defined(PCBX9DP) && PCBREV >= 2019) #define STORAGE_BLUETOOTH #define BT_RCC_APB1Periph RCC_APB1Periph_USART3 #define BT_RCC_APB2Periph 0 @@ -1800,6 +1825,10 @@ #define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE) // RCC_AHB1Periph_DMA1 #define BT_EN_GPIO GPIOE #define BT_EN_GPIO_PIN GPIO_Pin_15 // PE.15 + #elif defined(PCBX9LITES) + #define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD) // RCC_AHB1Periph_DMA1 + #define BT_EN_GPIO GPIOD + #define BT_EN_GPIO_PIN GPIO_Pin_14 // PD.14 #else #define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE) // RCC_AHB1Periph_DMA1 #define BT_EN_GPIO GPIOE diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp index 144d7e97e..380c7d9cc 100644 --- a/radio/src/targets/taranis/keys_driver.cpp +++ b/radio/src/targets/taranis/keys_driver.cpp @@ -179,7 +179,12 @@ uint32_t switchState(uint8_t index) ADD_3POS_CASE(B, 1); ADD_3POS_CASE(C, 2); -#if defined(PCBX9LITE) +#if defined(PCBX9LITES) + ADD_2POS_CASE(D); + ADD_2POS_CASE(E); + ADD_2POS_CASE(F); + ADD_2POS_CASE(G); +#elif defined(PCBX9LITE) ADD_2POS_CASE(D); ADD_2POS_CASE(E); #elif defined(PCBXLITES) diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 83ddc3095..5d7420330 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -50,6 +50,9 @@ #elif defined(RADIO_T12) #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0" +#elif defined(PCBX9LITES) + #define TR_POTS_VSRCRAW "\310S1\0" + #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0" #elif defined(PCBX9LITE) #define TR_POTS_VSRCRAW "\310S1\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0" diff --git a/radio/util/build-firmware.py b/radio/util/build-firmware.py index 41be5705a..e34ac4237 100755 --- a/radio/util/build-firmware.py +++ b/radio/util/build-firmware.py @@ -88,7 +88,11 @@ def main(): cmake_options["PCB"] = "X9LITE" firmware_options = options_taranis_x9lite maxsize = 65536 * 8 - elif board_name == "x7": + elif board_name == "x9lites": + cmake_options["PCB"] = "X9LITES" + firmware_options = options_taranis_x9lite + maxsize = 65536 * 8 + elif options[optcount] == "x7": cmake_options["PCB"] = "X7" firmware_options = options_taranis_x9dp maxsize = 65536 * 8 diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index c0cf47bd1..0b21114dc 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -50,6 +50,9 @@ make -j${JOBS} libsimulator cmake ${COMMON_OPTIONS} -DPCB=X9LITE ${SRCDIR} make -j${JOBS} libsimulator +cmake ${COMMON_OPTIONS} -DPCB=X9LITES ${SRCDIR} +make -j${JOBS} libsimulator + cmake ${COMMON_OPTIONS} -DPCB=X7 ${SRCDIR} make -j${JOBS} libsimulator diff --git a/tools/build-companion-release.sh b/tools/build-companion-release.sh index 14bda21bf..81a20b6cd 100755 --- a/tools/build-companion-release.sh +++ b/tools/build-companion-release.sh @@ -50,6 +50,9 @@ make -j${JOBS} libsimulator cmake ${COMMON_OPTIONS} -DPCB=X9LITE ${SRCDIR} make -j${JOBS} libsimulator +cmake ${COMMON_OPTIONS} -DPCB=X9LITES ${SRCDIR} +make -j${JOBS} libsimulator + cmake ${COMMON_OPTIONS} -DPCB=X7 ${SRCDIR} make -j${JOBS} libsimulator diff --git a/tools/build-frsky.py b/tools/build-frsky.py index 03beec3e3..9e538bc4a 100755 --- a/tools/build-frsky.py +++ b/tools/build-frsky.py @@ -61,6 +61,21 @@ boards = { "SBUS": "NO", "DEFAULT_MODE": "2", }, + "X9LITES": { + "PCB": "X9LITES", + "LUA": "NO_MODEL_SCRIPTS", + "GVARS": "YES", + "AUTOUPDATE": "YES", + "PXX1": "YES", + "XJT": "NO", + "MODULE_SIZE_STD": "NO", + "PPM": "NO", + "DSM2": "NO", + "MULTIMODULE": "NO", + "CROSSFIRE": "NO", + "SBUS": "NO", + "DEFAULT_MODE": "2", + }, "X9D+": { "PCB": "X9D+", "PCBREV": "2019", diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 73c7a2775..6e4719955 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -94,6 +94,15 @@ if [[ " X9LITE ALL " =~ " ${FLAVOR} " ]] ; then make -j${CORES} tests fi +if [[ " X9LITES ALL " =~ " ${FLAVOR} " ]] ; then + # OpenTX on X9LITES + rm -rf * + cmake ${COMMON_OPTIONS} -DPCB=X9LITES -DHELI=YES -DGVARS=YES ${SRCDIR} + make -j${CORES} ${FIRMARE_TARGET} + make -j${CORES} libsimulator + make -j${CORES} tests +fi + if [[ " X7 ALL " =~ " ${FLAVOR} " ]] ; then # OpenTX on X7 rm -rf * From 5418dc6c979f129649b6219f31b9ac64b9f62f30 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 14:41:28 +0200 Subject: [PATCH 026/257] Unused string removal --- 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 - 11 files changed, 11 deletions(-) diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 89d99c619..6ec267134 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -663,7 +663,6 @@ #define TR_PITCH_AT_ZERO INDENT "Tón na nule" #define TR_PITCH_AT_MAX INDENT "Tón na maximu" #define TR_REPEAT_AT_ZERO TR(INDENT "Opak. na nule", INDENT "Opakování na nule") -#define TR_POWEROFF "\027Vypínám..." #define TR_SHUTDOWN "Vypínání.." #define TR_SAVEMODEL "Ukládám nastavení modelu" #define TR_BATT_CALIB "Kalib. bat." diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 54fedd8c6..bef995a9f 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -665,7 +665,6 @@ #define TR_PITCH_AT_ZERO INDENT "Töne sinken" #define TR_PITCH_AT_MAX INDENT "Töne steigen" #define TR_REPEAT_AT_ZERO INDENT "Wiederholrate" -#define TR_POWEROFF "\027Power OFF..." #define TR_SHUTDOWN "Herunterfahren" #define TR_SAVEMODEL "Modelleinstellungen speichern" #define TR_BATT_CALIB TR("AkkuSpgwert", "Akku Kalibrierung") diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 64c1358ba..fa55e1941 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -665,7 +665,6 @@ #define TR_PITCH_AT_ZERO INDENT "Pitch zero" #define TR_PITCH_AT_MAX INDENT "Pitch max" #define TR_REPEAT_AT_ZERO INDENT "Repeat zero" -#define TR_POWEROFF "\027Power OFF..." #define TR_SHUTDOWN "SHUTTING DOWN" #define TR_SAVEMODEL "Saving model settings" #define TR_BATT_CALIB TR("Batt. calib", "Battery calibration") diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 06eebe928..1cb0090eb 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -688,7 +688,6 @@ #define TR_PITCH_AT_ZERO INDENT "Pitch at Zero" #define TR_PITCH_AT_MAX INDENT "Pitch at Max" #define TR_REPEAT_AT_ZERO INDENT "Repeat at Zero" -#define TR_POWEROFF "\027Power OFF..." #define TR_SHUTDOWN "APAGANDO" #define TR_SAVEMODEL "Saving model settings" #define TR_BATT_CALIB "Calib.bateria" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index da2db6387..d1cf825f6 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -682,7 +682,6 @@ #define TR_PITCH_AT_ZERO INDENT "Pitch at Zero" #define TR_PITCH_AT_MAX INDENT "Pitch at Max" #define TR_REPEAT_AT_ZERO INDENT "Repeat at Zero" -#define TR_POWEROFF "\027Power OFF..." #define TR_SHUTDOWN "SHUTTING DOWN" #define TR_SAVEMODEL "Saving model settings" #define TR_BATT_CALIB "Battery Calib" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 3b93dac83..c879b3c4e 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -685,7 +685,6 @@ #define TR_PITCH_AT_ZERO INDENT "Tonalité zéro" #define TR_PITCH_AT_MAX INDENT "Tonalité max" #define TR_REPEAT_AT_ZERO TR(INDENT "Interv. zéro", INDENT "Intervalle au zéro") -#define TR_POWEROFF "\037\120ARRET..." #define TR_SHUTDOWN "ARRET EN COURS" #define TR_SAVEMODEL "Sauvegarde modèle..." #define TR_BATT_CALIB "Calib. batt" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 3e779cf53..de340f087 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -683,7 +683,6 @@ #define TR_PITCH_AT_ZERO INDENT "Tono a Zero" #define TR_PITCH_AT_MAX INDENT "Tono al Max" #define TR_REPEAT_AT_ZERO INDENT "Ripeti a Zero" -#define TR_POWEROFF "\027Power OFF..." #define TR_SHUTDOWN "ARRESTO.." #define TR_SAVEMODEL "Salvataggio dati modello" #define TR_BATT_CALIB "Calibra batt." diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 3dedec93b..ab612da8f 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -671,7 +671,6 @@ TR_GYR_VSRCRAW #define TR_PITCH_AT_ZERO INDENT "Laagste Toon" #define TR_PITCH_AT_MAX INDENT "Hoogste Toon" #define TR_REPEAT_AT_ZERO INDENT "Herhalen bij 0" -#define TR_POWEROFF "\027Uitschakelen..." #define TR_SHUTDOWN "Afsluiten" #define TR_SAVEMODEL "Bewaar Model-instellingen" #define TR_BATT_CALIB "Accu Calib" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 447578f1d..1809484e5 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -683,7 +683,6 @@ #define TR_PITCH_AT_ZERO INDENT "Ton przy Zerze" #define TR_PITCH_AT_MAX INDENT "Ton przy Max" #define TR_REPEAT_AT_ZERO INDENT "Powtórz przy Zerze" -#define TR_POWEROFF "\027Wyłączanie.." #define TR_SHUTDOWN "Wyłączanie.." #define TR_SAVEMODEL "Zapisz ustwienia modelu" #define TR_BATT_CALIB "Kalib:Baterii" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index a71168ba8..6a8adc944 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -673,7 +673,6 @@ #define TR_PITCH_AT_ZERO INDENT "Pitch at Zero" #define TR_PITCH_AT_MAX INDENT "Pitch at Max" #define TR_REPEAT_AT_ZERO INDENT "Repeat at Zero" -#define TR_POWEROFF "\027Power OFF..." #define TR_SHUTDOWN "DESLIGANDOo" #define TR_SAVEMODEL "Saving model settings" #define TR_BATT_CALIB "CALIBRAR BATT" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index db141c446..236a3b26f 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -682,7 +682,6 @@ #define TR_PITCH_AT_ZERO INDENT "Ton vid Noll" #define TR_PITCH_AT_MAX INDENT "Ton vid Max" #define TR_REPEAT_AT_ZERO INDENT "Repetera vid Noll" -#define TR_POWEROFF "\027Stänger Av..." #define TR_SHUTDOWN "STÄNGER AV" #define TR_SAVEMODEL "Spara modellinställn." #define TR_BATT_CALIB "Kalib. Batteri" From 0032bfee557e85953e4269b157bd35d9d6af5aed Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 17:08:39 +0200 Subject: [PATCH 027/257] Unused string removal --- radio/src/translations/cz.h.txt | 7 +++---- 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 - 11 files changed, 3 insertions(+), 14 deletions(-) diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 6ec267134..5b4774292 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -559,11 +559,10 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" -#define TR_US "us" +#define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" -#define TR_TMIXMAXMS "Tmix max" -#define TR_FREE_STACK "Free stack" +#define TR_TMIXMAXMS "Tmix max" +#define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER" >> Reset" #define TR_PPM_TRAINER "TR" #define TR_CH "CH" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index bef995a9f..a44fe2e9d 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -563,7 +563,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"Keine Daten" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036GAS\037\146GS%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index fa55e1941..8a1e77bde 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -563,7 +563,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 1cb0090eb..cf639b377 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -577,7 +577,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "SIN DATOS" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index d1cf825f6..5701f6c14 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -569,7 +569,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index c879b3c4e..826cd56b1 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -579,7 +579,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036GAZ\037\146GZ%" #define TR_US "us" #define TR_TMR1LATMINUS "Tmr1Lat min\037\124us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index de340f087..8060c3e6a 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -580,7 +580,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"DATI ASSENTI" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index ab612da8f..53158ce0d 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -565,7 +565,6 @@ TR_GYR_VSRCRAW #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"Geen Data" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 1809484e5..f00e80cce 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -580,7 +580,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "BrakDAN" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "TmixMaks" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 6a8adc944..820436613 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -562,7 +562,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"SEM DADOS" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 236a3b26f..9f75ce93d 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -579,7 +579,6 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "DATA SAKNAS" -#define TR_TOTTM1TM2THRTHP "\037\146SES\036TM1\037\146TM2\036THR\037\146TH%" #define TR_US "us" #define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" From 713b43b9032dee0225dd819688ff0656f5d421bc Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 17:15:05 +0200 Subject: [PATCH 028/257] Unused string removal --- 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 - 11 files changed, 11 deletions(-) diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 5b4774292..c839d7d3f 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -560,7 +560,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER" >> Reset" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index a44fe2e9d..65e3f7cb3 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -564,7 +564,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"Keine Daten" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Freier Stack" #define TR_MENUTORESET TR_ENTER " für Reset" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 8a1e77bde..423067a10 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -564,7 +564,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER " to reset" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index cf639b377..3395c170c 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -578,7 +578,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "SIN DATOS" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER "Resetear" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 5701f6c14..65c67607b 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -570,7 +570,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 826cd56b1..fc3d2945f 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -581,7 +581,6 @@ #define TR_NODATA CENTER "NO DATA" #define TR_US "us" #define TR_TMR1LATMINUS "Tmr1Lat min\037\124us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 8060c3e6a..900913578 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -581,7 +581,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"DATI ASSENTI" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER" x Azzerare" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 53158ce0d..7aaf4d5ac 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -566,7 +566,6 @@ TR_GYR_VSRCRAW #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"Geen Data" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER" voor Reset" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index f00e80cce..1922fa9b0 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -581,7 +581,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "BrakDAN" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "TmixMaks" #define TR_FREE_STACK "Wolny stos" #define TR_MENUTORESET TR_ENTER " >> Reset" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 820436613..cefcb53fd 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -563,7 +563,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER"SEM DADOS" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER" Reinicia" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 9f75ce93d..3d60f986b 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -580,7 +580,6 @@ #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "DATA SAKNAS" #define TR_US "us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\037\124us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER " Nollar" From 82fbc590e58ac7b0d1438f8e46a3dc05190d6369 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 17:17:03 +0200 Subject: [PATCH 029/257] Cosmetics --- radio/src/translations/en.h.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 423067a10..b2090eaea 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -406,7 +406,6 @@ #if defined(PCBTARANIS) #define TR_POPUPS_ENTER_EXIT TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER) - #else #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT #endif @@ -563,9 +562,9 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" -#define TR_US "us" -#define TR_TMIXMAXMS "Tmix max" -#define TR_FREE_STACK "Free stack" +#define TR_US "us" +#define TR_TMIXMAXMS "Tmix max" +#define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER " to reset" #define TR_PPM_TRAINER "TR" #define TR_CH "CH" @@ -628,7 +627,7 @@ #define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") #define TR_MULTI_TELEMETRY "Telemetry" #define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") -#define TR_RFPOWER "RF Power" +#define TR_RFPOWER "RF Power" #define TR_MULTI_FIXEDID TR("FixedID", "Fixed ID") #define TR_MULTI_OPTION TR("Option", "Option value") #define TR_MULTI_AUTOBIND TR(INDENT "Autobind",INDENT "Bind on channel") @@ -778,7 +777,6 @@ #define TR_TEMP_CALIB "Temp. Calib" #define TR_TIME "Time" #define TR_MAXBAUDRATE "Max bauds" - #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" From 53d36cdbf448e4924a0ce16e9b29b003bec48be6 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 24 Sep 2019 20:25:05 +0200 Subject: [PATCH 030/257] The rotary encoder disables the inactivity warning --- radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp index fc028d3b5..274b37203 100644 --- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp +++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp @@ -84,6 +84,7 @@ void rotaryEncoderCheck() if (g_eeGeneral.backlightMode & e_backlight_mode_keys) { backlightOn(); } + inactivity.counter = 0; #endif } } From 6b12010473ca09fa0096f525da6a594027323b66 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 30 Aug 2019 15:49:19 +0200 Subject: [PATCH 031/257] Add T16 support Added support for: - T16 radio - internal multi-protocol module. - flashing internal and external multi-protocol modules. Many thx to: - goebish, for the hardware support. - qba667, for the original patches for the internal multi-protocol support (UI and serial com). --- .travis.yml | 1 + companion/src/CMakeLists.txt | 2 + companion/src/companion.qrc | 11 + companion/src/firmwares/boards.cpp | 12 +- companion/src/firmwares/boards.h | 12 +- companion/src/firmwares/generalsettings.cpp | 4 +- .../src/firmwares/opentx/opentxinterface.cpp | 16 +- .../images/simulator/JumperT16/JumperT16.svg | 2594 +++++++++++++++++ .../src/images/simulator/JumperT16/bottom.png | Bin 0 -> 250 bytes .../src/images/simulator/JumperT16/left.png | Bin 0 -> 13936 bytes .../images/simulator/JumperT16/left_mdl.png | Bin 0 -> 13911 bytes .../images/simulator/JumperT16/left_page.png | Bin 0 -> 13954 bytes .../simulator/JumperT16/left_scrnsht.png | Bin 0 -> 13798 bytes .../images/simulator/JumperT16/left_sys.png | Bin 0 -> 13783 bytes .../images/simulator/JumperT16/left_tele.png | Bin 0 -> 13902 bytes .../src/images/simulator/JumperT16/right.png | Bin 0 -> 11742 bytes .../images/simulator/JumperT16/right_ent.png | Bin 0 -> 11467 bytes .../images/simulator/JumperT16/right_rtn.png | Bin 0 -> 11339 bytes .../src/images/simulator/JumperT16/top.png | Bin 0 -> 439 bytes companion/src/simulation/CMakeLists.txt | 2 + companion/src/simulation/simulateduiwidget.h | 14 + .../simulation/simulateduiwidgetJumperT12.cpp | 1 - .../simulation/simulateduiwidgetJumperT16.cpp | 69 + .../simulation/simulateduiwidgetJumperT16.ui | 197 ++ .../src/simulation/simulatorstartupdialog.cpp | 2 +- companion/src/simulation/simulatorwidget.cpp | 5 +- launchpad/common/rules | 1 + radio/sdcard/horus/THEMES/Darkblue/t16.bmp | Bin 0 -> 164938 bytes radio/sdcard/horus/THEMES/Default/t16.bmp | Bin 0 -> 164938 bytes radio/src/dataconstants.h | 12 +- radio/src/fifo.h | 5 - radio/src/gui/128x64/model_setup.cpp | 79 +- radio/src/gui/212x64/model_setup.cpp | 28 +- radio/src/gui/480x272/model_setup.cpp | 276 +- radio/src/gui/480x272/radio_hardware.cpp | 14 +- radio/src/gui/480x272/radio_sdmanager.cpp | 32 +- radio/src/gui/480x272/themes/default.cpp | 4 +- .../src/gui/common/stdlcd/radio_sdmanager.cpp | 33 +- radio/src/gui/gui_common.cpp | 8 +- radio/src/gui/gui_common.h | 57 +- radio/src/io/frsky_firmware_update.cpp | 8 +- radio/src/io/frsky_firmware_update.h | 2 +- radio/src/io/multi_firmware_update.cpp | 447 +++ radio/src/io/multi_firmware_update.h | 96 + radio/src/io/stk500.h | 39 + radio/src/lua/CMakeLists.txt | 1 + radio/src/lua/api_general.cpp | 2 + radio/src/opentx.cpp | 4 +- radio/src/opentx.h | 2 + radio/src/options.h | 3 + radio/src/pulses/modules_helpers.h | 8 +- radio/src/pulses/multi.cpp | 132 +- radio/src/pulses/multi.h | 41 + radio/src/pulses/pulses.cpp | 18 +- radio/src/pulses/pulses.h | 14 +- radio/src/pulses/pxx2.cpp | 2 +- radio/src/sdcard.h | 5 +- .../conversions/conversions_218_219.cpp | 2 + radio/src/targets/common/arm/CMakeLists.txt | 2 +- .../targets/common/arm/stm32/adc_driver.cpp | 4 +- .../common/arm/stm32/audio_dac_driver.cpp | 10 +- .../common/arm/stm32/aux_serial_driver.cpp | 4 +- .../arm/stm32/intmodule_serial_driver.cpp | 54 +- .../arm/stm32/rotary_encoder_driver.cpp | 24 +- radio/src/targets/horus/CMakeLists.txt | 27 +- radio/src/targets/horus/board.h | 17 +- radio/src/targets/horus/extmodule_driver.cpp | 32 + radio/src/targets/horus/hal.h | 27 +- radio/src/targets/horus/telemetry_driver.cpp | 2 +- radio/src/targets/sky9x/CMakeLists.txt | 1 + radio/src/targets/taranis/CMakeLists.txt | 38 +- radio/src/targets/taranis/board.h | 5 +- .../src/targets/taranis/extmodule_driver.cpp | 32 + radio/src/targets/taranis/hal.h | 8 - .../src/targets/taranis/telemetry_driver.cpp | 2 +- radio/src/telemetry/flysky_ibus.cpp | 24 +- radio/src/telemetry/flysky_ibus.h | 2 +- radio/src/telemetry/multi.cpp | 280 +- radio/src/telemetry/multi.h | 12 +- radio/src/telemetry/spektrum.cpp | 51 +- radio/src/telemetry/spektrum.h | 4 +- radio/src/telemetry/telemetry.cpp | 32 +- radio/src/telemetry/telemetry.h | 11 +- radio/src/translations.cpp | 2 + radio/src/translations.h | 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 + radio/util/build-firmware.py | 5 + radio/util/fwoptions.py | 13 + 98 files changed, 4585 insertions(+), 481 deletions(-) create mode 100644 companion/src/images/simulator/JumperT16/JumperT16.svg create mode 100644 companion/src/images/simulator/JumperT16/bottom.png create mode 100644 companion/src/images/simulator/JumperT16/left.png create mode 100644 companion/src/images/simulator/JumperT16/left_mdl.png create mode 100644 companion/src/images/simulator/JumperT16/left_page.png create mode 100644 companion/src/images/simulator/JumperT16/left_scrnsht.png create mode 100644 companion/src/images/simulator/JumperT16/left_sys.png create mode 100644 companion/src/images/simulator/JumperT16/left_tele.png create mode 100644 companion/src/images/simulator/JumperT16/right.png create mode 100644 companion/src/images/simulator/JumperT16/right_ent.png create mode 100644 companion/src/images/simulator/JumperT16/right_rtn.png create mode 100644 companion/src/images/simulator/JumperT16/top.png create mode 100644 companion/src/simulation/simulateduiwidgetJumperT16.cpp create mode 100644 companion/src/simulation/simulateduiwidgetJumperT16.ui create mode 100755 radio/sdcard/horus/THEMES/Darkblue/t16.bmp create mode 100755 radio/sdcard/horus/THEMES/Default/t16.bmp create mode 100644 radio/src/io/multi_firmware_update.cpp create mode 100644 radio/src/io/multi_firmware_update.h create mode 100644 radio/src/io/stk500.h create mode 100644 radio/src/pulses/multi.h diff --git a/.travis.yml b/.travis.yml index cd3f1e948..442466067 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,7 @@ env: # - FLAVOR=X9D # - FLAVOR=X9D+ # - FLAVOR=X9E + - FLAVOR=T16 - FLAVOR=HORUS # - FLAVOR=X10 # - FLAVOR=X12Sr10 diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 61309d394..16245c848 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -347,6 +347,8 @@ elseif(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019) set(FLAVOUR x9d+2019) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL EXPRESS) set(FLAVOUR x10express) +elseif(PCB STREQUAL X10 AND PCBREV STREQUAL T16) + set(FLAVOUR t16) else() string(TOLOWER ${PCB} FLAVOUR) endif() diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index 2b4b18f71..567b52637 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -170,6 +170,17 @@ images/simulator/JumperT12/JumperT12-x.png images/simulator/JumperT12/JumperT12-center.png images/simulator/JumperT12/JumperT12-top.png + images/simulator/JumperT16/left.png + images/simulator/JumperT16/right.png + images/simulator/JumperT16/top.png + images/simulator/JumperT16/bottom.png + images/simulator/JumperT16/left_mdl.png + images/simulator/JumperT16/left_page.png + images/simulator/JumperT16/left_scrnsht.png + images/simulator/JumperT16/left_sys.png + images/simulator/JumperT16/left_tele.png + images/simulator/JumperT16/right_ent.png + images/simulator/JumperT16/right_rtn.png images/wizard/ailerons.png images/wizard/airbrakes.png images/wizard/elevons.png diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 99094edf3..809bc159a 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -89,6 +89,8 @@ uint32_t Boards::getFourCC(Type board) return 0; case BOARD_JUMPER_T12: return 0x3D78746F; + case BOARD_JUMPER_T16: + return 0x3F78746F; case BOARD_UNKNOWN: break; } @@ -127,6 +129,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_HORUS_X12S: case BOARD_X10: case BOARD_X10_EXPRESS: + case BOARD_JUMPER_T16: return 0; } @@ -162,6 +165,7 @@ int Boards::getFlashSize(Type board) case BOARD_HORUS_X12S: case BOARD_X10: case BOARD_X10_EXPRESS: + case BOARD_JUMPER_T16: return FSIZE_HORUS; case BOARD_UNKNOWN: return FSIZE_MAX; @@ -277,7 +281,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 2; else if (IS_TARANIS_X9E(board)) return 4; - else if (IS_HORUS_X10(board)) + else if (IS_HORUS_X10(board) || IS_JUMPER_T16(board)) return 5; else if (IS_HORUS_X12S(board)) return 3; @@ -293,7 +297,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) case Sliders: if (IS_HORUS_X12S(board) || IS_TARANIS_X9E(board)) return 4; - else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board)) + else if (IS_TARANIS_X9D(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) return 2; else return 0; @@ -458,7 +462,7 @@ QString Boards::getAnalogInputName(Board::Type board, int index) if (index < DIM(pots)) return pots[index]; } - else if (IS_HORUS_X10(board)) { + else if (IS_HORUS_X10(board) || IS_JUMPER_T16(board)) { const QString pots[] = { "S1", "6P", @@ -523,6 +527,8 @@ QString Boards::getBoardName(Board::Type board) return "Horus X10/X10S"; case BOARD_X10_EXPRESS: return "Horus X10 Express"; + case BOARD_JUMPER_T16: + return "Jumper T16"; default: return tr("Unknown"); } diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 7a60ad4f4..b7af393b6 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -52,9 +52,10 @@ namespace Board { BOARD_TARANIS_X9LITE, BOARD_TARANIS_X9LITES, BOARD_JUMPER_T12, + BOARD_JUMPER_T16, }; - constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T12 ; + constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_T16 ; enum PotType { @@ -223,6 +224,11 @@ inline bool IS_JUMPER_T12(Board::Type board) return board == Board::BOARD_JUMPER_T12; } +inline bool IS_JUMPER_T16(Board::Type board) +{ + return board == Board::BOARD_JUMPER_T16; +} + inline bool IS_TARANIS_XLITE(Board::Type board) { return board == Board::BOARD_TARANIS_XLITE || board == Board::BOARD_TARANIS_XLITES; @@ -285,7 +291,7 @@ inline bool IS_HORUS_X12S(Board::Type board) inline bool IS_HORUS(Board::Type board) { - return IS_HORUS_X12S(board) || IS_HORUS_X10(board); + return IS_HORUS_X12S(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board); } inline bool IS_HORUS_OR_TARANIS(Board::Type board) @@ -310,7 +316,7 @@ inline bool HAS_LARGE_LCD(Board::Type board) inline bool HAS_EXTERNAL_ANTENNA(Board::Type board) { - return (IS_HORUS(board) && board != Board::BOARD_X10_EXPRESS) || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board)); + return (board == Board::BOARD_X10 || board == Board::BOARD_HORUS_X12S || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))); } #endif // _BOARDS_H_ diff --git a/companion/src/firmwares/generalsettings.cpp b/companion/src/firmwares/generalsettings.cpp index 4f8532cd4..22934cf57 100644 --- a/companion/src/firmwares/generalsettings.cpp +++ b/companion/src/firmwares/generalsettings.cpp @@ -88,7 +88,7 @@ GeneralSettings::GeneralSettings() vBatMin = -5; //8,5V vBatMax = -5; //11,5V } - else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board)) { + else if (IS_TARANIS_XLITE(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) { // Lipo 2S vBatWarn = 66; vBatMin = -23; // 6.7V @@ -267,7 +267,7 @@ void GeneralSettings::setDefaultControlTypes(Board::Type board) sliderConfig[2] = Board::SLIDER_WITH_DETENT; sliderConfig[3] = Board::SLIDER_WITH_DETENT; } - else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board)) { + else if (IS_TARANIS_X9(board) || IS_HORUS_X10(board) || IS_JUMPER_T16(board)) { sliderConfig[0] = Board::SLIDER_WITH_DETENT; sliderConfig[1] = Board::SLIDER_WITH_DETENT; } diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 1ab1f3aba..7fcbb0cdc 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -68,6 +68,8 @@ const char * OpenTxEepromInterface::getName() return "OpenTX for Gruvin9x board / 9X"; case BOARD_JUMPER_T12: return "OpenTX for Jumper T12"; + case BOARD_JUMPER_T16: + return "OpenTX for Jumper T16"; case BOARD_TARANIS_X9D: return "OpenTX for FrSky Taranis X9D"; case BOARD_TARANIS_X9DP: @@ -770,18 +772,20 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) return true; case PULSES_PXX_XJT_X16: case PULSES_PXX_XJT_LR12: - return !(IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board)); + return !(IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_T16(board)); case PULSES_PXX_XJT_D8: - return !(IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || id.contains("eu")); + return !(IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_T16(board) || id.contains("eu")); case PULSES_PPM: return id.contains("internalppm"); case PULSES_ACCESS_ISRM: case PULSES_ACCST_ISRM_D16: return IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_HORUS(board) && id.contains("internalaccess")); + case PULSES_MULTIMODULE: + return id.contains("internalmulti"); default: return false; } - + case 1: switch (proto) { case PULSES_OFF: @@ -1291,6 +1295,12 @@ void registerOpenTxFirmwares() addOpenTxFontOptions(firmware); registerOpenTxFirmware(firmware); + /* Jumper T16 board */ + firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+"), BOARD_JUMPER_T16); + addOpenTxFrskyOptions(firmware); + firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module")); + registerOpenTxFirmware(firmware); + /* 9XR-Pro */ firmware = new OpenTxFirmware("opentx-9xrpro", Firmware::tr("Turnigy 9XR-PRO"), BOARD_9XRPRO); addOpenTxArm9xOptions(firmware, false); diff --git a/companion/src/images/simulator/JumperT16/JumperT16.svg b/companion/src/images/simulator/JumperT16/JumperT16.svg new file mode 100644 index 000000000..649a506c4 --- /dev/null +++ b/companion/src/images/simulator/JumperT16/JumperT16.svg @@ -0,0 +1,2594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + Activated button= black/opacity 40% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SYS + SYS + RTN + RTN + MDL + MDL + PAGE + PAGE + TELE + TELE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/companion/src/images/simulator/JumperT16/bottom.png b/companion/src/images/simulator/JumperT16/bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..8f0d29f7e4c93a2b813c766f31b5ce2b2cda5d22 GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0y~yV0-{%b8)Z%$()+rqdmmtT}V`<;yxP*J(3 zi(^Q|oVRy2@*Xzeadq@spuqfU&;LbjTuV=IIY#`*Yr1c{A@TLz`3wyIR)zC3G?)t| zFlZdIVLcB{>DqNWabOM8?tDnm{r-UW|2^CXQ literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/JumperT16/left.png b/companion/src/images/simulator/JumperT16/left.png new file mode 100644 index 0000000000000000000000000000000000000000..ed8f9e27fdd7f47b0c7f27b8edd0f7c918a2989d GIT binary patch literal 13936 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 Yy1IyeLtT^)9s+|X$*aj#$(V=!4+hHMvH$=8 literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/JumperT16/left_page.png b/companion/src/images/simulator/JumperT16/left_page.png new file mode 100644 index 0000000000000000000000000000000000000000..d135a33074f74bcf2166765b2b8ee5aed3e4d796 GIT binary patch literal 13954 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 literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/JumperT16/left_tele.png b/companion/src/images/simulator/JumperT16/left_tele.png new file mode 100644 index 0000000000000000000000000000000000000000..029506325fceac5155732552905ba6cc6dc9abca GIT binary patch literal 13902 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 ZO)?gldXT6Y0E5RMH6?AuI(h5x{{en)89D#} literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/JumperT16/right_rtn.png b/companion/src/images/simulator/JumperT16/right_rtn.png new file mode 100644 index 0000000000000000000000000000000000000000..00114f2a7904e3cc85ab92c02cea53c5cf66e40e GIT binary patch literal 11339 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 Af&c&j literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/JumperT16/top.png b/companion/src/images/simulator/JumperT16/top.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc1784ee2860dd9ffa705850dad1f93983f6aa6 GIT binary patch literal 439 zcmV;o0Z9IdP)B#)F`Hw}IF6?V%{>&{k39kQfE~Hmm5|HPEyeXQZQJ&AA|-?e;5vE) zN_X@X^yUh9nx-H{Jps)H0C2?RN3{(nmGbbJ13-LD>;e#8Zhw0MfLyrT1Fn1*0{{TF hH~|9y5WxEO-yc}D#MSsetupUi(this); diff --git a/companion/src/simulation/simulateduiwidgetJumperT16.cpp b/companion/src/simulation/simulateduiwidgetJumperT16.cpp new file mode 100644 index 000000000..317fdb24c --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperT16.cpp @@ -0,0 +1,69 @@ +/* + * 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. + */ + +// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h + +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetJumperT16.h" + +SimulatedUIWidgetJumperT16::SimulatedUIWidgetJumperT16(SimulatorInterface *simulator, QWidget * parent): + SimulatedUIWidget(simulator, parent), + ui(new Ui::SimulatedUIWidgetJumperT16) +{ + RadioUiAction * act; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + act = new RadioUiAction(3, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 70, 80, 35), "JumperT16/left_mdl.png", act)); + + act = new RadioUiAction(6, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 10, 80, 35), "JumperT16/left_sys.png", act)); + + act = new RadioUiAction(5, QList() << Qt::Key_Right, SIMU_STR_HLP_KEY_RGT, SIMU_STR_HLP_ACT_TELE); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 190, 80, 35), "JumperT16/left_tele.png", act)); + + act = new RadioUiAction(4, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, + SIMU_STR_HLP_KEY_DN % "
" % SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_RTN); + addRadioWidget(ui->rightbuttons->addArea(QRect(35, 10, 80, 35), "JumperT16/right_rtn.png", act)); + + act = new RadioUiAction(1, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN); + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 131, 80, 35), "JumperT16/left_page.png", act)); + + m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus, SIMU_STR_HLP_KEY_MIN % "|" % SIMU_STR_HLP_MOUSE_UP, SIMU_STR_HLP_ACT_ROT_LFT); + m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal, SIMU_STR_HLP_KEY_PLS % "|" % SIMU_STR_HLP_MOUSE_DN, SIMU_STR_HLP_ACT_ROT_RGT); + connectScrollActions(); + + m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(45, 70, 100, 160), "JumperT16/right_ent.png", m_mouseMidClickAction)); + + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 252, 30, 30), "JumperT16/left_scrnsht.png", m_screenshotAction)); + + m_backlightColors << QColor(47, 123, 227); + + setLcd(ui->lcd); +} + +SimulatedUIWidgetJumperT16::~SimulatedUIWidgetJumperT16() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetJumperT16.ui b/companion/src/simulation/simulateduiwidgetJumperT16.ui new file mode 100644 index 000000000..02085d7e7 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetJumperT16.ui @@ -0,0 +1,197 @@ + + + SimulatedUIWidgetJumperT16 + + + + 0 + 0 + 825 + 292 + + + + + 0 + 0 + + + + + 825 + 292 + + + + + 825 + 292 + + + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 174 + 292 + + + + + 174 + 292 + + + + background:url(:/images/simulator/JumperT16/right.png) + + + + + + + + 0 + 0 + + + + + 480 + 272 + + + + + 480 + 272 + + + + + 5 + + + + + + + + + 0 + 0 + + + + + 174 + 292 + + + + + 174 + 292 + + + + true + + + background:url(:/images/simulator/JumperT16/left.png); + + + + + + + + 0 + 0 + + + + + 480 + 10 + + + + + 480 + 10 + + + + + 5 + + + + background:url(:/images/simulator/JumperT16/top.png) + + + + + + + + 0 + 0 + + + + + 480 + 10 + + + + + 480 + 10 + + + + + 5 + false + + + + background:url(:/images/simulator/JumperT16/bottom.png) + + + + + + + + LcdWidget + QWidget +

lcdwidget.h
+ 1 + + + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+ + + + diff --git a/companion/src/simulation/simulatorstartupdialog.cpp b/companion/src/simulation/simulatorstartupdialog.cpp index 07766b7da..57272bf99 100644 --- a/companion/src/simulation/simulatorstartupdialog.cpp +++ b/companion/src/simulation/simulatorstartupdialog.cpp @@ -86,7 +86,7 @@ void SimulatorStartupDialog::changeEvent(QEvent *e) // FIXME : need a better way to check for this bool SimulatorStartupDialog::usesCategorizedStorage(const QString & name) { - return name.contains(QRegExp("(x12|x10|horus)", Qt::CaseInsensitive)); + return name.contains(QRegExp("(x12|x10|horus|t16)", Qt::CaseInsensitive)); } bool SimulatorStartupDialog::usesCategorizedStorage() diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index e5c7e2903..f823769aa 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -87,7 +87,10 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato break; case Board::BOARD_JUMPER_T12: radioUiWidget = new SimulatedUIWidgetJumperT12(simulator, this); - break; + break; + case Board::BOARD_JUMPER_T16: + radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this); + break; default: radioUiWidget = new SimulatedUIWidget9X(simulator, this); break; diff --git a/launchpad/common/rules b/launchpad/common/rules index 67b06466b..cf96b0fda 100755 --- a/launchpad/common/rules +++ b/launchpad/common/rules @@ -27,6 +27,7 @@ build: cd $(BUILDDIR); cmake $(COMMON_OPTIONS) $(STM32_OPTIONS) -DPCB=X9E ../ ; make libsimulator cd $(BUILDDIR); cmake $(COMMON_OPTIONS) $(STM32_OPTIONS) -DPCB=X12S ../ ; make libsimulator cd $(BUILDDIR); cmake $(COMMON_OPTIONS) $(STM32_OPTIONS) -DPCB=JUMPERT12 ../ ; make libsimulator + cd $(BUILDDIR); cmake $(COMMON_OPTIONS) $(STM32_OPTIONS) -DPCB=JUMPERT16 ../ ; make libsimulator make -C $(BUILDDIR) companion22 simulator22 diff --git a/radio/sdcard/horus/THEMES/Darkblue/t16.bmp b/radio/sdcard/horus/THEMES/Darkblue/t16.bmp new file mode 100755 index 0000000000000000000000000000000000000000..ac0d16cf6119ad1d3e791bf88258734cc443d9e0 GIT binary patch literal 164938 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 literal 0 HcmV?d00001 diff --git a/radio/sdcard/horus/THEMES/Default/t16.bmp b/radio/sdcard/horus/THEMES/Default/t16.bmp new file mode 100755 index 0000000000000000000000000000000000000000..ac0d16cf6119ad1d3e791bf88258734cc443d9e0 GIT binary patch literal 164938 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 literal 0 HcmV?d00001 diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 0052b0f6a..f4bc25566 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -208,20 +208,28 @@ enum TrainerMode { #if defined(BLUETOOTH) #define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH +#elif defined(RADIO_T16) + #define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE #elif defined(PCBX7) || defined(PCBXLITE) #define TRAINER_MODE_MAX() TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE #else #define TRAINER_MODE_MAX() HAS_WIRELESS_TRAINER_HARDWARE() ? TRAINER_MODE_MASTER_BATTERY_COMPARTMENT : TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE #endif -#if defined(PCBTARANIS) || defined(PCBHORUS) +#if defined(HARDWARE_INTERNAL_MODULE) #define IS_INTERNAL_MODULE_ENABLED() (g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE) -#elif defined(PCBSKY9X) +#else #define IS_INTERNAL_MODULE_ENABLED() (false) #endif #define IS_EXTERNAL_MODULE_ENABLED() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) +#if defined(HARDWARE_INTERNAL_MODULE) + #define IS_MODULE_ENABLED(moduleIdx) (moduleIdx==INTERNAL_MODULE ? IS_INTERNAL_MODULE_ENABLED() : moduleIdx==EXTERNAL_MODULE ? IS_EXTERNAL_MODULE_ENABLED() : false) +#else + #define IS_MODULE_ENABLED(moduleIdx) (moduleIdx==EXTERNAL_MODULE ? IS_EXTERNAL_MODULE_ENABLED() : false) +#endif + enum UartModes { #if defined(CLI) || defined(DEBUG) UART_MODE_DEBUG, diff --git a/radio/src/fifo.h b/radio/src/fifo.h index 35daef7ef..9aff60f57 100644 --- a/radio/src/fifo.h +++ b/radio/src/fifo.h @@ -77,11 +77,6 @@ class Fifo return (next == ridx); } - void flush() - { - while (!isEmpty()); - } - uint32_t size() const { return (N + widx - ridx) & (N - 1); diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index b89afc152..b70edf616 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -176,9 +176,6 @@ enum MenuModelSetupItems { #define SW_WARN_ROWS uint8_t(NAVIGATION_LINE_BY_LINE|(getSwitchWarningsCount()-1)), uint8_t(getSwitchWarningsCount() > MAX_SWITCH_PER_LINE ? TITLE_ROW : HIDDEN_ROW) #endif -#define IF_INTERNAL_MODULE_ON(x) (IS_INTERNAL_MODULE_ENABLED()? (uint8_t)(x) : HIDDEN_ROW) -#define IF_EXTERNAL_MODULE_ON(x) (IS_EXTERNAL_MODULE_ENABLED()? (uint8_t)(x) : HIDDEN_ROW) - #if defined(INTERNAL_MODULE_PXX1) #define INTERNAL_MODULE_TYPE_ROWS ((isModuleXJT(INTERNAL_MODULE) || isModulePXX2(INTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0) // Module type + RF protocols #else @@ -191,8 +188,6 @@ enum MenuModelSetupItems { #define OUTPUT_TYPE_ROW #endif -#define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 0) - inline uint8_t EXTERNAL_MODULE_TYPE_ROW() { if (isModuleXJT(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE)) @@ -283,7 +278,7 @@ void onBluetoothConnectMenu(const char * result) #define INTERNAL_MODULE_ROWS \ LABEL(InternalModule), \ INTERNAL_MODULE_TYPE_ROWS, \ - INTERNAL_MODULE_CHANNELS_ROWS, \ + MODULE_CHANNELS_ROWS(INTERNAL_MODULE), \ IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1)), \ IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* RxNum */ \ EXTERNAL_ANTENNA_ROW \ @@ -334,13 +329,13 @@ void menuModelSetup(event_t event) LABEL(ExternalModule), EXTERNAL_MODULE_TYPE_ROW(), MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) - EXTERNAL_MODULE_POWER_ROW, - MULTIMODULE_STATUS_ROWS - EXTERNAL_MODULE_CHANNELS_ROWS, - IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, EXTERNAL_MODULE_BIND_ROWS), // line reused for PPM: PPM settings + MODULE_POWER_ROW(EXTERNAL_MODULE), + MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), + IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum - IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, EXTERNAL_MODULE_OPTION_ROW), - MULTIMODULE_MODULE_ROWS + IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), + MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) FAILSAFE_ROWS(EXTERNAL_MODULE), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options @@ -355,13 +350,13 @@ void menuModelSetup(event_t event) LABEL(ExternalModule), EXTERNAL_MODULE_TYPE_ROW(), MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) - MULTIMODULE_STATUS_ROWS - EXTERNAL_MODULE_CHANNELS_ROWS, - EXTERNAL_MODULE_BIND_ROWS, + MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), + MODULE_BIND_ROWS(EXTERNAL_MODULE), OUTPUT_TYPE_ROW - EXTERNAL_MODULE_OPTION_ROW, - MULTIMODULE_MODULE_ROWS - EXTERNAL_MODULE_POWER_ROW, + MODULE_OPTION_ROW(EXTERNAL_MODULE), + MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) + MODULE_POWER_ROW(EXTERNAL_MODULE), FAILSAFE_ROWS(EXTERNAL_MODULE), EXTRA_MODULE_ROWS TRAINER_ROWS @@ -1066,26 +1061,24 @@ void menuModelSetup(event_t event) uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; lcdDrawTextAlignedLeft(y, STR_CHANNELRANGE); - if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) { - lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_CH, menuHorizontalPosition==0 ? attr : 0); - lcdDrawNumber(lcdLastRightPos, y, moduleData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0)); - lcdDrawChar(lcdLastRightPos, y, '-'); - lcdDrawNumber(lcdLastRightPos + FW+1, y, moduleData.channelsStart+sentModuleChannels(moduleIdx), LEFT | (menuHorizontalPosition==1 ? attr : 0)); - const char * delay = getModuleDelay(moduleIdx); - if (delay) - lcdDrawText(lcdLastRightPos+4, y, delay, SMLSIZE); - if (attr && s_editMode > 0) { - switch (menuHorizontalPosition) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount); - break; - case 1: - CHECK_INCDEC_MODELVAR_CHECK(event, moduleData.channelsCount, -4, min(maxModuleChannels_M8(moduleIdx), 32-8-moduleData.channelsStart), moduleData.type == MODULE_TYPE_ISRM_PXX2 ? isPxx2IsrmChannelsCountAllowed : nullptr); - if (checkIncDec_Ret && moduleData.type == MODULE_TYPE_PPM) { - setDefaultPpmFrameLength(moduleIdx); - } - break; - } + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_CH, menuHorizontalPosition==0 ? attr : 0); + lcdDrawNumber(lcdLastRightPos, y, moduleData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0)); + lcdDrawChar(lcdLastRightPos, y, '-'); + lcdDrawNumber(lcdLastRightPos + FW+1, y, moduleData.channelsStart+sentModuleChannels(moduleIdx), LEFT | (menuHorizontalPosition==1 ? attr : 0)); + const char * delay = getModuleDelay(moduleIdx); + if (delay) + lcdDrawText(lcdLastRightPos+4, y, delay, SMLSIZE); + if (attr && s_editMode > 0) { + switch (menuHorizontalPosition) { + case 0: + CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount); + break; + case 1: + CHECK_INCDEC_MODELVAR_CHECK(event, moduleData.channelsCount, -4, min(maxModuleChannels_M8(moduleIdx), 32-8-moduleData.channelsStart), moduleData.type == MODULE_TYPE_ISRM_PXX2 ? isPxx2IsrmChannelsCountAllowed : nullptr); + if (checkIncDec_Ret && moduleData.type == MODULE_TYPE_PPM) { + setDefaultPpmFrameLength(moduleIdx); + } + break; } } break; @@ -1270,8 +1263,8 @@ void menuModelSetup(event_t event) lcdDrawText(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); uint8_t newFlag = 0; #if defined(MULTIMODULE) - if (multiBindStatus == MULTI_BIND_FINISHED) { - multiBindStatus = MULTI_NORMAL_OPERATION; + if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) { + setMultiBindStatus(moduleIdx, MULTI_NORMAL_OPERATION); s_editMode = 0; } #endif @@ -1321,7 +1314,7 @@ void menuModelSetup(event_t event) #if defined(MULTIMODULE) if (newFlag == MODULE_MODE_BIND) { - multiBindStatus = MULTI_BIND_INITIATED; + setMultiBindStatus(moduleIdx, MULTI_BIND_INITIATED); } #endif @@ -1532,7 +1525,7 @@ void menuModelSetup(event_t event) lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS); char statusText[64]; - multiModuleStatus.getStatusString(statusText); + getMultiModuleStatus(EXTERNAL_MODULE).getStatusString(statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } @@ -1541,7 +1534,7 @@ void menuModelSetup(event_t event) lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC); char statusText[64]; - multiSyncStatus.getRefreshString(statusText); + getMultiSyncStatus(EXTERNAL_MODULE).getRefreshString(statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 4637d8634..5ae189763 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -230,8 +230,6 @@ void editTimerCountdown(int timerIdx, coord_t y, LcdFlags attr, event_t event) #define INTERNAL_MODULE_TYPE_ROWS (0) // Module type + RF protocols #endif -#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 1)) - #define TRAINER_CHANNELS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)1 : HIDDEN_ROW) #define TRAINER_PPM_PARAMS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW) #define TRAINER_BLUETOOTH_M_ROW ((bluetooth.distantAddr[0] == '\0' || bluetooth.state == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1) @@ -352,7 +350,7 @@ void menuModelSetup(event_t event) LABEL(InternalModule), INTERNAL_MODULE_TYPE_ROWS, - INTERNAL_MODULE_CHANNELS_ROWS, + MODULE_CHANNELS_ROWS(INTERNAL_MODULE), IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(isModuleFailsafeAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1)), IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // RxNum for ACCESS IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), // Failsafe @@ -364,13 +362,13 @@ void menuModelSetup(event_t event) LABEL(ExternalModule), EXTERNAL_MODULE_TYPE_ROW(), - MULTIMODULE_STATUS_ROWS - EXTERNAL_MODULE_CHANNELS_ROWS, - IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, EXTERNAL_MODULE_BIND_ROWS), + MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), + IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum for ACCESS - IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, EXTERNAL_MODULE_OPTION_ROW), - MULTIMODULE_MODULE_ROWS - EXTERNAL_MODULE_POWER_ROW, + IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), + MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) + MODULE_POWER_ROW(EXTERNAL_MODULE), FAILSAFE_ROWS(EXTERNAL_MODULE), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options @@ -1019,7 +1017,7 @@ void menuModelSetup(event_t event) uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; lcdDrawTextAlignedLeft(y, STR_CHANNELRANGE); - if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) { + if ((int8_t)MODULE_CHANNELS_ROWS(moduleIdx) >= 0) { lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_CH, menuHorizontalPosition==0 ? attr : 0); lcdDrawNumber(lcdLastRightPos, y, moduleData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0)); lcdDrawChar(lcdLastRightPos, y, '-'); @@ -1144,8 +1142,8 @@ void menuModelSetup(event_t event) lcdDrawText(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); uint8_t newFlag = 0; #if defined(MULTIMODULE) - if (multiBindStatus == MULTI_BIND_FINISHED) { - multiBindStatus = MULTI_NORMAL_OPERATION; + if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) { + setMultiBindStatus(moduleIdx, MULTI_NORMAL_OPERATION); s_editMode = 0; } #endif @@ -1178,7 +1176,7 @@ void menuModelSetup(event_t event) moduleState[moduleIdx].mode = newFlag; #if defined(MULTIMODULE) if (newFlag == MODULE_MODE_BIND) - multiBindStatus = MULTI_BIND_INITIATED; + setMultiBindStatus(moduleIdx, MULTI_BIND_INITIATED); #endif } } @@ -1317,7 +1315,7 @@ void menuModelSetup(event_t event) { lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS); char statusText[64]; - multiModuleStatus.getStatusString(statusText); + getMultiModuleStatus(EXTERNAL_MODULE).getStatusString(statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } @@ -1326,7 +1324,7 @@ void menuModelSetup(event_t event) { lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC); char statusText[64]; - multiSyncStatus.getRefreshString(statusText); + getMultiSyncStatus(EXTERNAL_MODULE).getRefreshString(statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index c759bfb77..ed166cb1e 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -66,22 +66,31 @@ enum MenuModelSetupItems { #if defined(PXX2) ITEM_MODEL_SETUP_REGISTRATION_ID, #endif - +#if defined(HARDWARE_INTERNAL_MODULE) ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL, ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE, +#if defined(INTERNAL_MODULE_MULTI) + ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, + ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS, +#endif ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS, ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM, + ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS, +#if defined(INTERNAL_MODULE_MULTI) + ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND, +#endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA, #endif + ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER, ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_3, - +#endif ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL, ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE, #if defined(MULTIMODULE) @@ -122,7 +131,11 @@ enum MenuModelSetupItems { #define MODEL_SETUP_SLIDPOT_SPACING 45 #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE) +#if defined(HARDWARE_INTERNAL_MODULE) #define CURRENT_RECEIVER_EDITED(k) (k - (k >= ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL ? ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_1 : ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1)) +#else +#define CURRENT_RECEIVER_EDITED(k) (EXTERNAL_MODULE) +#endif #include "common/stdlcd/model_setup_pxx1.cpp" @@ -468,19 +481,15 @@ int getSwitchWarningsCount() #define IF_ACCESS_MODULE_RF(module, xxx) (isModuleRFAccess(module) ? (uint8_t)(xxx) : HIDDEN_ROW) #define IF_NOT_ACCESS_MODULE_RF(module, xxx) (isModuleRFAccess(module) ? HIDDEN_ROW : (uint8_t)(xxx)) -#define INTERNAL_MODULE_TYPE_ROWS ((isModuleXJT(INTERNAL_MODULE) || isModulePXX2(INTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0) // Module type + RF protocols - -#define MODULE_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 1)) - #define TIMER_ROWS(x) NAVIGATION_LINE_BY_LINE|1, 0, 0, 0, g_model.timers[x].countdownBeep != COUNTDOWN_SILENT ? (uint8_t)1 : (uint8_t)0 -inline uint8_t EXTERNAL_MODULE_TYPE_ROW() +inline uint8_t MODULE_TYPE_ROWS(int moduleIdx) { - if (isModuleXJT(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE)) + if (isModuleXJT(moduleIdx) || isModuleR9MNonAccess(moduleIdx) || isModuleDSM2(moduleIdx) || isModulePXX2(moduleIdx)) return 1; #if defined(MULTIMODULE) - else if (isModuleMultimodule(EXTERNAL_MODULE)) { - return 1 + MULTIMODULE_RFPROTO_COLUMNS(EXTERNAL_MODULE); + else if (isModuleMultimodule(moduleIdx)) { + return 1 + MULTIMODULE_RFPROTO_COLUMNS(moduleIdx); } #endif else @@ -495,6 +504,7 @@ inline uint8_t EXTERNAL_MODULE_TYPE_ROW() #define TIMERS_ROWS TIMER_ROWS(0), TIMER_ROWS(1), TIMER_ROWS(2) #endif +#if defined(BLUETOOTH) #define TRAINER_CHANNELS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? (uint8_t)0 : HIDDEN_ROW)) #define TRAINER_PPM_PARAMS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW) #define IF_BT_TRAINER_ON(x) (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER ? (uint8_t)(x) : HIDDEN_ROW) @@ -502,6 +512,11 @@ inline uint8_t EXTERNAL_MODULE_TYPE_ROW() #define TRAINER_BLUETOOTH_S_ROW (bluetooth.distantAddr[0] == '\0' ? HIDDEN_ROW : LABEL()) #define TRAINER_BLUETOOTH_ROW (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW)) #define TRAINER_ROWS LABEL(Trainer), 0, IF_BT_TRAINER_ON(TRAINER_BLUETOOTH_ROW), TRAINER_CHANNELS_ROW, TRAINER_PPM_PARAMS_ROW +#else +#define TRAINER_CHANNELS_ROW (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : HIDDEN_ROW) +#define TRAINER_PPM_PARAMS_ROW (HIDDEN_ROW) +#define TRAINER_ROWS LABEL(Trainer), 0, TRAINER_CHANNELS_ROW, TRAINER_PPM_PARAMS_ROW +#endif #if defined(PXX2) #define REGISTRATION_ID_ROWS uint8_t((isDefaultModelRegistrationID() || (warningText && popupFunc == runPopupRegister)) ? HIDDEN_ROW : READONLY_ROW), @@ -527,11 +542,35 @@ void onModelAntennaSwitchConfirm(const char * result) #define EXTERNAL_ANTENNA_ROW #endif +#if defined(HARDWARE_INTERNAL_MODULE) + #define INTERNAL_MODULE_ROWS \ + LABEL(InternalModule), \ + MODULE_TYPE_ROWS(INTERNAL_MODULE), \ + MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) \ + MODULE_CHANNELS_ROWS(INTERNAL_MODULE), \ + IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), \ + MODULE_OPTION_ROW(INTERNAL_MODULE), \ + MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) \ + EXTERNAL_ANTENNA_ROW \ + MODULE_POWER_ROW(INTERNAL_MODULE), \ + IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), /* Range check and Register buttons */ \ + IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* Module options */ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 1 */ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 2 */ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 3 */ +#else + #define INTERNAL_MODULE_ROWS +#endif + + bool menuModelSetup(event_t event) { bool CURSOR_ON_CELL = (menuHorizontalPosition >= 0); int8_t old_editMode = s_editMode; + MENU(STR_MENUSETUP, MODEL_ICONS, menuTabModel, MENU_MODEL_SETUP, ITEM_MODEL_SETUP_MAX, { 0, // Model name 0, // Model bitmap @@ -559,28 +598,17 @@ bool menuModelSetup(event_t event) REGISTRATION_ID_ROWS - LABEL(InternalModule), - INTERNAL_MODULE_TYPE_ROWS, - INTERNAL_MODULE_CHANNELS_ROWS, - IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), // RxNum - EXTERNAL_ANTENNA_ROW - IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), /* Range check and Register buttons */ \ - IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* Module options */ \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 1 */ \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 2 */ \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 3 */ + INTERNAL_MODULE_ROWS LABEL(ExternalModule), - EXTERNAL_MODULE_TYPE_ROW(), - MULTIMODULE_STATUS_ROWS - EXTERNAL_MODULE_CHANNELS_ROWS, - IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, EXTERNAL_MODULE_BIND_ROWS), + MODULE_TYPE_ROWS(EXTERNAL_MODULE), + MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), + IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum for ACCESS - IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, EXTERNAL_MODULE_OPTION_ROW), - MULTIMODULE_MODULE_ROWS - EXTERNAL_MODULE_POWER_ROW, + IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), + MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) + MODULE_POWER_ROW(EXTERNAL_MODULE), FAILSAFE_ROWS(EXTERNAL_MODULE), IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options @@ -613,7 +641,7 @@ bool menuModelSetup(event_t event) if (mstate_tab[j] == HIDDEN_ROW) k++; } - + uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS); LcdFlags attr = (sub == k ? blink : 0); @@ -945,10 +973,12 @@ bool menuModelSetup(event_t event) if (attr) g_model.noGlobalFunctions = !checkIncDecModel(event, !g_model.noGlobalFunctions, 0, 1); break; +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_INTERNALRF); break; +#if !defined(INTERNAL_MODULE_MULTI) case ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE: lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_INTERNAL_MODULE_PROTOCOLS, g_model.moduleData[INTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); @@ -976,6 +1006,7 @@ bool menuModelSetup(event_t event) } } break; +#endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) case ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA: @@ -993,111 +1024,124 @@ bool menuModelSetup(event_t event) } break; #endif - +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_EXTERNALRF); break; +#if defined(INTERNAL_MODULE_MULTI) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE: lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MODE); - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); - if (isModuleXJT(EXTERNAL_MODULE)) - lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_XJT_ACCST_RF_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0)); - else if (isModuleDSM2(EXTERNAL_MODULE)) - lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0)); - else if (isModuleR9MNonAccess(EXTERNAL_MODULE)) - lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0)); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, g_model.moduleData[moduleIdx].type, menuHorizontalPosition==0 ? attr : 0); + if (isModuleXJT(moduleIdx)) + lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_XJT_ACCST_RF_PROTOCOLS, 1+g_model.moduleData[moduleIdx].subType, (menuHorizontalPosition==1 ? attr : 0)); + else if (isModuleDSM2(moduleIdx)) + lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_DSM_PROTOCOLS, g_model.moduleData[moduleIdx].rfProtocol, (menuHorizontalPosition==1 ? attr : 0)); + else if (isModuleR9MNonAccess(moduleIdx)) + lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_R9M_REGION, g_model.moduleData[moduleIdx].subType, (menuHorizontalPosition==1 ? attr : 0)); #if defined(MULTIMODULE) - else if (isModuleMultimodule(EXTERNAL_MODULE)) { - int multi_rfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false); - if (g_model.moduleData[EXTERNAL_MODULE].multi.customProto) { + else if (isModuleMultimodule(moduleIdx)) { + int multi_rfProto = g_model.moduleData[moduleIdx].getMultiProtocol(false); + if (g_model.moduleData[moduleIdx].multi.customProto) { lcdDrawText(MODEL_SETUP_3RD_COLUMN, y, STR_MULTI_CUSTOM, menuHorizontalPosition == 1 ? attr : 0); lcdDrawNumber(MODEL_SETUP_4TH_COLUMN, y, multi_rfProto, menuHorizontalPosition==2 ? attr : 0, 2); - lcdDrawNumber(MODEL_SETUP_4TH_COLUMN + MODEL_SETUP_BIND_OFS, y, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==3 ? attr : 0, 2); + lcdDrawNumber(MODEL_SETUP_4TH_COLUMN + MODEL_SETUP_BIND_OFS, y, g_model.moduleData[moduleIdx].subType, menuHorizontalPosition==3 ? attr : 0, 2); } else { const mm_protocol_definition * pdef = getMultiProtocolDefinition(multi_rfProto); lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_MULTI_PROTOCOLS, multi_rfProto, menuHorizontalPosition == 1 ? attr : 0); if (pdef->subTypeString != nullptr) - lcdDrawTextAtIndex(MODEL_SETUP_4TH_COLUMN, y, pdef->subTypeString, g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==2 ? attr : 0); + lcdDrawTextAtIndex(MODEL_SETUP_4TH_COLUMN, y, pdef->subTypeString, g_model.moduleData[moduleIdx].subType, menuHorizontalPosition==2 ? attr : 0); } } #endif + if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) { + if (s_editMode > 0) + EXTERNAL_MODULE_OFF(); + else + EXTERNAL_MODULE_ON(); + } if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { case 0: { - uint8_t moduleType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, isExternalModuleAvailable); +#if defined(HARDWARE_INTERNAL_MODULE) + IsValueAvailable checkFun = moduleIdx == 0 ? isInternalModuleAvailable : isExternalModuleAvailable; +#else + IsValueAvailable checkFun = isExternalModuleAvailable; +#endif + uint8_t moduleType = checkIncDec(event, g_model.moduleData[moduleIdx].type, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, checkFun); if (checkIncDec_Ret) { - setModuleType(EXTERNAL_MODULE, moduleType); + setModuleType(moduleIdx, moduleType); } break; } - case 1: - if (isModuleDSM2(EXTERNAL_MODULE)) - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX); + if (isModuleDSM2(moduleIdx)) + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX); #if defined(MULTIMODULE) - else if (isModuleMultimodule(EXTERNAL_MODULE)) { - int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].multi.customProto == 1 ? MODULE_SUBTYPE_MULTI_CUSTOM : g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false); + else if (isModuleMultimodule(moduleIdx)) { + int multiRfProto = g_model.moduleData[moduleIdx].multi.customProto == 1 ? MODULE_SUBTYPE_MULTI_CUSTOM : g_model.moduleData[moduleIdx].getMultiProtocol(false); CHECK_INCDEC_MODELVAR(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST); if (checkIncDec_Ret) { - g_model.moduleData[EXTERNAL_MODULE].multi.customProto = (multiRfProto == MODULE_SUBTYPE_MULTI_CUSTOM); - if (!g_model.moduleData[EXTERNAL_MODULE].multi.customProto) - g_model.moduleData[EXTERNAL_MODULE].setMultiProtocol(multiRfProto); - g_model.moduleData[EXTERNAL_MODULE].subType = 0; + g_model.moduleData[moduleIdx].multi.customProto = (multiRfProto == MODULE_SUBTYPE_MULTI_CUSTOM); + if (!g_model.moduleData[moduleIdx].multi.customProto) + g_model.moduleData[moduleIdx].setMultiProtocol(multiRfProto); + g_model.moduleData[moduleIdx].subType = 0; // Sensible default for DSM2 (same as for ppm): 7ch@22ms + Autodetect settings enabled - if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2) { - g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = 1; + if (g_model.moduleData[moduleIdx].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2) { + g_model.moduleData[moduleIdx].multi.autoBindMode = 1; } else { - g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = 0; + g_model.moduleData[moduleIdx].multi.autoBindMode = 0; } - g_model.moduleData[EXTERNAL_MODULE].multi.optionValue = 0; + g_model.moduleData[moduleIdx].multi.optionValue = 0; } } #endif - else if (isModuleR9MNonAccess(EXTERNAL_MODULE)) { - g_model.moduleData[EXTERNAL_MODULE].subType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].subType, MODULE_SUBTYPE_R9M_FCC, + else if (isModuleR9MNonAccess(moduleIdx)) { + g_model.moduleData[moduleIdx].subType = checkIncDec(event, g_model.moduleData[moduleIdx].subType, MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_LAST, EE_MODEL, isR9MModeAvailable); } else { - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, MODULE_SUBTYPE_PXX1_ACCST_D16, MODULE_SUBTYPE_PXX1_LAST); + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, MODULE_SUBTYPE_PXX1_ACCST_D16, MODULE_SUBTYPE_PXX1_LAST); } if (checkIncDec_Ret) { - g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; - g_model.moduleData[EXTERNAL_MODULE].channelsCount = defaultModuleChannels_M8(EXTERNAL_MODULE); + g_model.moduleData[moduleIdx].channelsStart = 0; + g_model.moduleData[moduleIdx].channelsCount = defaultModuleChannels_M8(moduleIdx); } break; #if defined(MULTIMODULE) case 2: - if (g_model.moduleData[EXTERNAL_MODULE].multi.customProto) { - g_model.moduleData[EXTERNAL_MODULE].setMultiProtocol(checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false), 0, 63, EE_MODEL)); + if (g_model.moduleData[moduleIdx].multi.customProto) { + g_model.moduleData[moduleIdx].setMultiProtocol(checkIncDec(event, g_model.moduleData[moduleIdx].getMultiProtocol(false), 0, 63, EE_MODEL)); break; } else { - const mm_protocol_definition *pdef = getMultiProtocolDefinition(g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false)); + const mm_protocol_definition *pdef = getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol(false)); if (pdef->maxSubtype > 0) - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, pdef->maxSubtype); + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, 0, pdef->maxSubtype); } break; case 3: // Custom protocol, third column is subtype - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].subType, 0, 7); + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, 0, 7); break; #endif } } #if POPUP_LEVEL > 1 else if (old_editMode > 0) { - if (isModuleR9MNonAccess(EXTERNAL_MODULE)) { - if (g_model.moduleData[EXTERNAL_MODULE].subType > MODULE_SUBTYPE_R9M_EU) { + if (isModuleR9MNonAccess(moduleIdx)) { + if (g_model.moduleData[moduleIdx].subType > MODULE_SUBTYPE_R9M_EU) { POPUP_WARNING(STR_MODULE_PROTOCOL_FLEX_WARN_LINE1); SET_WARNING_INFO(STR_MODULE_PROTOCOL_WARN_LINE2, sizeof(TR_MODULE_PROTOCOL_WARN_LINE2) - 1, 0); } #if POPUP_LEVEL >= 3 - else if (g_model.moduleData[EXTERNAL_MODULE].subType == MODULE_SUBTYPE_R9M_EU) { + else if (g_model.moduleData[moduleIdx].subType == MODULE_SUBTYPE_R9M_EU) { POPUP_WARNING(STR_MODULE_PROTOCOL_EU_WARN_LINE1); SET_WARNING_INFO(STR_MODULE_PROTOCOL_WARN_LINE2, sizeof(TR_MODULE_PROTOCOL_WARN_LINE2) - 1, 0); } @@ -1111,11 +1155,11 @@ bool menuModelSetup(event_t event) #endif } break; - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CHANNELRANGE); if ((int8_t)MODULE_CHANNELS_ROWS(moduleIdx) >= 0) { @@ -1141,7 +1185,6 @@ bool menuModelSetup(event_t event) } break; } - case ITEM_MODEL_SETUP_TRAINER_LABEL: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRAINER); break; @@ -1149,12 +1192,15 @@ bool menuModelSetup(event_t event) case ITEM_MODEL_SETUP_TRAINER_MODE: lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MODE); g_model.trainerData.mode = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), attr, event); +#if defined(BLUETOOTH) if (attr && checkIncDec_Ret) { bluetooth.state = BLUETOOTH_STATE_OFF; bluetooth.distantAddr[0] = 0; } +#endif break; +#if defined(BLUETOOTH) case ITEM_MODEL_SETUP_TRAINER_BLUETOOTH: if (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH) { if (attr) { @@ -1194,6 +1240,7 @@ bool menuModelSetup(event_t event) } } break; +#endif case ITEM_MODEL_SETUP_TRAINER_CHANNELS: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CHANNELRANGE); @@ -1242,10 +1289,11 @@ bool menuModelSetup(event_t event) break; #endif +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RECEIVER_NUM); lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], attr | LEADING0 | LEFT, 2); if (attr) { @@ -1261,11 +1309,11 @@ bool menuModelSetup(event_t event) } } break; - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_REGISTER_RANGE: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MODULE); drawButton(MODEL_SETUP_2ND_COLUMN, y, STR_REGISTER, (menuHorizontalPosition == 0 ? attr : 0)); drawButton(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_MODULE_RANGE, (menuHorizontalPosition == 1 ? attr : 0)); @@ -1288,8 +1336,9 @@ bool menuModelSetup(event_t event) } } break; - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_OPTIONS: lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_OPTIONS); drawButton(MODEL_SETUP_2ND_COLUMN, y, STR_SET, attr); @@ -1298,15 +1347,15 @@ bool menuModelSetup(event_t event) pushMenu(menuModelModuleOptions); } break; - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1: case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2: case ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_3: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_1: case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_2: case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_3: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); uint8_t receiverIdx = CURRENT_RECEIVER_EDITED(k); ModuleInformation & moduleInformation = reusableBuffer.moduleSetup.pxx2.moduleInformation; @@ -1382,11 +1431,11 @@ bool menuModelSetup(event_t event) } } break; - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; if (isModulePPM(moduleIdx)) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PPMFRAME); @@ -1454,8 +1503,8 @@ bool menuModelSetup(event_t event) drawButton(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==2 ? attr : 0)); uint8_t newFlag = 0; #if defined(MULTIMODULE) - if (multiBindStatus == MULTI_BIND_FINISHED) { - multiBindStatus = MULTI_NORMAL_OPERATION; + if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) { + setMultiBindStatus(moduleIdx, MULTI_NORMAL_OPERATION); s_editMode = 0; } #endif @@ -1488,17 +1537,17 @@ bool menuModelSetup(event_t event) moduleState[moduleIdx].mode = newFlag; #if defined(MULTIMODULE) if (newFlag == MODULE_MODE_BIND) - multiBindStatus = MULTI_BIND_INITIATED; + setMultiBindStatus(moduleIdx, MULTI_BIND_INITIATED); #endif } } break; } - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FAILSAFE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, menuHorizontalPosition==0 ? attr : 0); @@ -1536,15 +1585,16 @@ bool menuModelSetup(event_t event) } break; } - +#if defined(HARDWARE_INTERNAL_MODULE) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); #if defined(MULTIMODULE) if (isModuleMultimodule(moduleIdx)) { int optionValue = g_model.moduleData[moduleIdx].multi.optionValue; - const uint8_t multi_proto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true); + const uint8_t multi_proto = g_model.moduleData[moduleIdx].getMultiProtocol(true); const mm_protocol_definition *pdef = getMultiProtocolDefinition(multi_proto); if (pdef->optionsstr) lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, pdef->optionsstr); @@ -1580,13 +1630,14 @@ bool menuModelSetup(event_t event) } break; } - +#if defined(HARDWARE_INTERNAL_MODULE) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER: { - uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); if (isModuleR9MNonAccess(moduleIdx)) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RFPOWER); - if(isModuleR9M_FCC_VARIANT(moduleIdx)) { + if (isModuleR9M_FCC_VARIANT(moduleIdx)) { lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9M_FCC_POWER_VALUES, g_model.moduleData[moduleIdx].pxx.power, LEFT | attr); if (attr) CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].pxx.power, 0, R9M_FCC_POWER_MAX); @@ -1596,7 +1647,7 @@ bool menuModelSetup(event_t event) if (attr) CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].pxx.power, 0, R9M_LBT_POWER_MAX); if (attr && s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) { - if((reusableBuffer.moduleSetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) { //switching between mode 2 and 3 does not require rebind + if ((reusableBuffer.moduleSetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) { //switching between mode 2 and 3 does not require rebind POPUP_WARNING(STR_WARNING); SET_WARNING_INFO(STR_REBIND, sizeof(TR_REBIND), 0); } @@ -1607,39 +1658,49 @@ bool menuModelSetup(event_t event) #if defined(MULTIMODULE) else if (isModuleMultimodule(moduleIdx)) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_LOWPOWER); - g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.moduleData[moduleIdx].multi.lowPowerMode = editCheckBox(g_model.moduleData[moduleIdx].multi.lowPowerMode, MODEL_SETUP_2ND_COLUMN, y, attr, event); } #endif } - break; + break; #if defined(MULTIMODULE) +#if defined(INTERNAL_MODULE_MULTI) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND: +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND: - if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2) + if (g_model.moduleData[moduleIdx].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_DSM_AUTODTECT); else lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_AUTOBIND); - g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode = editCheckBox(g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; - - case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: { +#if defined(INTERNAL_MODULE_MULTI) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS: +#endif + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: + { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODULE_STATUS); char statusText[64]; - multiModuleStatus.getStatusString(statusText); + getMultiModuleStatus(moduleIdx).getStatusString(statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; - - case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: { + } +#if defined(INTERNAL_MODULE_MULTI) + case ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS: +#endif + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: + { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODULE_SYNC); char statusText[64]; - multiSyncStatus.getRefreshString(statusText); + getMultiSyncStatus(moduleIdx).getRefreshString(statusText); lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; - } } #endif + } } @@ -1656,7 +1717,7 @@ bool menuModelSetup(event_t event) case ITEM_MODEL_SETUP_NAME: mod_cell->setModelName(g_model.header.name); break; - +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND: if (menuHorizontalPosition != 0) break; @@ -1664,7 +1725,7 @@ bool menuModelSetup(event_t event) mod_cell->setRfData(&g_model); checkModelIdUnique(INTERNAL_MODULE); break; - +#endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND: if (menuHorizontalPosition != 0) break; @@ -1672,6 +1733,7 @@ bool menuModelSetup(event_t event) mod_cell->setRfData(&g_model); if (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) checkModelIdUnique(EXTERNAL_MODULE); + break; } } } diff --git a/radio/src/gui/480x272/radio_hardware.cpp b/radio/src/gui/480x272/radio_hardware.cpp index db5fbc759..89a5aabff 100644 --- a/radio/src/gui/480x272/radio_hardware.cpp +++ b/radio/src/gui/480x272/radio_hardware.cpp @@ -55,10 +55,11 @@ enum MenuRadioHardwareItems { ITEM_RADIO_HARDWARE_BATTERY_CALIB, ITEM_RADIO_HARDWARE_RTC_BATTERY, ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE, +#if defined(BLUETOOTH) ITEM_RADIO_HARDWARE_BLUETOOTH_MODE, ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE, ITEM_RADIO_HARDWARE_BLUETOOTH_NAME, - +#endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA, #endif @@ -77,7 +78,11 @@ enum MenuRadioHardwareItems { #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 -#define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode != BLUETOOTH_TELEMETRY ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? -1 : 0) +#if defined(BLUETOOTH) + #define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode != BLUETOOTH_TELEMETRY ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? -1 : 0), +#else + #define BLUETOOTH_ROWS +#endif // TODO should be moved to the HAL #define SWITCH_TYPE_MAX(sw) ((MIXSRC_SF-MIXSRC_FIRST_SWITCH == sw || MIXSRC_SH-MIXSRC_FIRST_SWITCH == sw || MIXSRC_SI-MIXSRC_FIRST_SWITCH == sw || MIXSRC_SJ-MIXSRC_FIRST_SWITCH == sw) ? SWITCH_2POS : SWITCH_3POS) @@ -121,7 +126,7 @@ bool menuRadioHardware(event_t event) 0, /* max baudrate */ - BLUETOOTH_ROWS, + BLUETOOTH_ROWS EXTERNAL_ANTENNA_ROW @@ -270,7 +275,7 @@ bool menuRadioHardware(event_t event) } } break; - +#if defined(BLUETOOTH) case ITEM_RADIO_HARDWARE_BLUETOOTH_MODE: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BLUETOOTH); g_eeGeneral.bluetoothMode = editChoice(HW_SETTINGS_COLUMN+50, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER, attr, event); @@ -285,6 +290,7 @@ bool menuRadioHardware(event_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_NAME); editName(HW_SETTINGS_COLUMN+50, y, g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME, event, attr); break; +#endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) case ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA: diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp index 4c82c42fe..0534e6bbf 100644 --- a/radio/src/gui/480x272/radio_sdmanager.cpp +++ b/radio/src/gui/480x272/radio_sdmanager.cpp @@ -19,7 +19,8 @@ */ #include -#include +#include "io/frsky_firmware_update.h" +#include "io/multi_firmware_update.h" #include "opentx.h" #include "storage/modelslist.h" @@ -173,6 +174,18 @@ void onSdManagerMenu(const char * result) FrskyDeviceFirmwareUpdate device(SPORT_MODULE); device.flashFirmware(lfn); } +#if defined(MULTIMODULE) +#if defined(INTERNAL_MODULE_MULTI) + else if (result == STR_FLASH_INTERNAL_MULTI) { + getSelectionFullPath(lfn); + multiFlashFirmware(INTERNAL_MODULE, lfn); + } +#endif + else if (result == STR_FLASH_EXTERNAL_MULTI) { + getSelectionFullPath(lfn); + multiFlashFirmware(EXTERNAL_MODULE, lfn); + } +#endif #if defined(LUA) else if (result == STR_EXECUTE_FILE) { getSelectionFullPath(lfn); @@ -258,9 +271,22 @@ bool menuRadioSdManager(event_t _event) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE); } - else if (!READ_ONLY() && !strcasecmp(ext, UPDATE_FIRMWARE_EXT)) { +#if defined(MULTIMODULE) + else if (!READ_ONLY() && !strcasecmp(ext, MULTI_FIRMWARE_EXT)) { + TCHAR lfn[_MAX_LFN + 1]; + getSelectionFullPath(lfn); + MultiFirmwareInformation information; + if (information.readMultiFirmwareInformation(line) == nullptr) { +#if defined(INTERNAL_MODULE_MULTI) + POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MULTI); +#endif + POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MULTI); + } +#endif + } + else if (!READ_ONLY() && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) { FrSkyFirmwareInformation information; - if (readFirmwareInformation(line, information) == nullptr) { + if (readFrSkyFirmwareInformation(line, information) == nullptr) { if (information.productFamily == FIRMWARE_FAMILY_INTERNAL_MODULE) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); if (information.productFamily == FIRMWARE_FAMILY_EXTERNAL_MODULE) diff --git a/radio/src/gui/480x272/themes/default.cpp b/radio/src/gui/480x272/themes/default.cpp index d444a6994..84b23e168 100644 --- a/radio/src/gui/480x272/themes/default.cpp +++ b/radio/src/gui/480x272/themes/default.cpp @@ -176,7 +176,9 @@ class DefaultTheme: public Theme calibTrackpBackground = BitmapBuffer::load(getThemePath("trackp_background.png")); delete calibHorus; -#if defined(PCBX10) +#if defined(RADIO_T16) + calibHorus = BitmapBuffer::load(getThemePath("t16.bmp")); +#elif defined(PCBX10) if(STICKS_PWM_ENABLED()) { calibHorus = BitmapBuffer::load(getThemePath("X10S.bmp")); } diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp index 797717314..763fdcada 100644 --- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp +++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "io/frsky_firmware_update.h" +#include "io/multi_firmware_update.h" #define NODE_TYPE(fname) fname[SD_SCREEN_FILE_LENGTH+1] #define IS_DIRECTORY(fname) ((bool)(!NODE_TYPE(fname))) @@ -219,6 +220,16 @@ void onSdManagerMenu(const char * result) FrskyDeviceFirmwareUpdate device(SPORT_MODULE); device.flashFirmware(lfn); } +#if defined(INTERNAL_MODULE_MULTI) + else if (result == STR_FLASH_INTERNAL_MULTI) { + getSelectionFullPath(lfn); + multiFlashFirmware(INTERNAL_MODULE, lfn); + } +#endif + else if (result == STR_FLASH_EXTERNAL_MULTI) { + getSelectionFullPath(lfn); + multiFlashFirmware(EXTERNAL_MODULE, lfn); + } #if defined(BLUETOOTH) else if (result == STR_FLASH_BLUETOOTH_MODULE) { getSelectionFullPath(lfn); @@ -340,6 +351,9 @@ void menuRadioSdManager(event_t _event) break; } #endif + TCHAR lfn[_MAX_LFN + 1]; + getSelectionFullPath(lfn); + if (SD_CARD_PRESENT() && s_editMode <= 0) { killEvents(_event); int index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset; @@ -364,10 +378,19 @@ void menuRadioSdManager(event_t _event) POPUP_MENU_ADD_ITEM(STR_EXECUTE_FILE); } #endif +#if defined(MULTIMODULE) && !defined(DISABLE_MULTI_UPDATE) + if (!READ_ONLY() && !strcasecmp(ext, MULTI_FIRMWARE_EXT)) { + MultiFirmwareInformation information; + if (information.readMultiFirmwareInformation(line) == nullptr) { +#if defined(INTERNAL_MODULE_MULTI) + POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MULTI); +#endif + POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MULTI); + } + } +#endif #if defined(PCBTARANIS) - else if (!READ_ONLY() && !strcasecmp(ext, FIRMWARE_EXT)) { - TCHAR lfn[_MAX_LFN + 1]; - getSelectionFullPath(lfn); + if (!READ_ONLY() && !strcasecmp(ext, FIRMWARE_EXT)) { if (isBootloader(lfn)) { POPUP_MENU_ADD_ITEM(STR_FLASH_BOOTLOADER); } @@ -378,9 +401,9 @@ void menuRadioSdManager(event_t _event) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE); } - else if (!READ_ONLY() && !strcasecmp(ext, UPDATE_FIRMWARE_EXT)) { + else if (!READ_ONLY() && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) { FrSkyFirmwareInformation information; - if (readFirmwareInformation(line, information) == nullptr) { + if (readFrSkyFirmwareInformation(line, information) == nullptr) { if (information.productFamily == FIRMWARE_FAMILY_INTERNAL_MODULE) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); if (information.productFamily == FIRMWARE_FAMILY_EXTERNAL_MODULE) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 52dc9fd18..3d0c6c1f7 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -567,6 +567,13 @@ bool isInternalModuleAvailable(int moduleType) if (moduleType == MODULE_TYPE_NONE) return true; +#if defined(INTERNAL_MODULE_MULTI) + if (moduleType == MODULE_TYPE_MULTIMODULE) + return true; + else + return false; +#endif + if (moduleType == MODULE_TYPE_XJT_PXX1) { #if defined(PXX1) && defined(INTERNAL_MODULE_PXX1) return !isModuleUsingSport(EXTERNAL_MODULE, g_model.moduleData[EXTERNAL_MODULE].type); @@ -584,7 +591,6 @@ bool isInternalModuleAvailable(int moduleType) return true; #endif } - return false; } #endif diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index b941d2ec9..9f4d12894 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -116,10 +116,33 @@ void drawFatalErrorScreen(const char * message); void runFatalErrorScreen(const char * message); #endif +#define IF_INTERNAL_MODULE_ON(x) (IS_INTERNAL_MODULE_ENABLED() ? (uint8_t)(x) : HIDDEN_ROW) +#define IF_MODULE_ON(moduleIndex, x) (IS_MODULE_ENABLED(moduleIndex) ? (uint8_t)(x) : HIDDEN_ROW) + // model_setup Defines that are used in all uis in the same way -#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON((uint8_t)1) -#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON((isModuleDSM2(EXTERNAL_MODULE) || isModuleCrossfire(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE) || (isModuleMultimodule(EXTERNAL_MODULE) && g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) != MODULE_SUBTYPE_MULTI_DSM2)) ? (uint8_t)0 : (uint8_t)1) -#define EXTERNAL_MODULE_BIND_ROWS (isModuleXJTD8(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE)) ? (uint8_t)1 : (isModulePPM(EXTERNAL_MODULE) || isModulePXX1(EXTERNAL_MODULE) || isModulePXX2(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW + +inline uint8_t MODULE_BIND_ROWS(int moduleIdx) +{ + if (isModuleXJTD8(moduleIdx) || isModuleSBUS(moduleIdx)) + return 1; + + if (isModulePPM(moduleIdx) || isModulePXX1(moduleIdx) || isModulePXX2(moduleIdx) || isModuleDSM2(moduleIdx) || isModuleMultimodule(moduleIdx)) + return 2; + else + return HIDDEN_ROW; +} + +inline uint8_t MODULE_CHANNELS_ROWS(int moduleIdx) +{ + if (!IS_MODULE_ENABLED(moduleIdx)) + return HIDDEN_ROW; + + if (isModuleDSM2(moduleIdx) || isModuleCrossfire(moduleIdx) || isModuleSBUS(moduleIdx) || (isModuleMultimodule(moduleIdx) && g_model.moduleData[moduleIdx].getMultiProtocol(true) != MODULE_SUBTYPE_MULTI_DSM2)) + return 0; + else + return 1; +} + #if defined(MULTIMODULE) // When using packed, the pointer in here end up not being aligned, which clang and gcc complain about @@ -132,9 +155,9 @@ struct mm_protocol_definition { const char *optionsstr; }; const mm_protocol_definition *getMultiProtocolDefinition (uint8_t protocol); -#define MULTIMODULE_STATUS_ROWS isModuleMultimodule(EXTERNAL_MODULE) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(EXTERNAL_MODULE) && multiSyncStatus.isValid()) ? TITLE_ROW : HIDDEN_ROW, -#define MULTIMODULE_MODULE_ROWS isModuleMultimodule(EXTERNAL_MODULE) ? (uint8_t) 0 : HIDDEN_ROW, -#define MULTIMODULE_MODE_ROWS(x) (g_model.moduleData[x].multi.customProto) ? (uint8_t) 3 :MULTIMODULE_HAS_SUBTYPE(g_model.moduleData[x].getMultiProtocol(true)) ? (uint8_t)2 : (uint8_t)1 +#define MULTIMODULE_STATUS_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(moduleIdx) && getMultiSyncStatus(moduleIdx).isValid()) ? TITLE_ROW : HIDDEN_ROW, +#define MULTIMODULE_MODULE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, +#define MULTIMODULE_MODE_ROWS(moduleIdx) (g_model.moduleData[moduleIdx].multi.customProto) ? (uint8_t) 3 :MULTIMODULE_HAS_SUBTYPE(g_model.moduleData[moduleIdx].getMultiProtocol(true)) ? (uint8_t)2 : (uint8_t)1 inline bool MULTIMODULE_HAS_SUBTYPE(uint8_t moduleIdx) { return getMultiProtocolDefinition(moduleIdx)->maxSubtype > 0; @@ -147,21 +170,21 @@ inline uint8_t MULTIMODULE_RFPROTO_COLUMNS(uint8_t moduleIdx) return (g_model.moduleData[moduleIdx].multi.customProto ? (uint8_t) 2 : MULTIMODULE_HAS_SUBTYPE(g_model.moduleData[moduleIdx].getMultiProtocol(true)) ? (uint8_t) 1 : 0); #endif } -#define MULTIMODULE_SUBTYPE_ROWS(x) isModuleMultimodule(x) ? MULTIMODULE_RFPROTO_COLUMNS(x) : HIDDEN_ROW, -#define MULTIMODULE_HASOPTIONS(x) (getMultiProtocolDefinition(x)->optionsstr != nullptr) -#define MULTIMODULE_OPTIONS_ROW (isModuleMultimodule(EXTERNAL_MODULE) && MULTIMODULE_HASOPTIONS(g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true))) ? (uint8_t) 0: HIDDEN_ROW +#define MULTIMODULE_SUBTYPE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? MULTIMODULE_RFPROTO_COLUMNS(moduleIdx) : HIDDEN_ROW, +#define MULTIMODULE_HASOPTIONS(moduleIdx) (getMultiProtocolDefinition(moduleIdx)->optionsstr != nullptr) +#define MULTIMODULE_OPTIONS_ROW(moduleIdx) (isModuleMultimodule(moduleIdx) && MULTIMODULE_HASOPTIONS(g_model.moduleData[moduleIdx].getMultiProtocol(true))) ? (uint8_t) 0: HIDDEN_ROW #else -#define MULTIMODULE_STATUS_ROWS -#define MULTIMODULE_MODULE_ROWS -#define MULTIMODULE_SUBTYPE_ROWS(x) -#define MULTIMODULE_MODE_ROWS(x) (uint8_t)0 -#define MULTIMODULE_OPTIONS_ROW HIDDEN_ROW +#define MULTIMODULE_STATUS_ROWS(moduleIdx) +#define MULTIMODULE_MODULE_ROWS(moduleIdx) +#define MULTIMODULE_SUBTYPE_ROWS(moduleIdx) +#define MULTIMODULE_MODE_ROWS(moduleIdx) (uint8_t)0 +#define MULTIMODULE_OPTIONS_ROW(moduleIdx) HIDDEN_ROW #endif -#define FAILSAFE_ROWS(x) isModuleFailsafeAvailable(x) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW -#define EXTERNAL_MODULE_OPTION_ROW (isModuleR9MNonAccess(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW) -#define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9MNonAccess(EXTERNAL_MODULE)) ? (isModuleR9MLiteNonPro(EXTERNAL_MODULE) ? (isModuleR9M_FCC_VARIANT(EXTERNAL_MODULE) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW +#define FAILSAFE_ROWS(moduleIdx) isModuleFailsafeAvailable(moduleIdx) ? (g_model.moduleData[moduleIdx].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW +#define MODULE_OPTION_ROW(moduleIdx) (isModuleR9MNonAccess(moduleIdx) || isModuleSBUS(moduleIdx) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW(moduleIdx)) +#define MODULE_POWER_ROW(moduleIdx) (isModuleMultimodule(moduleIdx) || isModuleR9MNonAccess(moduleIdx)) ? (isModuleR9MLiteNonPro(moduleIdx) ? (isModuleR9M_FCC_VARIANT(moduleIdx) ? READONLY_ROW : (uint8_t)0) : (uint8_t)0) : HIDDEN_ROW void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags); diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 889139990..d8a8933e9 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -33,7 +33,7 @@ #define PRIM_END_DOWNLOAD 0x83 #define PRIM_DATA_CRC_ERR 0x84 -const char * readFirmwareInformation(const char * filename, FrSkyFirmwareInformation & data) +const char * readFrSkyFirmwareInformation(const char * filename, FrSkyFirmwareInformation & data) { FIL file; UINT count; @@ -305,7 +305,7 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename) } const char * ext = getFileExtension(filename); - if (ext && !strcasecmp(ext, UPDATE_FIRMWARE_EXT)) { + if (ext && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) { if (f_read(&file, &information, sizeof(FrSkyFirmwareInformation), &count) != FR_OK || count != sizeof(FrSkyFirmwareInformation)) { f_close(&file); return "Format error"; @@ -321,7 +321,7 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename) if (module == INTERNAL_MODULE && information.productId == FIRMWARE_ID_XJT) { INTERNAL_MODULE_ON(); RTOS_WAIT_MS(1); - intmoduleSerialStart(38400, true); + intmoduleSerialStart(38400, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); GPIO_SetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN); result = uploadFileToHorusXJT(filename, &file); GPIO_ResetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN); @@ -336,7 +336,7 @@ const char * FrskyDeviceFirmwareUpdate::doFlashFirmware(const char * filename) // this ifdef can be removed if we use .frsk instead of .frk // theorically it should be possible to use an ISRM module in an XLite case INTERNAL_MODULE: - intmoduleSerialStart(57600, true); + intmoduleSerialStart(57600, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); break; #endif diff --git a/radio/src/io/frsky_firmware_update.h b/radio/src/io/frsky_firmware_update.h index 9d3dcc820..a229edb27 100644 --- a/radio/src/io/frsky_firmware_update.h +++ b/radio/src/io/frsky_firmware_update.h @@ -53,7 +53,7 @@ PACK(struct FrSkyFirmwareInformation { uint16_t crc; }); -const char * readFirmwareInformation(const char * filename, FrSkyFirmwareInformation & data); +const char * readFrSkyFirmwareInformation(const char * filename, FrSkyFirmwareInformation & data); class FrskyDeviceFirmwareUpdate { enum State { diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp new file mode 100644 index 000000000..dcc6d6e7b --- /dev/null +++ b/radio/src/io/multi_firmware_update.cpp @@ -0,0 +1,447 @@ +/* + * 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. + */ + +#if !defined(DISABLE_MULTI_UPDATE) +#include "opentx.h" +#include "multi_firmware_update.h" +#include "stk500.h" +#include "debug.h" + +#define UPDATE_MULTI_EXT_BIN ".bin" + +//#define DEBUG_EXT_MODULE_FLASH + +class MultiFirmwareUpdateDriver +{ + public: + MultiFirmwareUpdateDriver() = default; + const char* flashFirmware(FIL* file, const char* label) const; + + protected: + virtual void init() const = 0; + virtual bool getByte(uint8_t& byte) const = 0; + virtual void sendByte(uint8_t byte) const = 0; + virtual void clear() const = 0; + + private: + bool getRxByte(uint8_t& byte) const; + bool checkRxByte(uint8_t byte) const; + const char * waitForInitialSync() const; + const char * getDeviceSignature(uint8_t* signature) const; + const char * loadAddress(uint32_t offset) const; + const char * progPage(uint8_t* buffer, uint16_t size) const; +}; + +#if defined(INTERNAL_MODULE_MULTI) + +class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver +{ + public: + MultiInternalUpdateDriver() = default; + + protected: + void init() const override + { + INTERNAL_MODULE_ON(); + intmoduleSerialStart(57600, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); + } + + bool getByte(uint8_t& byte) const override + { + return intmoduleFifo.pop(byte); + } + + void sendByte(uint8_t byte) const override + { + intmoduleSendByte(byte); + } + + void clear() const override + { + intmoduleFifo.clear(); + } +}; + +static const MultiInternalUpdateDriver multiInternalUpdateDriver; + +#endif + +class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver +{ + public: + MultiExternalUpdateDriver() = default; + + protected: + void init() const override + { +#if !defined(EXTMODULE_USART) + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_Init(EXTMODULE_TX_GPIO, &GPIO_InitStructure); +#endif + + EXTERNAL_MODULE_ON(); + telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT); + } + + bool getByte(uint8_t& byte) const override + { + return telemetryGetByte(&byte); + } + + void sendByte(uint8_t byte) const override + { + extmoduleSendInvertedByte(byte); + } + + void clear() const override + { + telemetryClearFifo(); + } +}; + +static const MultiExternalUpdateDriver multiExternalUpdateDriver; + +bool MultiFirmwareUpdateDriver::getRxByte(uint8_t& byte) const +{ + uint16_t time; + + time = getTmr2MHz() ; + while ( (uint16_t) (getTmr2MHz() - time) < 25000 ) { // 12.5mS + + if (getByte(byte)) { +#if defined(DEBUG_EXT_MODULE_FLASH) + TRACE("[RX] 0x%X", byte); +#endif + return true; + } + } + + byte = 0; + return false; +} + +bool MultiFirmwareUpdateDriver::checkRxByte(uint8_t byte) const +{ + uint8_t rxchar; + return getRxByte(rxchar) ? rxchar == byte : false; +} + +const char * MultiFirmwareUpdateDriver::waitForInitialSync() const +{ + clear(); + + uint8_t byte; + int retries = 1000; + do { + // Send sync request + sendByte(STK_GET_SYNC); + sendByte(CRC_EOP); + + getRxByte(byte); + wdt_reset(); + + } while((byte != STK_INSYNC) && --retries); + + if (!retries) { + return "NoSync"; + } + + if (byte != STK_INSYNC) { + return "NoSync"; + } + + if (!checkRxByte(STK_OK)) { + return "NoSync"; + } + + return nullptr; +} + +const char * MultiFirmwareUpdateDriver::getDeviceSignature(uint8_t* signature) const +{ + // Read signature + sendByte(STK_READ_SIGN); + sendByte(CRC_EOP); + + if (!checkRxByte(STK_INSYNC)) + return "NoSync"; + + for (uint8_t i=0; i<4; i++) { + if (!getRxByte(signature[i])) { + return "NoSignature"; + } + } + + return nullptr; +} + +const char * MultiFirmwareUpdateDriver::loadAddress(uint32_t offset) const +{ + sendByte(STK_LOAD_ADDRESS); + sendByte(offset & 0xFF); // low byte + sendByte(offset >> 8); // high byte + sendByte(CRC_EOP); + + if (!checkRxByte(STK_INSYNC) || !checkRxByte(STK_OK)) { + return "NoSync"; + } + + return nullptr; +} + +const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size) const +{ + sendByte(STK_PROG_PAGE); + // page size 256 + sendByte(1); + sendByte(0); + // flash/eeprom flag + sendByte(0); + + // #if defined(DEBUG_EXT_MODULE_FLASH) + // TRACE("writing at 0x%X", writeOffset << 1); + // #endif + + for (uint16_t i=0; i < size; i++) { + sendByte(buffer[i]); + } + sendByte(CRC_EOP); + + if (!checkRxByte(STK_INSYNC)) + return "NoSync"; + + uint8_t byte; + uint8_t retries = 4; + do { + getRxByte(byte); + wdt_reset(); + } while(!byte && --retries); + + if (!retries || (byte != STK_OK)) + return "NoPageSync"; + + return nullptr; +} + +const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* label) const +{ + const char* result = nullptr; + init(); + + /* wait 500ms for power on */ + watchdogSuspend(500); + RTOS_WAIT_MS(500); + + result = waitForInitialSync(); + if (result != nullptr) + return result; + + unsigned char signature[4]; // 3 bytes signature + STK_OK + result = getDeviceSignature(signature); + if (result != nullptr) + return result; + + uint8_t buffer[256]; // page size = 256 + uint32_t writeOffset = 0x1000; // start offset (word address) + + while (!f_eof(file)) { + + drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize); + + UINT count=0; + memclear(buffer, 256); + if (f_read(file, buffer, 256, &count) != FR_OK) { + result = "Error reading file"; + break; + } + + if (!count) + break; + + clear(); + + result = loadAddress(writeOffset); + if (result != nullptr) { + break; + } + + result = progPage(buffer, 256); + if (result != nullptr) { + break; + } + + writeOffset += 128; // page / 2 + } + + if (f_eof(file)) { + drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize); + } + + sendByte(STK_LEAVE_PROGMODE); + sendByte(CRC_EOP); + + // eat last sync byte + checkRxByte(STK_INSYNC); + + return result; +} + +// example : multi-stm-bcsid-01020176 +#define MULTI_SIGN_SIZE 24 +#define MULTI_SIGN_BOOTLOADER_SUPPORT_OFFSET 10 +#define MULTI_SIGN_BOOTLOADER_CHECK_OFFSET 11 +#define MULTI_SIGN_TELEM_TYPE_OFFSET 12 +#define MULTI_SIGN_TELEM_INVERSION_OFFSET 13 +#define MULTI_SIGN_VERSION_OFFSET 15 + +const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename) +{ + FIL file; + f_open(&file, filename, FA_READ); + char buffer[MULTI_SIGN_SIZE]; + UINT count; + + f_lseek(&file, f_size(&file) - MULTI_SIGN_SIZE); + if (f_read(&file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) { + return "Error reading file"; + } + + if(!memcmp(buffer, "multi-stm", 9)) + boardType = FIRMWARE_MULTI_STM; + else if (!memcmp(buffer, "multi-avr", 9)) + boardType = FIRMWARE_MULTI_AVR; + else if (!memcmp(buffer, "multi-orx", 9)) + boardType = FIRMWARE_MULTI_ORX; + else + return "Wrong format"; + + if(buffer[MULTI_SIGN_BOOTLOADER_SUPPORT_OFFSET] == 'b') + optibootSupport = true; + else + optibootSupport = false; + + if(buffer[MULTI_SIGN_BOOTLOADER_CHECK_OFFSET] == 'c') + bootloaderCheck = true; + else + bootloaderCheck = false; + + if(buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 't') + telemetryType = FIRMWARE_MULTI_TELEM_MULTI; + else if (buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 's') + telemetryType = FIRMWARE_MULTI_TELEM_STATUS; + else + telemetryType = FIRMWARE_MULTI_TELEM_NONE; + + if(buffer[MULTI_SIGN_TELEM_INVERSION_OFFSET] == 'i') + telemetryInversion = true; + else + telemetryInversion = false; + + return nullptr; +} + + + + +const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename) +{ + FIL file; + const char * result = nullptr; + + const char * ext = getFileExtension(filename); + if (ext && strcasecmp(ext, UPDATE_MULTI_EXT_BIN)) { + return "Wrong file extension"; + } + + if (f_open(&file, filename, FA_READ) != FR_OK) { + return "Error opening file"; + } + + pausePulses(); + +#if defined(INTERNAL_MODULE_MULTI) + uint8_t intPwr = IS_INTERNAL_MODULE_ON(); + INTERNAL_MODULE_OFF(); +#endif + + uint8_t extPwr = IS_EXTERNAL_MODULE_ON(); + EXTERNAL_MODULE_OFF(); + + SPORT_UPDATE_POWER_OFF(); + + drawProgressScreen(getBasename(filename), STR_DEVICE_RESET, 0, 0); + + /* wait 2s off */ + watchdogSuspend(2000); + RTOS_WAIT_MS(2000); + + // TODO: real update here + const MultiFirmwareUpdateDriver* driver = &multiExternalUpdateDriver; +#if defined(INTERNAL_MODULE_MULTI) + if (moduleIdx == INTERNAL_MODULE) + driver = &multiInternalUpdateDriver; +#endif + + result = driver->flashFirmware(&file, getBasename(filename)); + f_close(&file); + + AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1 ); + BACKLIGHT_ENABLE(); + + if (result) { + POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR); + SET_WARNING_INFO(result, strlen(result), 0); + } + else { + POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS); + } + + INTERNAL_MODULE_OFF(); + EXTERNAL_MODULE_OFF(); + SPORT_UPDATE_POWER_OFF(); + + /* wait 2s off */ + watchdogSuspend(2000); + RTOS_WAIT_MS(2000); + telemetryClearFifo(); + +#if defined(INTERNAL_MODULE_MULTI) + if (intPwr) { + INTERNAL_MODULE_ON(); + setupPulsesInternalModule(); + } +#endif + + if (extPwr) { + EXTERNAL_MODULE_ON(); + setupPulsesExternalModule(); + } + + //state = SPORT_IDLE; + resumePulses(); + + return result; +} +#endif \ No newline at end of file diff --git a/radio/src/io/multi_firmware_update.h b/radio/src/io/multi_firmware_update.h new file mode 100644 index 000000000..45c6f8e91 --- /dev/null +++ b/radio/src/io/multi_firmware_update.h @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#ifndef OPENTX_MULTI_FIRMWARE_H +#define OPENTX_MULTI_FIRMWARE_H + +/* Signature format is multi-[board type]-[bootloader support][check for bootloader][multi telemetry type][telemetry inversion][debug]-[firmware version] + Where: + [board type] is avr, stm, or orx + [bootloader support] b for optiboot (AVR) / USB (STM) or u (unsupported) + [check for bootloader] is c (CHECK_FOR_BOOTLOADER) or u (undefined) + [telemetry type] is t (MULTI_TELEMETRY), s (MULTI_STATUS), or u (undefined) for neither + [telemetry inversion] is i (INVERT_TELEMETRY) or u (undefined) + [firmware version] is the version padded to two bytes per segment, without seperators e.g. 01020176 + + For example: REM multi-stm-bcsid-01020176 +*/ + +class MultiFirmwareInformation { + public: + enum MultiFirmwareBoardType { + FIRMWARE_MULTI_STM, + FIRMWARE_MULTI_AVR, + FIRMWARE_MULTI_ORX, + }; + + enum MultiFirmwareTelemetryType { + FIRMWARE_MULTI_TELEM_MULTI, + FIRMWARE_MULTI_TELEM_STATUS, + FIRMWARE_MULTI_TELEM_NONE, + }; + + bool isMultiStmFirmware() const + { + return boardType == FIRMWARE_MULTI_STM; + } + + bool isMultiAvrFirmware() const + { + return boardType == FIRMWARE_MULTI_AVR; + } + + bool isMultiOrxFirmware() const + { + return boardType == FIRMWARE_MULTI_ORX; + } + + bool isMultiWithBootloaderFirmware() const + { + return optibootSupport; + } + + bool isMultiInternalFirmware() const + { + return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == false && optibootSupport == true && telemetryType == FIRMWARE_MULTI_TELEM_STATUS); + } + + bool isMultiExternalFirmware() const + { + return (telemetryInversion == false && optibootSupport == true && telemetryType == FIRMWARE_MULTI_TELEM_STATUS); + } + + const char * readMultiFirmwareInformation(const char * filename); + + private: + uint8_t boardType; + uint8_t optibootSupport; + uint8_t bootloaderCheck; + uint8_t telemetryType; + uint8_t telemetryInversion; + uint8_t firmwareVersionMajor; + uint8_t firmwareVersionMinor; + uint8_t firmwareVersionRevision; + uint8_t firmwareVersionSubRevision; +}; + +const char* multiFlashFirmware(uint8_t module, const char * filename); + +#endif //OPENTX_MULTI_FIRMWARE_H diff --git a/radio/src/io/stk500.h b/radio/src/io/stk500.h new file mode 100644 index 000000000..ca0dd91df --- /dev/null +++ b/radio/src/io/stk500.h @@ -0,0 +1,39 @@ +/* STK500 constants list, from AVRDUDE */ +#define STK_OK 0x10 +#define STK_FAILED 0x11 // Not used +#define STK_UNKNOWN 0x12 // Not used +#define STK_NODEVICE 0x13 // Not used +#define STK_INSYNC 0x14 // ' ' +#define STK_NOSYNC 0x15 // Not used +#define ADC_CHANNEL_ERROR 0x16 // Not used +#define ADC_MEASURE_OK 0x17 // Not used +#define PWM_CHANNEL_ERROR 0x18 // Not used +#define PWM_ADJUST_OK 0x19 // Not used +#define CRC_EOP 0x20 // 'SPACE' +#define STK_GET_SYNC 0x30 // '0' +#define STK_GET_SIGN_ON 0x31 // '1' +#define STK_SET_PARAMETER 0x40 // '@' +#define STK_GET_PARAMETER 0x41 // 'A' +#define STK_SET_DEVICE 0x42 // 'B' +#define STK_SET_DEVICE_EXT 0x45 // 'E' +#define STK_ENTER_PROGMODE 0x50 // 'P' +#define STK_LEAVE_PROGMODE 0x51 // 'Q' +#define STK_CHIP_ERASE 0x52 // 'R' +#define STK_CHECK_AUTOINC 0x53 // 'S' +#define STK_LOAD_ADDRESS 0x55 // 'U' +#define STK_UNIVERSAL 0x56 // 'V' +#define STK_PROG_FLASH 0x60 // '`' +#define STK_PROG_DATA 0x61 // 'a' +#define STK_PROG_FUSE 0x62 // 'b' +#define STK_PROG_LOCK 0x63 // 'c' +#define STK_PROG_PAGE 0x64 // 'd' +#define STK_PROG_FUSE_EXT 0x65 // 'e' +#define STK_READ_FLASH 0x70 // 'p' +#define STK_READ_DATA 0x71 // 'q' +#define STK_READ_FUSE 0x72 // 'r' +#define STK_READ_LOCK 0x73 // 's' +#define STK_READ_PAGE 0x74 // 't' +#define STK_READ_SIGN 0x75 // 'u' +#define STK_READ_OSCCAL 0x76 // 'v' +#define STK_READ_FUSE_EXT 0x77 // 'w' +#define STK_READ_OSCCAL_EXT 0x78 // 'x' diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt index 751d4716a..f0ed96e94 100644 --- a/radio/src/lua/CMakeLists.txt +++ b/radio/src/lua/CMakeLists.txt @@ -26,4 +26,5 @@ if(PYTHONINTERP_FOUND) add_lua_export_target(x10 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10) add_lua_export_target(x12s ${LUA_INCLUDES} -DPCBHORUS -DPCBX12S) add_lua_export_target(t12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T12) + add_lua_export_target(t16 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10 -DRADIO_T16) endif() diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index e69ea7060..9dec737d3 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -27,6 +27,8 @@ #if defined(PCBX12S) #include "lua/lua_exports_x12s.inc" // this line must be after lua headers +#elif defined(RADIO_T16) + #include "lua/lua_exports_t16.inc" #elif defined(PCBX10) #include "lua/lua_exports_x10.inc" #elif defined(PCBX9E) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 16419655d..8191cccfa 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1512,7 +1512,7 @@ void doMixerCalculations() static uint8_t countRangecheck = 0; for (uint8_t i=0; i= MODULE_MODE_BEEP_FIRST || multiModuleStatus.isBinding()) { + if (moduleState[i].mode >= MODULE_MODE_BEEP_FIRST || getMultiModuleStatus(i).isBinding()) { #else if (moduleState[i].mode >= MODULE_MODE_BEEP_FIRST) { #endif @@ -1862,7 +1862,7 @@ void opentxInit() sportStopSendByteLoop(); if (f_stat(AUTOUPDATE_FILENAME, nullptr) == FR_OK) { FrSkyFirmwareInformation information; - if (readFirmwareInformation(AUTOUPDATE_FILENAME, information) == nullptr) { + if (readFrSkyFirmwareInformation(AUTOUPDATE_FILENAME, information) == nullptr) { #if defined(BLUETOOTH) if (information.productFamily == FIRMWARE_FAMILY_BLUETOOTH_CHIP) { if (bluetooth.flashFirmware(AUTOUPDATE_FILENAME) == nullptr) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index a2c3d86ca..5d2266202 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -544,6 +544,8 @@ bool setTrimValue(uint8_t phase, uint8_t idx, int trim); #if defined(PCBSKY9X) #define ROTARY_ENCODER_GRANULARITY (2 << g_eeGeneral.rotarySteps) +#elif defined(RADIO_T16) + #define ROTARY_ENCODER_GRANULARITY (1) #else #define ROTARY_ENCODER_GRANULARITY (2) #endif diff --git a/radio/src/options.h b/radio/src/options.h index 1038af319..e7ddb0caf 100644 --- a/radio/src/options.h +++ b/radio/src/options.h @@ -56,6 +56,9 @@ static const char * options[] = { #if defined(INTERNAL_MODULE_PPM) "internalppm", #endif +#if defined(INTERNAL_MODULE_MULTI) + "internalmulti", +#endif #if defined(MULTIMODULE) "multimodule", #endif diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 3bc69e3bc..6a2a6a34b 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -34,7 +34,7 @@ #if defined(MULTIMODULE) inline bool isModuleMultimodule(uint8_t idx) { - return idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE; + return g_model.moduleData[idx].type == MODULE_TYPE_MULTIMODULE; } inline bool isModuleMultimoduleDSM2(uint8_t idx) @@ -350,8 +350,10 @@ inline bool isModuleFailsafeAvailable(uint8_t idx) return g_model.moduleData[idx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16; #if defined(MULTIMODULE) - if (isModuleMultimodule(idx)) - return multiModuleStatus.isValid() && multiModuleStatus.supportsFailsafe(); + if (isModuleMultimodule(idx)){ + MultiModuleStatus& status = getMultiModuleStatus(idx); + return status.isValid() && status.supportsFailsafe(); + } #endif if (isModuleR9M(idx)) diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index a84bb04a1..9ceb57886 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -31,27 +31,38 @@ #define MULTI_CHANS 16 #define MULTI_CHAN_BITS 11 -static void sendFrameProtocolHeader(uint8_t port, bool failsafe); +static void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe); -void sendChannels(uint8_t port); +void sendChannels(uint8_t moduleIdx); -static void sendSetupFrame() +static void sendMulti(uint8_t moduleIdx, uint8_t b) +{ +#if defined(INTERNAL_MODULE_MULTI) + if (moduleIdx == INTERNAL_MODULE) { + intmodulePulsesData.multi.sendByte(b); + } + else +#endif + sendByteSbus(b); +} + +static void sendSetupFrame(uint8_t moduleIdx) { // Old multi firmware will mark config messsages as invalid frame and throw them away - sendByteSbus('M'); - sendByteSbus('P'); - sendByteSbus(0x80); // Module Configuration - sendByteSbus(1); // 1 byte data + sendMulti(moduleIdx, 'M'); + sendMulti(moduleIdx, 'P'); + sendMulti(moduleIdx, 0x80); // Module Configuration + sendMulti(moduleIdx, 1); // 1 byte data uint8_t config = 0x01 | 0x02; // inversion + multi_telemetry #if !defined(PPM_PIN_SERIAL) // TODO why PPM_PIN_SERIAL would change MULTI protocol? config |= 0x04; // input synchronsisation #endif - sendByteSbus(config); + sendMulti(moduleIdx, config); } -static void sendFailsafeChannels(uint8_t port) +static void sendFailsafeChannels(uint8_t moduleIdx) { uint32_t bits = 0; uint8_t bitsavailable = 0; @@ -60,61 +71,72 @@ static void sendFailsafeChannels(uint8_t port) int16_t failsafeValue = g_model.failsafeChannels[i]; int pulseValue; - if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) { + if (g_model.moduleData[moduleIdx].failsafeMode == FAILSAFE_HOLD) { pulseValue = 2047; } - else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) { + else if (g_model.moduleData[moduleIdx].failsafeMode == FAILSAFE_NOPULSES) { pulseValue = 0; } else { - failsafeValue += 2 * PPM_CH_CENTER(g_model.moduleData[port].channelsStart + i) - 2 * PPM_CENTER; + failsafeValue += 2 * PPM_CH_CENTER(g_model.moduleData[moduleIdx].channelsStart + i) - 2 * PPM_CENTER; pulseValue = limit(1, (failsafeValue * 800 / 1000) + 1024, 2047); } bits |= pulseValue << bitsavailable; bitsavailable += MULTI_CHAN_BITS; while (bitsavailable >= 8) { - sendByteSbus((uint8_t) (bits & 0xff)); + sendMulti(moduleIdx, (uint8_t) (bits & 0xff)); bits >>= 8; bitsavailable -= 8; } } } -void setupPulsesMultimodule() +void setupPulsesMulti(uint8_t moduleIdx) { - static int counter = 0; + static int counter[2] = {0,0}; //TODO + // Every 1000 cycles (=9s) send a config packet that configures the multimodule (inversion, telemetry type) + counter[moduleIdx]++; + if (counter[moduleIdx] % 1000 == 500) { + sendSetupFrame(moduleIdx); + } + else if (counter[moduleIdx] % 1000 == 0 && g_model.moduleData[moduleIdx].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[moduleIdx].failsafeMode != FAILSAFE_RECEIVER) { + sendFrameProtocolHeader(moduleIdx, true); + sendFailsafeChannels(moduleIdx); + } + else { + // Normal Frame + sendFrameProtocolHeader(moduleIdx, false); + sendChannels(moduleIdx); + } +} + +void setupPulsesMultiExternalModule() +{ #if defined(PPM_PIN_SERIAL) extmodulePulsesData.dsm2.serialByte = 0 ; extmodulePulsesData.dsm2.serialBitCount = 0 ; #else - extmodulePulsesData.dsm2.rest = multiSyncStatus.getAdjustedRefreshRate(); + extmodulePulsesData.dsm2.rest = getMultiSyncStatus(EXTERNAL_MODULE).getAdjustedRefreshRate(); extmodulePulsesData.dsm2.index = 0; #endif extmodulePulsesData.dsm2.ptr = extmodulePulsesData.dsm2.pulses; - // Every 1000 cycles (=9s) send a config packet that configures the multimodule (inversion, telemetry type) - counter++; - if (counter % 1000 == 500) { - sendSetupFrame(); - } - else if (counter % 1000 == 0 && g_model.moduleData[EXTERNAL_MODULE].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[EXTERNAL_MODULE].failsafeMode != FAILSAFE_RECEIVER) { - sendFrameProtocolHeader(EXTERNAL_MODULE, true); - sendFailsafeChannels(EXTERNAL_MODULE); - } - else { - // Normal Frame - sendFrameProtocolHeader(EXTERNAL_MODULE, false); - sendChannels(EXTERNAL_MODULE); - } - + setupPulsesMulti(EXTERNAL_MODULE); putDsm2Flush(); } +#if defined(INTERNAL_MODULE_MULTI) +void setupPulsesMultiInternalModule() +{ + intmodulePulsesData.multi.initFrame(); + setupPulsesMulti(INTERNAL_MODULE); +} +#endif -void sendChannels(uint8_t port) +void sendChannels(uint8_t moduleIdx) { uint32_t bits = 0; uint8_t bitsavailable = 0; @@ -123,7 +145,7 @@ void sendChannels(uint8_t port) // Range for pulses (channelsOutputs) is [-1024:+1024] for [-100%;100%] // Multi uses [204;1843] as [-100%;100%] for (int i = 0; i < MULTI_CHANS; i++) { - int channel = g_model.moduleData[port].channelsStart + i; + int channel = g_model.moduleData[moduleIdx].channelsStart + i; int value = channelOutputs[channel] + 2 * PPM_CH_CENTER(channel) - 2 * PPM_CENTER; // Scale to 80% @@ -133,36 +155,36 @@ void sendChannels(uint8_t port) bits |= value << bitsavailable; bitsavailable += MULTI_CHAN_BITS; while (bitsavailable >= 8) { - sendByteSbus((uint8_t) (bits & 0xff)); + sendMulti(moduleIdx, (uint8_t) (bits & 0xff)); bits >>= 8; bitsavailable -= 8; } } } -void sendFrameProtocolHeader(uint8_t port, bool failsafe) +void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe) {// byte 1+2, protocol information // Our enumeration starts at 0 - int type = g_model.moduleData[port].getMultiProtocol(false) + 1; - int subtype = g_model.moduleData[port].subType; - int8_t optionValue = g_model.moduleData[port].multi.optionValue; + int type = g_model.moduleData[moduleIdx].getMultiProtocol(false) + 1; + int subtype = g_model.moduleData[moduleIdx].subType; + int8_t optionValue = g_model.moduleData[moduleIdx].multi.optionValue; uint8_t protoByte = 0; - if (moduleState[port].mode == MODULE_MODE_BIND) + if (moduleState[moduleIdx].mode == MODULE_MODE_BIND) protoByte |= MULTI_SEND_BIND; - else if (moduleState[port].mode == MODULE_MODE_RANGECHECK) + else if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK) protoByte |= MULTI_SEND_RANGECHECK; // rfProtocol - if (g_model.moduleData[port].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2) { + if (g_model.moduleData[moduleIdx].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2) { // Autobinding should always be done in DSMX 11ms - if (g_model.moduleData[port].multi.autoBindMode && moduleState[port].mode == MODULE_MODE_BIND) + if (g_model.moduleData[moduleIdx].multi.autoBindMode && moduleState[moduleIdx].mode == MODULE_MODE_BIND) subtype = MM_RF_DSM2_SUBTYPE_AUTO; // Multi module in DSM mode wants the number of channels to be used as option value - optionValue = sentModuleChannels(EXTERNAL_MODULE); + optionValue = sentModuleChannels(moduleIdx); } @@ -175,7 +197,7 @@ void sendFrameProtocolHeader(uint8_t port, bool failsafe) if (type >= 25) type = type + 1; - if (g_model.moduleData[port].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_FRSKY) { + if (g_model.moduleData[moduleIdx].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_FRSKY) { if (subtype == MM_RF_FRSKY_SUBTYPE_D8) { //D8 type = 3; @@ -199,12 +221,12 @@ void sendFrameProtocolHeader(uint8_t port, bool failsafe) // Set the highest bit of option byte in AFHDS2A protocol to instruct MULTI to passthrough telemetry bytes instead // of sending Frsky D telemetry - if (g_model.moduleData[port].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) + if (g_model.moduleData[moduleIdx].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) optionValue = optionValue | 0x80; // For custom protocol send unmodified type byte - if (g_model.moduleData[port].getMultiProtocol(true) == MM_RF_CUSTOM_SELECTED) - type = g_model.moduleData[port].getMultiProtocol(false); + if (g_model.moduleData[moduleIdx].getMultiProtocol(true) == MM_RF_CUSTOM_SELECTED) + type = g_model.moduleData[moduleIdx].getMultiProtocol(false); uint8_t headerByte = 0x54; @@ -213,24 +235,24 @@ void sendFrameProtocolHeader(uint8_t port, bool failsafe) // header, byte 0, 0x55 for proto 0-31 0x54 for 32-63 if (type <= 31) - sendByteSbus(headerByte+1); + sendMulti(moduleIdx, headerByte+1); else - sendByteSbus(headerByte); + sendMulti(moduleIdx, headerByte); // protocol byte protoByte |= (type & 0x1f); - if (g_model.moduleData[port].getMultiProtocol(true) != MODULE_SUBTYPE_MULTI_DSM2) - protoByte |= (g_model.moduleData[port].multi.autoBindMode << 6); + if (g_model.moduleData[moduleIdx].getMultiProtocol(true) != MODULE_SUBTYPE_MULTI_DSM2) + protoByte |= (g_model.moduleData[moduleIdx].multi.autoBindMode << 6); - sendByteSbus(protoByte); + sendMulti(moduleIdx, protoByte); // byte 2, subtype, powermode, model id - sendByteSbus((uint8_t) ((g_model.header.modelId[port] & 0x0f) + sendMulti(moduleIdx, (uint8_t) ((g_model.header.modelId[moduleIdx] & 0x0f) | ((subtype & 0x7) << 4) - | (g_model.moduleData[port].multi.lowPowerMode << 7)) + | (g_model.moduleData[moduleIdx].multi.lowPowerMode << 7)) ); // byte 3 - sendByteSbus((uint8_t) optionValue); + sendMulti(moduleIdx, (uint8_t) optionValue); } diff --git a/radio/src/pulses/multi.h b/radio/src/pulses/multi.h new file mode 100644 index 000000000..d3f088b7d --- /dev/null +++ b/radio/src/pulses/multi.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef _MULTI_PULSES_H_ +#define _MULTI_PULSES_H_ + +#include "pulses_common.h" + +class UartMultiPulses: public DataBuffer +{ + public: + void initFrame() + { + initBuffer(); + } + + void sendByte(uint8_t b) + { + if (getSize() < 64) + *ptr++ = b; + } +}; + +#endif diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index cec72d8a0..e771d4e90 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -269,7 +269,7 @@ void setupPulsesExternalModule(uint8_t protocol) #if defined(MULTIMODULE) case PROTOCOL_CHANNELS_MULTIMODULE: - setupPulsesMultimodule(); + setupPulsesMultiExternalModule(); scheduleNextMixerCalculation(EXTERNAL_MODULE, MULTIMODULE_PERIOD); break; #endif @@ -306,10 +306,17 @@ void enablePulsesInternalModule(uint8_t protocol) #if defined(PXX2) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: - intmoduleSerialStart(PXX2_HIGHSPEED_BAUDRATE, true); + intmoduleSerialStart(PXX2_HIGHSPEED_BAUDRATE, true, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); break; #endif +#if defined(INTERNAL_MODULE_MULTI) + case PROTOCOL_CHANNELS_MULTIMODULE: + intmodulePulsesData.multi.initFrame(); + intmoduleSerialStart(MULTIMODULE_BAUDRATE, true, USART_Parity_Even, USART_StopBits_2, USART_WordLength_9b); + intmoduleTimerStart(MULTIMODULE_PERIOD); + break; +#endif default: break; } @@ -355,6 +362,13 @@ void setupPulsesInternalModule(uint8_t protocol) break; #endif +#if defined(INTERNAL_MODULE_MULTI) + case PROTOCOL_CHANNELS_MULTIMODULE: + setupPulsesMultiInternalModule(); + scheduleNextMixerCalculation(INTERNAL_MODULE, MULTIMODULE_PERIOD); + break; +#endif + default: break; } diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index e2aa1664a..9fa17a196 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -24,8 +24,9 @@ #include "definitions.h" #include "dataconstants.h" #include "pulses_common.h" -#include "pulses/pxx1.h" -#include "pulses/pxx2.h" +#include "pxx1.h" +#include "pxx2.h" +#include "multi.h" #include "modules_helpers.h" #include "ff.h" @@ -248,6 +249,10 @@ union InternalModulePulsesData { Pxx2Pulses pxx2; #endif +#if defined(INTERNAL_MODULE_MULTI) //&& defined(INTMODULE_USART) + UartMultiPulses multi; +#endif + #if defined(INTERNAL_MODULE_PPM) PpmPulsesData ppm; #endif @@ -294,11 +299,14 @@ union TrainerPulsesData { extern TrainerPulsesData trainerPulsesData; +#if defined(HARDWARE_INTERNAL_MODULE) bool setupPulsesInternalModule(); +#endif bool setupPulsesExternalModule(); void setupPulsesDSM2(); void setupPulsesCrossfire(); -void setupPulsesMultimodule(); +void setupPulsesMultiExternalModule(); +void setupPulsesMultiInternalModule(); void setupPulsesSbus(); void setupPulsesPPMInternalModule(); void setupPulsesPPMExternalModule(); diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index b32eede0c..baa421de7 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -469,7 +469,7 @@ const char * Pxx2OtaUpdate::doFlashFirmware(const char * filename) uint32_t size; const char * ext = getFileExtension(filename); - if (ext && !strcasecmp(ext, UPDATE_FIRMWARE_EXT)) { + if (ext && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) { FrSkyFirmwareInformation * information = (FrSkyFirmwareInformation *) buffer; if (f_read(&file, buffer, sizeof(FrSkyFirmwareInformation), &count) != FR_OK || count != sizeof(FrSkyFirmwareInformation)) { f_close(&file); diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index 0b518eb24..3f7ed8eda 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -70,7 +70,8 @@ const char RADIO_SETTINGS_PATH[] = RADIO_PATH "/radio.bin"; #define FIRMWARE_EXT ".bin" #define EEPROM_EXT ".bin" #define SPORT_FIRMWARE_EXT ".frk" -#define UPDATE_FIRMWARE_EXT ".frsk" +#define FRSKY_FIRMWARE_EXT ".frsk" +#define MULTI_FIRMWARE_EXT ".bin" #define LEN_FILE_EXTENSION_MAX 5 // longest used, including the dot, excluding null term. @@ -125,6 +126,8 @@ const char * getBasename(const char * path); #if defined(PCBX12S) #define OTX_FOURCC 0x3478746F // otx for X12S +#elif defined(RADIO_T16) + #define OTX_FOURCC 0x3F78746F // otx for Jumper T16 #elif defined(PCBX10) #define OTX_FOURCC 0x3778746F // otx for X10 #elif defined(PCBX9E) diff --git a/radio/src/storage/conversions/conversions_218_219.cpp b/radio/src/storage/conversions/conversions_218_219.cpp index f6076917d..bba32aef0 100644 --- a/radio/src/storage/conversions/conversions_218_219.cpp +++ b/radio/src/storage/conversions/conversions_218_219.cpp @@ -124,9 +124,11 @@ void convertModelData_218_to_219(ModelData &model) memclear(&newModel.header.bitmap[10], 4); memcpy(newModel.timers, oldModel.timers, offsetof(ModelData_v218, mixData) - offsetof(ModelData_v218, timers)); +#if defined(BLUETOOTH) // trainer battery compartment removed if (newModel.trainerData.mode >= TRAINER_MODE_MASTER_BLUETOOTH) newModel.trainerData.mode -= 1; +#endif #endif memclear(newModel.mixData, sizeof(ModelData_v219) - offsetof(ModelData_v219, mixData)); diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 9b488138c..04d30f936 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -143,7 +143,7 @@ endif() if(MULTIMODULE) add_definitions(-DMULTIMODULE) - set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/multi.cpp) + set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/multi.cpp io/multi_firmware_update.cpp) endif() if(CROSSFIRE) diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/adc_driver.cpp index 36d0e5a60..49887799e 100644 --- a/radio/src/targets/common/arm/stm32/adc_driver.cpp +++ b/radio/src/targets/common/arm/stm32/adc_driver.cpp @@ -22,8 +22,10 @@ #if defined(SIMU) // not needed +#elif defined(RADIO_T16) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,1, -1,1, -1,1}; #elif defined(PCBX10) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,1, 1, -1}; + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,1, 1, -1}; #elif defined(PCBX9E) #if defined(HORUS_STICKS) const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,-1, -1,-1,-1}; diff --git a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp index fd1e83183..2962731b7 100644 --- a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp +++ b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp @@ -95,8 +95,14 @@ void audioConsumeCurrentBuffer() nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer(); if (nextBuffer) { #if defined(AUDIO_MUTE_GPIO_PIN) - // un-mute - GPIO_ResetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN); + // if muted + if (GPIO_ReadOutputDataBit(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN)) { + // ..un-mute + GPIO_ResetBits(AUDIO_MUTE_GPIO, AUDIO_MUTE_GPIO_PIN); +#if defined(AUDIO_UNMUTE_DELAY) + RTOS_WAIT_MS(AUDIO_UNMUTE_DELAY); +#endif + } #endif AUDIO_DMA_Stream->CR &= ~DMA_SxCR_EN ; // Disable DMA channel AUDIO_DMA->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits diff --git a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp index 1f22abc48..9499e24f9 100644 --- a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp @@ -20,6 +20,7 @@ #include "opentx.h" +#if defined(AUX_SERIAL) uint8_t auxSerialMode = 0; Fifo auxSerialTxFifo; AuxSerialRxFifo auxSerialRxFifo __DMA (AUX_SERIAL_DMA_Stream_RX); @@ -183,4 +184,5 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void) } #endif } -#endif \ No newline at end of file +#endif +#endif // AUX_SERIAL diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp index 8102b5eee..e2f01f586 100755 --- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp @@ -39,14 +39,20 @@ void intmoduleStop() USART_DeInit(INTMODULE_USART); GPIO_ResetBits(INTMODULE_GPIO, INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN); + +#if defined(INTERNAL_MODULE_MULTI) + // stop pulses timer + INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; +#endif } void intmodulePxx1SerialStart() { - intmoduleSerialStart(INTMODULE_PXX1_SERIAL_BAUDRATE, false); + intmoduleSerialStart(INTMODULE_PXX1_SERIAL_BAUDRATE, false, USART_Parity_No, USART_StopBits_1, USART_WordLength_8b); } -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable) +void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength) { INTERNAL_MODULE_ON(); @@ -71,9 +77,9 @@ void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable) USART_DeInit(INTMODULE_USART); USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = baudrate; - USART_InitStructure.USART_Parity = USART_Parity_No; - USART_InitStructure.USART_StopBits = USART_StopBits_1; - USART_InitStructure.USART_WordLength = USART_WordLength_8b; + USART_InitStructure.USART_Parity = parity; + USART_InitStructure.USART_StopBits = stopBits; + USART_InitStructure.USART_WordLength = wordLength; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(INTMODULE_USART, &USART_InitStructure); @@ -87,6 +93,28 @@ void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable) } } +#if defined(INTERNAL_MODULE_MULTI) +void intmoduleTimerStart(uint32_t periodMs) +{ + // Timer + INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) + INTMODULE_TIMER->ARR = periodMs * 2000; + INTMODULE_TIMER->CCR2 = (periodMs - 1) * 2000; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E; + INTMODULE_TIMER->CCMR2 = 0; + INTMODULE_TIMER->EGR = 1; // Restart + + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt + INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + + NVIC_EnableIRQ(INTMODULE_TIMER_IRQn); + NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7); +} +#endif + #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE) extern "C" void INTMODULE_USART_IRQHandler(void) { @@ -98,7 +126,6 @@ extern "C" void INTMODULE_USART_IRQHandler(void) intmoduleFifo.errors++; } else { - hardwareOptions.pxx2Enabled = true; intmoduleFifo.push(data); } status = INTMODULE_USART->SR; @@ -152,5 +179,20 @@ void intmoduleSendNextFrame() intmoduleSendBuffer(intmodulePulsesData.pxx_uart.getData(), intmodulePulsesData.pxx_uart.getSize()); break; #endif + +#if defined(INTERNAL_MODULE_MULTI) + case PROTOCOL_CHANNELS_MULTIMODULE: + intmoduleSendBuffer(intmodulePulsesData.multi.getData(), intmodulePulsesData.multi.getSize()); + break; +#endif } } + +#if defined(INTERNAL_MODULE_MULTI) +extern "C" void INTMODULE_TIMER_IRQHandler() +{ + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag + setupPulsesInternalModule(); + intmoduleSendNextFrame(); +} +#endif diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp index fc028d3b5..e457de7d7 100644 --- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp +++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp @@ -71,6 +71,27 @@ void rotaryEncoderInit() void rotaryEncoderCheck() { +#if defined(RADIO_T16) + static uint8_t state = 0; + uint8_t pins = ROTARY_ENCODER_POSITION(); + + if (pins != (state & 0x03) && !(readKeys() & (1 << KEY_ENTER))) { + if ((pins & 0x01) ^ ((pins & 0x02) >> 1)) { + if ((state & 0x03) == 3) + ++rotencValue; + else + --rotencValue; + } + else + { + if ((state & 0x03) == 3) + --rotencValue; + else if ((state & 0x03) == 0) + ++rotencValue; + } + state &= ~0x03 ; + state |= pins ; +#else uint8_t newPosition = ROTARY_ENCODER_POSITION(); if (newPosition != rotencPosition && !(readKeys() & (1 << KEY_ENTER))) { if ((rotencPosition & 0x01) ^ ((newPosition & 0x02) >> 1)) { @@ -80,6 +101,7 @@ void rotaryEncoderCheck() ++rotencValue; } rotencPosition = newPosition; +#endif #if !defined(BOOT) if (g_eeGeneral.backlightMode & e_backlight_mode_keys) { backlightOn(); @@ -127,4 +149,4 @@ extern "C" void ROTARY_ENCODER_TIMER_IRQHandler(void) ROTARY_ENCODER_TIMER->SR &= ~TIM_SR_UIF; ROTARY_ENCODER_TIMER->CR1 = 0; rotaryEncoderCheck(); -} \ No newline at end of file +} diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 118426265..065e4d6ba 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -44,15 +44,23 @@ if (PCB STREQUAL X10) set(FLAVOUR x10express) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) + set(BLUETOOTH ON) + elseif (PCBREV STREQUAL T16) + set(FLAVOUR t16) + set(LUA_EXPORT lua_export_t16) + add_definitions(-DRADIO_T16) + option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" OFF) else() set(FLAVOUR x10) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) + set(BLUETOOTH ON) endif() elseif (PCB STREQUAL X12S) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) set(FLAVOUR x12s) + set(BLUETOOTH ON) set(PCBREV "13" CACHE STRING "PCB Revision") if(${PCBREV} GREATER 10) option(INTERNAL_GPS "Internal GPS installed" YES) @@ -91,14 +99,21 @@ if(NOT UNEXPECTED_SHUTDOWN) endif() if(INTERNAL_MODULE_PXX1) + add_definitions(-DHARDWARE_INTERNAL_MODULE) add_definitions(-DINTERNAL_MODULE_PXX1) endif() if(INTERNAL_MODULE_PXX2) set(PXX2 ON) + add_definitions(-DHARDWARE_INTERNAL_MODULE) add_definitions(-DINTERNAL_MODULE_PXX2) endif() +if(INTERNAL_MODULE_MULTI) + add_definitions(-DHARDWARE_INTERNAL_MODULE) + add_definitions(-DINTERNAL_MODULE_MULTI) +endif() + include_directories(${RADIO_SRC_DIRECTORY}/fonts/480x272 gui/${GUI_DIR} gui/${GUI_DIR}/layouts) file(GLOB THEMES_SRC RELATIVE ${RADIO_SRC_DIRECTORY}/gui/480x272 ${RADIO_SRC_DIRECTORY}/gui/480x272/themes/*.cpp) @@ -163,10 +178,15 @@ set(TARGET_SRC ../common/arm/stm32/heartbeat_driver.cpp ../common/arm/stm32/timers_driver.cpp ../common/arm/stm32/intmodule_serial_driver.cpp - ../common/arm/stm32/bluetooth_driver.cpp ../common/arm/stm32/rotary_encoder_driver.cpp ) +if(BLUETOOTH) + add_definitions(-DBLUETOOTH) + set(TARGET_SRC ${TARGET_SRC} ../common/arm/stm32/bluetooth_driver.cpp) + set(SRC ${SRC} bluetooth.cpp) +endif() + set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} ${LCD_DRIVER} @@ -179,12 +199,10 @@ set(FIRMWARE_TARGET_SRC ../common/arm/loadboot.cpp ) -add_definitions(-DBLUETOOTH) - set(SRC ${SRC} - bluetooth.cpp io/frsky_firmware_update.cpp + io/multi_firmware_update.cpp ) set(STM32LIB_SRC @@ -202,4 +220,3 @@ if(PYTHONINTERP_FOUND) DEPENDS ${RADIO_DIRECTORY}/src/datastructs.h ${RADIO_DIRECTORY}/util/generate_datacopy.py ) endif() - diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 13717068a..fb12142a0 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -59,7 +59,7 @@ extern uint16_t sessionTimer; #define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE) -#if defined(PCBX10) +#if defined(PCBX10) && !defined(RADIO_T16) #define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_SET) #else #define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET) @@ -173,7 +173,10 @@ void SDRAM_Init(); void init_intmodule_heartbeat(); void check_intmodule_heartbeat(); -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable); +void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength); +#if defined(INTERNAL_MODULE_MULTI) +void intmoduleTimerStart(uint32_t periodMs); +#endif void intmoduleSendByte(uint8_t byte); void intmoduleSendBuffer(const uint8_t * data, uint8_t size); void intmoduleSendNextFrame(); @@ -182,6 +185,7 @@ void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inver void extmoduleInvertedSerialStart(uint32_t baudrate); void extmoduleSendBuffer(const uint8_t * data, uint8_t size); void extmoduleSendNextFrame(); +void extmoduleSendInvertedByte(uint8_t byte); // Trainer driver void init_trainer_ppm(); @@ -507,6 +511,8 @@ void backlightEnable(uint8_t dutyCycle = 0); #define BACKLIGHT_LEVEL_MAX 100 #if defined(PCBX12S) #define BACKLIGHT_LEVEL_MIN 5 +#elif defined(RADIO_T16) +#define BACKLIGHT_LEVEL_MIN 1 #else #define BACKLIGHT_LEVEL_MIN 46 #endif @@ -521,6 +527,10 @@ void usbJoystickUpdate(); #define USB_NAME "FrSky Horus" #define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ #define USB_PRODUCT 'H', 'o', 'r', 'u', 's', ' ', ' ', ' ' /* 8 Bytes */ +#elif defined(RADIO_T16) + #define USB_NAME "Jumper T16" + #define USB_MANUFACTURER 'J', 'u', 'm', 'p', 'e', 'r', ' ', ' ' /* 8 bytes */ + #define USB_PRODUCT 'T', '1', '6', ' ', ' ', ' ', ' ', ' ' /* 8 Bytes */ #elif defined(PCBX10) #define USB_NAME "FrSky X10" #define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */ @@ -554,7 +564,7 @@ void telemetryPortSetDirectionInput(); void telemetryPortSetDirectionOutput(); void sportSendByte(uint8_t byte); void sportSendBuffer(const uint8_t * buffer, uint32_t count); -uint8_t telemetryGetByte(uint8_t * byte); +bool telemetryGetByte(uint8_t * byte); void telemetryClearFifo(); extern uint32_t telemetryErrors; @@ -605,6 +615,7 @@ void bluetoothDisable(); extern DMAFifo<512> telemetryFifo; typedef DMAFifo<32> AuxSerialRxFifo; extern AuxSerialRxFifo auxSerialRxFifo; +extern volatile uint32_t externalModulePort; #endif #endif // _BOARD_H_ diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 5c628edf1..0da9e46a5 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -350,6 +350,38 @@ void extmoduleSendNextFrame() } } +void extmoduleSendInvertedByte(uint8_t byte) +{ + uint16_t time; + uint32_t i; + + __disable_irq(); + time = getTmr2MHz(); + GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + while ((uint16_t) (getTmr2MHz() - time) < 34) { + // wait + } + time += 34; + for (i = 0 ; i < 8 ; i += 1) { + if (byte & 1) { + GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + } + else { + GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + } + byte >>= 1 ; + while ((uint16_t) (getTmr2MHz() - time) < 35) { + // wait + } + time += 35 ; + } + GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + __enable_irq() ; // No need to wait for the stop bit to complete + while ((uint16_t) (getTmr2MHz() - time) < 34) { + // wait + } +} + extern "C" void EXTMODULE_TIMER_DMA_IRQHandler() { if (!DMA_GetITStatus(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC)) diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 5c07cb7b5..18acb1602 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -183,10 +183,17 @@ #define TRIMS_GPIO_PIN_RVU GPIO_Pin_12 // PJ.12 #define TRIMS_GPIO_REG_RHR GPIOD->IDR #define TRIMS_GPIO_PIN_RHR GPIO_Pin_7 // PD.07 - #define TRIMS_GPIO_REG_LSU GPIOJ->IDR - #define TRIMS_GPIO_PIN_LSU GPIO_Pin_8 // PJ.08 - #define TRIMS_GPIO_REG_LSD GPIOD->IDR - #define TRIMS_GPIO_PIN_LSD GPIO_Pin_13 // PD.13 + #if defined(RADIO_T16) + #define TRIMS_GPIO_REG_LSU GPIOD->IDR + #define TRIMS_GPIO_PIN_LSU GPIO_Pin_13 // PD.13 + #define TRIMS_GPIO_REG_LSD GPIOJ->IDR + #define TRIMS_GPIO_PIN_LSD GPIO_Pin_8 // PJ.08 + #else + #define TRIMS_GPIO_REG_LSU GPIOJ->IDR + #define TRIMS_GPIO_PIN_LSU GPIO_Pin_8 // PJ.08 + #define TRIMS_GPIO_REG_LSD GPIOD->IDR + #define TRIMS_GPIO_PIN_LSD GPIO_Pin_13 // PD.13 + #endif #define TRIMS_GPIO_REG_RSU GPIOB->IDR #define TRIMS_GPIO_PIN_RSU GPIO_Pin_14 // PB.14 #define TRIMS_GPIO_REG_RSD GPIOB->IDR @@ -281,8 +288,12 @@ #define ADC_DMA_Stream DMA2_Stream0 #define ADC_SET_DMA_FLAGS() ADC_DMA->LIFCR = (DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0) #define ADC_TRANSFER_COMPLETE() (ADC_DMA->LISR & DMA_LISR_TCIF0) +#if defined(RADIO_T16) + #define ADC_VREF_PREC2 300 +#else #define ADC_VREF_PREC2 250 #endif +#endif // Power #define PWR_RCC_AHB1Periph RCC_AHB1Periph_GPIOJ @@ -525,6 +536,10 @@ #define AUDIO_DMA DMA1 #endif +#if defined(RADIO_T16) + #define AUDIO_UNMUTE_DELAY 150 +#endif + // I2C Bus #define I2C_RCC_AHB1Periph RCC_AHB1Periph_GPIOB #define I2C_RCC_APB1Periph RCC_APB1Periph_I2C1 @@ -563,9 +578,9 @@ #define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR2 #endif -// Internal Module -#define HARDWARE_INTERNAL_MODULE +#if !defined(RADIO_T16) #define EXTERNAL_ANTENNA +#endif #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2) #define INTMODULE_PWR_GPIO GPIOA #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PA.08 diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index 8b782f759..2ca7c6c0a 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -254,7 +254,7 @@ extern "C" void TELEMETRY_USART_IRQHandler(void) } // TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp -uint8_t telemetryGetByte(uint8_t * byte) +bool telemetryGetByte(uint8_t * byte) { #if defined(PCBX12S) if (telemetryFifoMode & TELEMETRY_SERIAL_WITHOUT_DMA) diff --git a/radio/src/targets/sky9x/CMakeLists.txt b/radio/src/targets/sky9x/CMakeLists.txt index 08b120ad8..b2bf06065 100644 --- a/radio/src/targets/sky9x/CMakeLists.txt +++ b/radio/src/targets/sky9x/CMakeLists.txt @@ -10,6 +10,7 @@ set(TARGET_DIR sky9x) set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps) set(PPM_LIMITS_SYMETRICAL YES) set(PXX1 YES) +add_definitions(-DDISABLE_MULTI_UPDATE) if(PCB STREQUAL 9XRPRO) add_definitions(-Dat91sam3s8 -DREVX) diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 65ba8c975..bbd0b8a64 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -1,12 +1,13 @@ option(SHUTDOWN_CONFIRMATION "Shutdown confirmation" OFF) option(LCD_DUAL_BUFFER "Dual LCD Buffer" OFF) -option(INTERNAL_MODULE_PPM "Support for PPM internal module hack" OFF) -option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module replacement" OFF) option(PXX1 "PXX1 protocol support" ON) option(PXX2 "PXX2 protocol support" OFF) +option(INTERNAL_MODULE_PPM "Support for PPM internal module" OFF) option(AUTOUPDATE "Auto update internal chips from SD" OFF) if(PCB STREQUAL X9E) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(STICKS "STANDARD" CACHE STRING "Sticks type (STANDARD/HORUS)") set(CPU_TYPE STM32F4) @@ -49,6 +50,8 @@ elseif(PCB STREQUAL X9D+) set(PCBREV 2014 CACHE STRING "PCB Revision") add_definitions(-DPCBREV=${PCBREV}) if (${PCBREV} STREQUAL 2019) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F4) set(CPU_TYPE_FULL STM32F407xE) # for size report @@ -64,6 +67,8 @@ elseif(PCB STREQUAL X9D+) set(PXX_FREQUENCY "HIGH") set(FLAVOUR x9d+2019) else() + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) set(CPU_TYPE STM32F2) set(CPU_TYPE_FULL STM32F205xE) # for size report set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld) @@ -72,6 +77,8 @@ elseif(PCB STREQUAL X9D+) set(FLAVOUR x9d+) endif() elseif(PCB STREQUAL X9D) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) set(CPU_TYPE STM32F2) set(CPU_TYPE_FULL STM32F205xE) # for size report set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld) @@ -101,6 +108,8 @@ elseif(PCB STREQUAL X7) add_definitions(-DRADIO_T12) add_definitions(-DEEPROM_VARIANT=0x4001) else() + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) set(LUA_EXPORT lua_export_x7) set(FLAVOUR x7) set(NAVIGATION_TYPE x7) @@ -116,6 +125,8 @@ elseif(PCB STREQUAL X7) set(GVAR_SCREEN model_gvars.cpp) set(STATUS_LEDS YES) elseif(PCB STREQUAL X9LITE) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(PXX_FREQUENCY "HIGH") set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F2) @@ -137,6 +148,8 @@ elseif(PCB STREQUAL X9LITE) set(GVAR_SCREEN model_gvars.cpp) set(STATUS_LEDS YES) elseif(PCB STREQUAL X9LITES) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(PXX_FREQUENCY "HIGH") set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F2) @@ -158,6 +171,8 @@ elseif(PCB STREQUAL X9LITES) set(GVAR_SCREEN model_gvars.cpp) set(STATUS_LEDS YES) elseif(PCB STREQUAL XLITE) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" OFF) set(PXX_FREQUENCY "HIGH" CACHE STRING "PXX frequency (LOW / HIGH)") # always use HIGH except on some prototype boards set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F2) @@ -178,6 +193,8 @@ elseif(PCB STREQUAL XLITE) set(GVAR_SCREEN model_gvars.cpp) set(STATUS_LEDS YES) elseif(PCB STREQUAL XLITES) + option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) + option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(PXX_FREQUENCY "HIGH") set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F2) @@ -266,6 +283,7 @@ add_definitions(-DAUDIO -DVOICE -DRTCLOCK) set(SRC ${SRC} io/frsky_firmware_update.cpp + io/multi_firmware_update.cpp ) set(GUI_SRC @@ -322,12 +340,20 @@ if(LCD_DUAL_BUFFER) add_definitions(-DLCD_DUAL_BUFFER) endif() -if(INTERNAL_MODULE_PPM) - add_definitions(-DINTERNAL_MODULE_PPM) -endif() - if(INTERNAL_MODULE_PXX1) + add_definitions(-DHARDWARE_INTERNAL_MODULE) add_definitions(-DINTERNAL_MODULE_PXX1) endif() +if(INTERNAL_MODULE_PXX2) + set(PXX2 ON) + add_definitions(-DHARDWARE_INTERNAL_MODULE) + add_definitions(-DINTERNAL_MODULE_PXX2) +endif() + +if(INTERNAL_MODULE_PPM) + add_definitions(-DHARDWARE_INTERNAL_MODULE) + add_definitions(-DINTERNAL_MODULE_PPM) +endif() + set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} ${BITMAPS_TARGET}) diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index dae1b0f0f..b5c242b00 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -121,7 +121,7 @@ uint32_t isBootloaderStart(const uint8_t * buffer); #define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET) #endif -void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable); +void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable, uint16_t parity, uint16_t stopBits, uint16_t wordLength); void intmoduleSendByte(uint8_t byte); void intmoduleSendBuffer(const uint8_t * data, uint8_t size); void intmoduleSendNextFrame(); @@ -130,6 +130,7 @@ void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us, bool inver void extmoduleInvertedSerialStart(uint32_t baudrate); void extmoduleSendBuffer(const uint8_t * data, uint8_t size); void extmoduleSendNextFrame(); +void extmoduleSendInvertedByte(uint8_t byte); // Trainer driver #define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE) @@ -670,7 +671,7 @@ void sportSendByte(uint8_t byte); void sportSendByteLoop(uint8_t byte); void sportStopSendByteLoop(); void sportSendBuffer(const uint8_t * buffer, uint32_t count); -uint8_t telemetryGetByte(uint8_t * byte); +bool telemetryGetByte(uint8_t * byte); void telemetryClearFifo(); extern uint32_t telemetryErrors; diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index 3ab23f3e9..19bd04525 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -309,6 +309,38 @@ void extmoduleSendNextFrame() } } +void extmoduleSendInvertedByte(uint8_t byte) +{ + uint16_t time; + uint32_t i; + + __disable_irq(); + time = getTmr2MHz(); + GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + while ((uint16_t) (getTmr2MHz() - time) < 34) { + // wait + } + time += 34; + for (i = 0 ; i < 8 ; i += 1) { + if (byte & 1) { + GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + } + else { + GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + } + byte >>= 1 ; + while ((uint16_t) (getTmr2MHz() - time) < 35) { + // wait + } + time += 35 ; + } + GPIO_ResetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); + __enable_irq() ; // No need to wait for the stop bit to complete + while ((uint16_t) (getTmr2MHz() - time) < 34) { + // wait + } +} + extern "C" void EXTMODULE_TIMER_DMA_STREAM_IRQHandler() { if (!DMA_GetITStatus(EXTMODULE_TIMER_DMA_STREAM, EXTMODULE_TIMER_DMA_FLAG_TC)) diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 5b58b1267..89fee14d2 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -929,17 +929,9 @@ #endif // Internal Module -#if !defined(RADIO_T12) - #define HARDWARE_INTERNAL_MODULE -#endif #if defined(PCBXLITE) #define EXTERNAL_ANTENNA #endif -#if defined(PCBXLITES) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019) - #define INTERNAL_MODULE_PXX2 -#else - #define INTERNAL_MODULE_PXX1 -#endif #if defined(PCBXLITE) || defined(PCBX9LITE) #define INTMODULE_RCC_APB1Periph 0 #define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1 diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index ec6da0c86..b439dc906 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -218,7 +218,7 @@ extern "C" void TELEMETRY_USART_IRQHandler(void) } // TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp -uint8_t telemetryGetByte(uint8_t * byte) +bool telemetryGetByte(uint8_t * byte) { #if defined(AUX_SERIAL) if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) { diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index cebb60e78..208df3cac 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -133,35 +133,35 @@ void processFlySkyPacket(const uint8_t *packet) } } -void processFlySkyTelemetryData(uint8_t data) +void processFlySkyTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount) { - if (telemetryRxBufferCount == 0 && data != 0xAA) { + if (rxBufferCount == 0 && data != 0xAA) { TRACE("[IBUS] invalid start byte 0x%02X", data); return; } - if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) { - telemetryRxBuffer[telemetryRxBufferCount++] = data; + if (rxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + rxBuffer[rxBufferCount++] = data; } else { - TRACE("[IBUS] array size %d error", telemetryRxBufferCount); - telemetryRxBufferCount = 0; + TRACE("[IBUS] array size %d error", rxBufferCount); + rxBufferCount = 0; } - if (telemetryRxBufferCount >= FLYSKY_TELEMETRY_LENGTH) { + if (rxBufferCount >= FLYSKY_TELEMETRY_LENGTH) { // debug print the content of the packets #if 0 debugPrintf("[IBUS] Packet 0x%02X rssi 0x%02X: ", - telemetryRxBuffer[0], telemetryRxBuffer[1]); + rxBuffer[0], rxBuffer[1]); for (int i=0; i<7; i++) { - debugPrintf("[%02X %02X %02X%02X] ", telemetryRxBuffer[i*4+2], telemetryRxBuffer[i*4 + 3], - telemetryRxBuffer[i*4 + 4], telemetryRxBuffer[i*4 + 5]); + debugPrintf("[%02X %02X %02X%02X] ", rxBuffer[i*4+2], rxBuffer[i*4 + 3], + rxBuffer[i*4 + 4], rxBuffer[i*4 + 5]); } debugPrintf("\r\n"); #endif - processFlySkyPacket(telemetryRxBuffer+1); - telemetryRxBufferCount = 0; + processFlySkyPacket(rxBuffer+1); + rxBufferCount = 0; } } diff --git a/radio/src/telemetry/flysky_ibus.h b/radio/src/telemetry/flysky_ibus.h index 71726d64c..f952f7968 100644 --- a/radio/src/telemetry/flysky_ibus.h +++ b/radio/src/telemetry/flysky_ibus.h @@ -21,7 +21,7 @@ #ifndef _FLYSKY_IBUS_H #define _FLYSKY_IBUS_H -void processFlySkyTelemetryData(uint8_t data); +void processFlySkyTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount); void flySkySetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance); // Used by multi protocol diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 87944a862..c8e4c7867 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -21,11 +21,6 @@ #include "telemetry.h" #include "multi.h" -MultiModuleStatus multiModuleStatus; -MultiModuleSyncStatus multiSyncStatus; -uint8_t multiBindStatus = MULTI_NORMAL_OPERATION; - - enum MultiPacketTypes : uint8_t { MultiStatus = 1, FrSkySportTelemtry, @@ -51,53 +46,142 @@ enum MultiBufferState : uint8_t { MultiStatusOrFrskyData }; -MultiBufferState guessProtocol() + +#if defined(INTERNAL_MODULE_MULTI) + +static MultiModuleStatus multiModuleStatus[NUM_MODULES] = { MultiModuleStatus(), MultiModuleStatus() }; +static MultiModuleSyncStatus multiSyncStatus[NUM_MODULES] = { MultiModuleSyncStatus(), MultiModuleSyncStatus() }; +static uint8_t multiBindStatus[NUM_MODULES] = { MULTI_NORMAL_OPERATION, MULTI_NORMAL_OPERATION }; + +static MultiBufferState multiTelemetryBufferState[NUM_MODULES]; + +MultiModuleStatus& getMultiModuleStatus(uint8_t module) { - if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_DSM2) + return multiModuleStatus[module]; +} + +MultiModuleSyncStatus& getMultiSyncStatus(uint8_t module) +{ + return multiSyncStatus[module]; +} + +uint8_t getMultiBindStatus(uint8_t module) +{ + return multiBindStatus[module]; +} + +void setMultiBindStatus(uint8_t module, uint8_t bindStatus) +{ + multiBindStatus[module] = bindStatus; +} + +MultiBufferState getMultiTelemetryBufferState(uint8_t module) +{ + return multiTelemetryBufferState[module]; +} + +void setMultiTelemetryBufferState(uint8_t module, MultiBufferState state) +{ + multiTelemetryBufferState[module] = state; +} + +// Use additional telemetry buffer +uint8_t intTelemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; +uint8_t intTelemetryRxBufferCount; + +#else // !INTERNAL_MODULE_MULTI + +static MultiModuleStatus multiModuleStatus; +static MultiModuleSyncStatus multiSyncStatus; +static uint8_t multiBindStatus = MULTI_NORMAL_OPERATION; + +static MultiBufferState multiTelemetryBufferState; + +MultiModuleStatus& getMultiModuleStatus(uint8_t) +{ + return multiModuleStatus; +} + +MultiModuleSyncStatus& getMultiSyncStatus(uint8_t) +{ + return multiSyncStatus; +} + +uint8_t getMultiBindStatus(uint8_t) +{ + return multiBindStatus; +} + +void setMultiBindStatus(uint8_t, uint8_t bindStatus) +{ + multiBindStatus = bindStatus; +} + +MultiBufferState getMultiTelemetryBufferState(uint8_t) +{ + return multiTelemetryBufferState; +} + +void setMultiTelemetryBufferState(uint8_t, MultiBufferState state) +{ + multiTelemetryBufferState = state; +} + +#endif // INTERNAL_MODULE_MULTI + + +static MultiBufferState guessProtocol(uint8_t module) +{ + if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_DSM2) return SpektrumTelemetryFallback; - else if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) + else if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) return FlyskyTelemetryFallback; else return FrskyTelemetryFallback; } -static void processMultiStatusPacket(const uint8_t *data) +static void processMultiStatusPacket(const uint8_t *data, uint8_t module) { + MultiModuleStatus& status = getMultiModuleStatus(module); + // At least two status packets without bind flag - bool wasBinding = (multiModuleStatus.isBinding()); + bool wasBinding = status.isBinding(); - multiModuleStatus.flags = data[0]; - multiModuleStatus.major = data[1]; - multiModuleStatus.minor = data[2]; - multiModuleStatus.revision = data[3]; - multiModuleStatus.patch = data[4]; - multiModuleStatus.lastUpdate = get_tmr10ms(); + status.flags = data[0]; + status.major = data[1]; + status.minor = data[2]; + status.revision = data[3]; + status.patch = data[4]; + status.lastUpdate = get_tmr10ms(); - if (wasBinding && !multiModuleStatus.isBinding() && multiBindStatus == MULTI_BIND_INITIATED) - multiBindStatus = MULTI_BIND_FINISHED; + if (wasBinding && !status.isBinding() && getMultiBindStatus(module) == MULTI_BIND_INITIATED) + setMultiBindStatus(module, MULTI_BIND_FINISHED); } -static void processMultiSyncPacket(const uint8_t *data) +static void processMultiSyncPacket(const uint8_t *data, uint8_t module) { - multiSyncStatus.lastUpdate = get_tmr10ms(); - multiSyncStatus.interval = data[4]; - multiSyncStatus.target = data[5]; + MultiModuleSyncStatus& status = getMultiSyncStatus(module); + + status.lastUpdate = get_tmr10ms(); + status.interval = data[4]; + status.target = data[5]; #if !defined(PPM_PIN_SERIAL) - auto oldlag = multiSyncStatus.inputLag; + auto oldlag = status.inputLag; (void) oldlag; #endif - multiSyncStatus.calcAdjustedRefreshRate(data[0] << 8 | data[1], data[2] << 8 | data[3]); + status.calcAdjustedRefreshRate(data[0] << 8 | data[1], data[2] << 8 | data[3]); #if !defined(PPM_PIN_SERIAL) - TRACE("MP ADJ: rest: %d, lag %04d, diff: %04d target: %d, interval: %d, Refresh: %d, intAdjRefresh: %d, adjRefresh %d\r\n", extmodulePulsesData.dsm2.rest, - multiSyncStatus.inputLag, oldlag-multiSyncStatus.inputLag, multiSyncStatus.target, multiSyncStatus.interval, multiSyncStatus.refreshRate, multiSyncStatus.adjustedRefreshRate/50, - multiSyncStatus.getAdjustedRefreshRate()); + TRACE("MP ADJ: rest: %d, lag %04d, diff: %04d target: %d, interval: %d, Refresh: %d, intAdjRefresh: %d, adjRefresh %d\r\n", + module == EXTERNAL_MODULE ? extmodulePulsesData.dsm2.rest : 0, + status.inputLag, oldlag-status.inputLag, status.target, status.interval, status.refreshRate, status.adjustedRefreshRate/50, + status.getAdjustedRefreshRate()); #endif } -static void processMultiTelemetryPaket(const uint8_t *packet) +static void processMultiTelemetryPaket(const uint8_t *packet, uint8_t module) { uint8_t type = packet[0]; uint8_t len = packet[1]; @@ -107,12 +191,12 @@ static void processMultiTelemetryPaket(const uint8_t *packet) switch (type) { case MultiStatus: if (len >= 5) - processMultiStatusPacket(data); + processMultiStatusPacket(data, module); break; case DSMBindPacket: if (len >= 10) - processDSMBindPacket(data); + processDSMBindPacket(module, data); break; case SpektrumTelemetry: @@ -147,7 +231,7 @@ static void processMultiTelemetryPaket(const uint8_t *packet) case InputSync: if (len >= 6) - processMultiSyncPacket(data); + processMultiSyncPacket(data, module); else TRACE("[MP] Received input sync len %d < 6", len); break; @@ -294,9 +378,11 @@ void MultiModuleStatus::getStatusString(char *statusText) { if (!isValid()) { #if defined(PCBTARANIS) || defined(PCBHORUS) +#if !defined(INTERNAL_MODULE_MULTI) if (IS_INTERNAL_MODULE_ENABLED()) strcpy(statusText, STR_DISABLE_INTERNAL); else +#endif #endif strcpy(statusText, STR_MODULE_NO_TELEMETRY); return; @@ -333,50 +419,71 @@ void MultiModuleStatus::getStatusString(char *statusText) strcat(statusText, STR_MODULE_BINDING); } - -static MultiBufferState multiTelemetryBufferState; - -static void processMultiTelemetryByte(const uint8_t data) +static uint8_t* getRxBuffer(uint8_t moduleIdx) { - if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) { - telemetryRxBuffer[telemetryRxBufferCount++] = data; +#if defined(INTERNAL_MODULE_MULTI) + if (moduleIdx == INTERNAL_MODULE) + return intTelemetryRxBuffer; +#endif + return telemetryRxBuffer; +} + +static uint8_t& getRxBufferCount(uint8_t moduleIdx) +{ +#if defined(INTERNAL_MODULE_MULTI) + if (moduleIdx == INTERNAL_MODULE) + return intTelemetryRxBufferCount; +#endif + return telemetryRxBufferCount; +} + +static void processMultiTelemetryByte(const uint8_t data, uint8_t module) +{ + uint8_t* rxBuffer = getRxBuffer(module); + uint8_t& rxBufferCount = getRxBufferCount(module); + + if (rxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + rxBuffer[rxBufferCount++] = data; } else { - TRACE("[MP] array size %d error", telemetryRxBufferCount); - multiTelemetryBufferState = NoProtocolDetected; + TRACE("[MP] array size %d error", rxBufferCount); + setMultiTelemetryBufferState(module, NoProtocolDetected); } // Length field does not count the header - if (telemetryRxBufferCount >= 2 && telemetryRxBuffer[1] == telemetryRxBufferCount - 2) { + if (rxBufferCount >= 2 && rxBuffer[1] == rxBufferCount - 2) { // debug print the content of the packet #if 0 debugPrintf("[MP] Packet type %02X len 0x%02X: ", - telemetryRxBuffer[0], telemetryRxBuffer[1]); - for (int i=0; i<(telemetryRxBufferCount+3)/4; i++) { - debugPrintf("[%02X%02X %02X%02X] ", telemetryRxBuffer[i*4+2], telemetryRxBuffer[i*4 + 3], - telemetryRxBuffer[i*4 + 4], telemetryRxBuffer[i*4 + 5]); + rxBuffer[0], rxBuffer[1]); + for (int i=0; i<(rxBufferCount+3)/4; i++) { + debugPrintf("[%02X%02X %02X%02X] ", rxBuffer[i*4+2], rxBuffer[i*4 + 3], + rxBuffer[i*4 + 4], rxBuffer[i*4 + 5]); } debugPrintf("\r\n"); #endif // Packet is complete, process it - processMultiTelemetryPaket(telemetryRxBuffer); - multiTelemetryBufferState = NoProtocolDetected; + processMultiTelemetryPaket(rxBuffer, module); + setMultiTelemetryBufferState(module, NoProtocolDetected); } } -void processMultiTelemetryData(const uint8_t data) +void processMultiTelemetryData(uint8_t data, uint8_t module) { - // debugPrintf("State: %d, byte received %02X, buflen: %d\r\n", multiTelemetryBufferState, data, telemetryRxBufferCount); - switch (multiTelemetryBufferState) { + uint8_t* rxBuffer = getRxBuffer(module); + uint8_t& rxBufferCount = getRxBufferCount(module); + + debugPrintf("State: %d, byte received %02X, buflen: %d\r\n", multiTelemetryBufferState, data, rxBufferCount); + switch (getMultiTelemetryBufferState(module)) { case NoProtocolDetected: if (data == 'M') { - multiTelemetryBufferState = MultiFirstByteReceived; + setMultiTelemetryBufferState(module, MultiFirstByteReceived); } else if (data == 0xAA || data == 0x7e) { - multiTelemetryBufferState = guessProtocol(); + setMultiTelemetryBufferState(module, guessProtocol(module)); // Process the first byte by the protocol - processMultiTelemetryData(data); + processMultiTelemetryData(data, module); } else { TRACE("[MP] invalid start byte 0x%02X", data); @@ -384,91 +491,92 @@ void processMultiTelemetryData(const uint8_t data) break; case FrskyTelemetryFallback: - multiTelemetryBufferState = FrskyTelemetryFallbackFirstByte; + setMultiTelemetryBufferState(module, FrskyTelemetryFallbackFirstByte); processFrskyTelemetryData(data); break; case FrskyTelemetryFallbackFirstByte: if (data == 'M') { - multiTelemetryBufferState = MultiStatusOrFrskyData; + setMultiTelemetryBufferState(module, MultiStatusOrFrskyData); } else { processFrskyTelemetryData(data); if (data != 0x7e) - multiTelemetryBufferState = FrskyTelemetryFallbackNextBytes; + setMultiTelemetryBufferState(module, FrskyTelemetryFallbackNextBytes); } break; case FrskyTelemetryFallbackNextBytes: processFrskyTelemetryData(data); - if (data == 0x7e) + if (data == 0x7e) { // end of packet or start of new packet - multiTelemetryBufferState = FrskyTelemetryFallbackFirstByte; + setMultiTelemetryBufferState(module, FrskyTelemetryFallbackFirstByte); + } break; case FlyskyTelemetryFallback: - processFlySkyTelemetryData(data); - if (telemetryRxBufferCount == 0) - multiTelemetryBufferState = NoProtocolDetected; + processFlySkyTelemetryData(data, rxBuffer, rxBufferCount); + if (rxBufferCount == 0) { + setMultiTelemetryBufferState(module, NoProtocolDetected); + } break; case SpektrumTelemetryFallback: - processSpektrumTelemetryData(data); - if (telemetryRxBufferCount == 0) - multiTelemetryBufferState = NoProtocolDetected; + processSpektrumTelemetryData(module, data,rxBuffer, rxBufferCount); + if (rxBufferCount == 0) { + setMultiTelemetryBufferState(module, NoProtocolDetected); + } break; case MultiFirstByteReceived: - telemetryRxBufferCount = 0; + rxBufferCount = 0; if (data == 'P') { - multiTelemetryBufferState = ReceivingMultiProtocol; + setMultiTelemetryBufferState(module, ReceivingMultiProtocol); } else if (data >= 5 && data <= 10) { // Protocol indented for er9x/ersky9, accept only 5-10 as packet length to have // a bit of validation - multiTelemetryBufferState = ReceivingMultiStatus; - processMultiTelemetryData(data); + setMultiTelemetryBufferState(module, ReceivingMultiStatus); + processMultiTelemetryData(data, module); } else { TRACE("[MP] invalid second byte 0x%02X", data); - multiTelemetryBufferState = NoProtocolDetected; + setMultiTelemetryBufferState(module, NoProtocolDetected); } break; case ReceivingMultiProtocol: - processMultiTelemetryByte(data); + processMultiTelemetryByte(data, module); break; case MultiStatusOrFrskyData: // Check len byte if it makes sense for multi if (data >= 5 && data <= 10) { - multiTelemetryBufferState = ReceivingMultiStatus; - telemetryRxBufferCount = 0; + setMultiTelemetryBufferState(module, ReceivingMultiStatus); + rxBufferCount = 0; } else { - multiTelemetryBufferState = FrskyTelemetryFallbackNextBytes; - processMultiTelemetryData('M'); + setMultiTelemetryBufferState(module, FrskyTelemetryFallbackNextBytes); + processMultiTelemetryData('M', module); } - processMultiTelemetryData(data); + processMultiTelemetryData(data, module); break; case ReceivingMultiStatus: - telemetryRxBuffer[telemetryRxBufferCount++] = data; - if (telemetryRxBufferCount > 5 && telemetryRxBuffer[0] == telemetryRxBufferCount-1) { - processMultiStatusPacket(telemetryRxBuffer+1); - telemetryRxBufferCount = 0; - multiTelemetryBufferState = NoProtocolDetected; + rxBuffer[rxBufferCount++] = data; + if (rxBufferCount > 5 && rxBuffer[0] == rxBufferCount-1) { + processMultiStatusPacket(rxBuffer+1, module); + rxBufferCount = 0; + setMultiTelemetryBufferState(module, NoProtocolDetected); } - if (telemetryRxBufferCount > 10) { + if (rxBufferCount > 10) { // too long ignore - TRACE("Overlong multi status packet detected ignoring, wanted %d", telemetryRxBuffer[0]); - telemetryRxBufferCount =0; - multiTelemetryBufferState = NoProtocolDetected; + TRACE("Overlong multi status packet detected ignoring, wanted %d", rxBuffer[0]); + rxBufferCount =0; + setMultiTelemetryBufferState(module, NoProtocolDetected); } - - + break; } - } diff --git a/radio/src/telemetry/multi.h b/radio/src/telemetry/multi.h index 1b439ea24..a538df303 100644 --- a/radio/src/telemetry/multi.h +++ b/radio/src/telemetry/multi.h @@ -82,9 +82,7 @@ Type 0x06 Flysky AFHDS2 telemetry data */ - - -void processMultiTelemetryData(uint8_t data); +void processMultiTelemetryData(uint8_t data, uint8_t module); // This should be put into the Module definition if other modules gain this functionality struct MultiModuleSyncStatus { @@ -107,7 +105,7 @@ struct MultiModuleSyncStatus { }; -extern MultiModuleSyncStatus multiSyncStatus; +MultiModuleSyncStatus& getMultiSyncStatus(uint8_t module); struct MultiModuleStatus { @@ -131,13 +129,15 @@ struct MultiModuleStatus { inline bool inputDetected() { return (bool) (flags & 0x01); } }; -extern MultiModuleStatus multiModuleStatus; +MultiModuleStatus& getMultiModuleStatus(uint8_t module); + enum MultiBindStatus : uint8_t { MULTI_NORMAL_OPERATION, MULTI_BIND_INITIATED, MULTI_BIND_FINISHED, }; -extern uint8_t multiBindStatus; +uint8_t getMultiBindStatus(uint8_t module); +void setMultiBindStatus(uint8_t module, uint8_t bindStatus); #endif //OPENTX_MULTI_H diff --git a/radio/src/telemetry/spektrum.cpp b/radio/src/telemetry/spektrum.cpp index 41b27b88c..ae5435845 100644 --- a/radio/src/telemetry/spektrum.cpp +++ b/radio/src/telemetry/spektrum.cpp @@ -370,28 +370,27 @@ void processSpektrumPacket(const uint8_t *packet) LemonRX+Sat+tele 0xb2 07 1 */ -void processDSMBindPacket(const uint8_t *packet) +void processDSMBindPacket(uint8_t module, const uint8_t *packet) { uint32_t debugval; - if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2 - && g_model.moduleData[EXTERNAL_MODULE].multi.autoBindMode) { + if (g_model.moduleData[module].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[module].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2 + && g_model.moduleData[module].multi.autoBindMode) { int channels = packet[5]; // Only sets channel etc when in DSM multi mode - g_model.moduleData[EXTERNAL_MODULE].channelsCount = channels - 8; + g_model.moduleData[module].channelsCount = channels - 8; // bool use11ms = (packet[8] & 0x10) ; if (packet[6] >= 0xb2) - g_model.moduleData[EXTERNAL_MODULE].subType = MM_RF_DSM2_SUBTYPE_DSMX_11; + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_11; else if (packet[6] >= 0xa2) - g_model.moduleData[EXTERNAL_MODULE].subType = MM_RF_DSM2_SUBTYPE_DSMX_22; + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSMX_22; else if (packet[6] >= 0x12) - g_model.moduleData[EXTERNAL_MODULE].subType = MM_RF_DSM2_SUBTYPE_DSM2_11; + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_11; else - g_model.moduleData[EXTERNAL_MODULE].subType = MM_RF_DSM2_SUBTYPE_DSM2_22; + g_model.moduleData[module].subType = MM_RF_DSM2_SUBTYPE_DSM2_22; storageDirty(EE_MODEL); - } debugval = packet[7] << 24 | packet[6] << 16 | packet[5] << 8 | packet[4]; @@ -400,45 +399,45 @@ void processDSMBindPacket(const uint8_t *packet) setTelemetryValue(PROTOCOL_TELEMETRY_SPEKTRUM, (I2C_PSEUDO_TX << 8) + 4, 0, 0, debugval, UNIT_RAW, 0); /* Finally stop binding as the rx just told us that it is bound */ - if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2 && moduleState[EXTERNAL_MODULE].mode == MODULE_MODE_BIND) { - multiBindStatus=MULTI_BIND_FINISHED; + if (g_model.moduleData[module].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[module].getMultiProtocol(true) == MODULE_SUBTYPE_MULTI_DSM2 && moduleState[module].mode == MODULE_MODE_BIND) { + setMultiBindStatus(module, MULTI_BIND_FINISHED); } } -void processSpektrumTelemetryData(uint8_t data) +void processSpektrumTelemetryData(uint8_t module, uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount) { - if (telemetryRxBufferCount == 0 && data != 0xAA) { + if (rxBufferCount == 0 && data != 0xAA) { TRACE("[SPK] invalid start byte 0x%02X", data); return; } - if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) { - telemetryRxBuffer[telemetryRxBufferCount++] = data; + if (rxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + rxBuffer[rxBufferCount++] = data; } else { - TRACE("[SPK] array size %d error", telemetryRxBufferCount); - telemetryRxBufferCount = 0; + TRACE("[SPK] array size %d error", rxBufferCount); + rxBufferCount = 0; } - if (telemetryRxBuffer[1] == 0x80 && telemetryRxBufferCount >= DSM_BIND_PACKET_LENGTH) { - processDSMBindPacket(telemetryRxBuffer+2); - telemetryRxBufferCount = 0; + if (rxBuffer[1] == 0x80 && rxBufferCount >= DSM_BIND_PACKET_LENGTH) { + processDSMBindPacket(module, rxBuffer+2); + rxBufferCount = 0; return; } - if (telemetryRxBufferCount >= SPEKTRUM_TELEMETRY_LENGTH) { + if (rxBufferCount >= SPEKTRUM_TELEMETRY_LENGTH) { // Debug print content of Telemetry to console #if 0 debugPrintf("[SPK] Packet 0x%02X rssi 0x%02X: ic2 0x%02x, %02x: ", - telemetryRxBuffer[0], telemetryRxBuffer[1], telemetryRxBuffer[2], telemetryRxBuffer[3]); + rxBuffer[0], rxBuffer[1], rxBuffer[2], rxBuffer[3]); for (int i=4; i Date: Tue, 24 Sep 2019 22:37:15 +0200 Subject: [PATCH 032/257] #6821 - Skin of the X9-Lite Companion simulator (#6822) --- .../src/images/simulator/X9LITE/Readme.md | 29 ++++++++++++++++++ .../X9LITE/X9-Lite_Companion_image.png | Bin 0 -> 41808 bytes .../src/images/simulator/X9LITE/bottom.png | Bin 252 -> 4609 bytes .../images/simulator/X9LITE/center_LCD.png | Bin 0 -> 472 bytes .../src/images/simulator/X9LITE/left.png | Bin 17744 -> 12536 bytes .../src/images/simulator/X9LITE/left_exit.png | Bin 16804 -> 12453 bytes .../src/images/simulator/X9LITE/left_menu.png | Bin 17224 -> 12441 bytes .../src/images/simulator/X9LITE/left_page.png | Bin 16873 -> 12439 bytes .../images/simulator/X9LITE/left_scrnshot.png | Bin 17800 -> 12479 bytes .../src/images/simulator/X9LITE/right.png | Bin 19197 -> 10117 bytes .../src/images/simulator/X9LITE/right_ent.png | Bin 18890 -> 11523 bytes .../simulator/X9LITE/right_rotary_encoder.png | Bin 0 -> 9958 bytes companion/src/images/simulator/X9LITE/top.png | Bin 8615 -> 3913 bytes 13 files changed, 29 insertions(+) create mode 100644 companion/src/images/simulator/X9LITE/Readme.md create mode 100644 companion/src/images/simulator/X9LITE/X9-Lite_Companion_image.png create mode 100644 companion/src/images/simulator/X9LITE/center_LCD.png create mode 100644 companion/src/images/simulator/X9LITE/right_rotary_encoder.png diff --git a/companion/src/images/simulator/X9LITE/Readme.md b/companion/src/images/simulator/X9LITE/Readme.md new file mode 100644 index 000000000..46b4f4f4b --- /dev/null +++ b/companion/src/images/simulator/X9LITE/Readme.md @@ -0,0 +1,29 @@ + +# X9-Lite skin for the Companion simulator +![X9-Lite Image for Companion](X9-Lite_Companion_image.png "X9-Lite") + +## The different parts of the image + +The image is divided into 4 pieces: top, bottom, left and right. +For the images concerned, there is the version with the activated element and the version without the activated element (such as a button, a rotary encoder, clicking on the rotary encoder). + +| File name | What is this image ? | +|:---------------------|:----------------------------------------------| +| `bottom.png` | central lower band | +| `center_LCD.png` | central LCD 256x128px (useless for simulator) | +| `left.png` | left part with inactive elements | +| `left_exit.png` | left part with the EXIT button activated | +| `left_menu.png` | left part with the MENU button activated | +| `left_page.png` | left part with the PAGE button activated | +| `left_scrnshot.png `| left part with the SCREENSHOT button activated| +| `right_ent.png` | right part with the ENT button activated | +| `right_rotcoder.png` | right part with the Rotary Encoder actuated | +| `right.png` | right part with inactive elements | +| `top.png` | central upper band | +`X9-Lite_Companion_image.png` is the image displayed here. + +When turning the rotary encoder, it is possible to make a motion effect by displaying `right_rotcoder.png` and `right.png`. + +## Software used : +- **Inkscape** : vector drawing software (http://www.inkscape.org/) +- **Gimp** : image editor (http://www.gimp.org/) \ No newline at end of file diff --git a/companion/src/images/simulator/X9LITE/X9-Lite_Companion_image.png b/companion/src/images/simulator/X9LITE/X9-Lite_Companion_image.png new file mode 100644 index 0000000000000000000000000000000000000000..d206c83e1a99c497e97c04492a0d07b7ce5c97ea GIT binary patch literal 41808 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 Bpb`K8 literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9LITE/bottom.png b/companion/src/images/simulator/X9LITE/bottom.png index 3f709a449487f743fd35b0575b564584a3ca8bd6..43f26ab49b801821691963d8725a9621e87f7a29 100644 GIT binary patch literal 4609 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 delta 237 zcmZov`NKFtyq=4Lje&t7dS1g8AjMMbN&PEETsM6ELF(jk$?e&Aa4GID* z4*Cl&CEj<_1~5`_Vcj`9N1Nc)I$ztaD0e0sv}lRpEZzkxv|GpM$51V@SoVw^s}W84NfWHU|CQbxYJeq1jr9)4pcUpVEe@ v>sS&P8We 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 Hu0mjfNwc7c diff --git a/companion/src/images/simulator/X9LITE/left_exit.png b/companion/src/images/simulator/X9LITE/left_exit.png index 0d7cd5b5b40cd2345b21bb5899dbccc89b0ce7b1..16a7dfda997c5d060503512e11f216adbc23dff5 100644 GIT binary patch literal 12453 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 literal 16804 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 diff --git a/companion/src/images/simulator/X9LITE/left_menu.png b/companion/src/images/simulator/X9LITE/left_menu.png index b97ba1da4e1cf9c131a1ee43c44aaf61cb3cabdc..db1cbd768141ad25dfb5a3542b9cfefb98a799ec 100644 GIT binary patch literal 12441 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 XTn*4bGRA1^00000NkvXXu0mjfo=(-# literal 17224 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

-`${ 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 V>t({inE3zz002ovPDHLkV1mA7)}H_X literal 16873 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 G*#7~ZB1)S)~8~02y>e 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 JPDHLkV1mfT+#CP^ literal 17800 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

9)OFKScV6APdgS3J|_~r%o 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

OAP%Cju~zPUMr~Ya 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 diff --git a/companion/src/images/simulator/X9LITE/right_ent.png b/companion/src/images/simulator/X9LITE/right_ent.png index 3292fb0e54f791f8339e8a2354d108814a704a48..1640129f8b37bae00b98539f63a003f5582418e9 100644 GIT binary patch literal 11523 zcmV+eE&S4nP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{03ZNKL_t(|+U=ctuq4S<-oJA) zv%2qNX70>r?#zz%y*sWUETLi zcU443zpApjD}VLXmnXAM())k;8HaW$wGcs^m8VGDnj_pNLbCTiYJdCyn&W@a3Pg{5 z`>#ohWVwZzaPNbgc=f%9-RJ-8OMLnAR&fQHzS1cFibkzZ{jX^E*;V*>@C6l$DHf1@ zH)P+G+bd1lU%7qJxc@n3dF=If2)8(vUz`&>_l5K5ZATn*^z_iC+sTMxWW@TA{#Syb zzeCFId(;M3+_xRMZ78x<5ngB z+=yk6@-Cs0mzBMz+cyS9fBqNWUCCXj?m?LKO>{Qy#_EYL!`jKmpjVH!AWyus4}pM& zg$0uDsYDqhkhHB|W}9*=P0u0CZX3k}IC8q`9_-FF*qv+Gx%f1$J@Z=t5!Oz;0UM8e z0}kB%<}5tYLR+@N#@CwvRsf+n$83l1b2=`kKXDWT5LXr4;SH5r=l%q@&ix5G8+T#z zE8dT_laIB~j<^U?S$LU*~0N-hA_pAdfeXCvpD;kAHca!{{&pLv$TG9 zoQsta!Gm#fJw9eDBetCEkY%*7-nT6?#RPFKoJr&C+B3g}FaG*>Bf5Eh380l))g@)> zSt^z+bL2>B6fRAG%K)f1v#3IN?JS=EpWln#)w4?@wKCP#yHA3-g+m(Z9GJ(iX9W;w zd#2&Ac>6NWe)5BeZe3V-Ze^4wm=Ma9GQJ~!;g|o|FV#@$~1K?B~3@| zfip6LvvO~FS4_}Mm*>`VcKNAa#m?pDmMXe1=n;qkA}T!mus$lrzbE#}&BETwe&DiP zQ~|iE=U1r?7ys~=aOc;4|NQ=B*Pwf#n_ON9%nZc@R=L+h-{)Q@+p!`r`S&7%l|zEV zn+M>WBo7Dc1kU>R);a&V&3)$t&gNbx@11i1``_pyi}2ByScRJ}er~R+8*N+kZbc*GoTCR`$$$-&A?JABKl<9!pPcI<+P)Ft#)WOfk%NdNk7Nvt2%HGS z`G*@+LhBG)hd6eKB8Mon2qTLyw1^^$IQHLJ+gDoW2FlC!mwcY=+gS%2TM+M78a8Tj zwaa{X+HZ?CN`&bw2YS9^3$CB})STj#{mO_#i)*iJVe4woLzZ5~U3yvfmv(FYBZD<| zh$Dw6@}P#1MHI#eqZnZVaTHs`kwqL^zn%3Udzf9auj2lq$ge9SE{`;krYbR}X~&q& zaD^H_N-IKy_yzvOe{&Ds^vK%Wz_mNquyf_i{4Yx)*t!|w^0}MXx*leb+Soth*h3e^ zDYUi#Y^t zV*JJP+j9dqy#CUjdnFe;+`8Js){PL|HG}S|fl^!yS*5_{?_?zu=7j0wzErK|*u#v^itr(;kS~FNv5(ge6w{I21dQj7d0U#Ohbt}A4R!SE( zBSIT0Rw;%!SOC!9{_nqt-+SuTd=Z(`xP{ssOae#}RY((I5W|PA5+5u8;BvRlq@7@B z=1v95dy<*3HC2zno-9T)gd_w2{o9|rfkj=Y!M3i5w-p4yx?B$}&Gw|Leap*?!E3Vk zvSlg7Ai*tQ!EaBOJvdQjQr6VtW#^y!U=}-5ngF7!3lA@GduEgZGhJ#G zcRzD0%X+u;IIBQl&`Yi2-u5S*On-LXMrXIy3QTl<@fG(rRxP4IUn+}owoMaN5GV37 z0PrvT>i@x;|He19*P(p}0o4XXZXXt_foqhIW^WZ9zULr*;NN`@4jtWWUGBc(R@%d| z%PKG!?uE=Mtacc$`73W}P42$>>9ja4&E~+R81#jL$JHiik4$^g%~ZXoJ@=RhPkhV$ ziyu{Joz7w@HZcGq*MfVS3+FPq2O=um%*QP@`?aFllfLM02_lG=0$h>X_xzH!=d7?8 zr2xXtQh-Y&w->Fg;*N_bfCM*|#45BdXHi9H6t>TO0o%X(3pjGmYZ2Z5PQ>DH=@TEov7?9KPQ4RXE}VzG`VtQHUdHMp zUxRCLfN<+N%ojg}jXNL0E4KtaOIW%56oSn=aQ=7y2X1c1c<`Hl@b-;}(7ZH=@bS|W zE~Qn-FFTj6VCU)2;K1f4&VTHm@KAGkv^*4YF&8HhsU)}-MzPE_Ww4d$ZRotwtLRn>e>3Gf!J(PlIQM7^a}+)OKn zBv+;^k=?)?4$1p8O{hp2U-KotR|@xQ2C zZ=riZxkniUR=eU zbhJ~&&D(tHds}8dZB!5hP};+YP9NML2+-+r25Y9c$u=%#7-Jwt1Bh~wh`}Ga-xYW7 ze+e<;iSK;l)^aHBq~o15z$hO_mA*yrjV_ZYu7BpBgCMYdP_0I%V+!CZW4yH><&~E; zlv1N36Qkm|V`fL8X+mK%TbP@UTnrmvv(Vs91Uqe<4Qcut<2`NA@oK7#w+a*l2m;&p zxFQGwo%6gMs04CYPQdLTP%&8X2sKfoz0Q6dAx866W}_Lf5-$z7G{NPj;1&nW2$WJ_ zt-J*YbONq_Pl1Lp44r)60l^r`6gLP0sK6_*5MYdfV-2GWNUPyWI&GJ4$%w>s-goa@ zh|&te*j^fNC*CBPfa@fGS@IB)O2E}70oOmXF)+r5!-60{OoUFyd)c&6MoJ~%3W6Yj zkbzMKoRk#~{KAn@g|U}@+UM%q9QsBpkl^|fDeeTYB~EUp?JI7l(}6JtN*VNwfl1U; zt5k6ffqY(stM1Bwiu(9$A zoC}FjasmWG3BU?Q8%TOGkU?QcMCIGjsnJ6+G={s6dOwtAki*$Fs*r1(d7pA1ekPROhxkoLk z`3~0U1WHI+aC1(d`h+9+WSVJ(JWv*+k!g~RRD1|x+@QE`dVw>f#ChChSrp= z>zsjBRM@r;u7y$xfzmMS;L$wT6^OlR8)z6ZQ0X{a z*46$F&EUXP8uLJN<(d`KiC3R}Ziy6k()5d7adif#$<%dFahW~P9#Dej6kH9h0F^?S zvkKN)|C!TJWcy_}&dMt7ap$CN)8aP^?@L7Z&^z9-(^`dG;|xHivdRQGP#JL?XCUju z)3WltX3QQ=5e3DPDXvanOv}_-BX$f;8ZNOUO1xE2JJ+5Y&v!?w!qTqSuTe=%-y;3UDX)ocT+63ZXWtuf91D^Ph1VT}Z3~prFWs z6&Dnji2Cq@;m6k`1?R(E$#<#ZrXDvI0<-@$zFdZa00`Rs6Tmq$6N}GU`DryQ}{-O1t;`)Xcv&y~~ z>96n0@k%QxxU9h9^X&Td^yK=ddhk%ge9hZ28?8X#=a&lH$@P#bW8z225PM zC^XJo5{}}6!j4m1W*@@hRB^%JiY+F+CSX&FQgM1V?^mj}uom4Zpi$mTTmVQ&Kl zrHTmx1+Xla;!X~S*&>w01>o`zN@A{xIctD1GXRDnWZx4jaB@QAVfTtFNf}g_!;HuE zoKZa+P`c4p@ebmtkgQRjF-pXmXNP^au$gQo&*SSd;L_+q9@0z^(@T0@aXGi$!1_gh z+gDi1hq#h5#wl*;=xmMq(x^#=oT2U2ipg|$o^Bgwg%#3pSOOpVkY);+gR}5Ce5ZpD zCmk7mxYI-+{q_5vHGQ9!F|OxKYC%$UG0D(rki@wFcxoT0_&F;cauO8R8LZqF!GWzpJ45sVnW>jvHO{nW{XVfs8m|9dbNU*hp z;L-%aO*7d@!Bp}1J=P^{gI zSA;Z$mxzk+ItP%;F8gi(Znx{?5IC_A;Vk>PaLHV=RFj^%V|8jNdUN_4Xr>jT|8(iV zEpzLRa|}VMl9D}h0*n3hN=WenOMP z>&Dh4KGuPRir^-VvREuY7AjF|>%8|(mDeU^xehI0x;iTxNA4kIdM5opGTulc(u zN<gZ76njkPG#db z9t!cu++m5$9W@y>H5LM^m;tiVP4o5id}T!mnEq%<8)q{1z)7lpE(I%s)m~v;9K$&z zD(WC&5nBs_6v4Fumb{XtV7tQepxWkb$2hA{Y**8S20oQ%vsN;Z=GAx9((M{?jz7Dk z;FeQd$r@ID#TDle#SWSkoE111`^K51K*oro2(eR85X1?{Q7mu??1M_1*^A^k8{@0= z7{yITl~u3^^B#XVgV;tVP}JFoKfRpb=El#C3Wote9C@%}O2Bd!VlCp>A!ZLHIg8jj z!1;A`0$>!|tn>sx(%~{0Vlml>n$$06UXBw;3gh76z_54 z*uq(hChNE{6)u0_Neahxb@ z47fy{;{da@!|ce$sswDFXu%y#ZuT;cW5g~* zq!YD_BE&HvfR2vO32 zi{lt!B#<1qv2_K-?S&rX!d<@;x_n7WKuc9YtDh)(x*)^&hS`xLD!GJP^Rm5AfIO&?MVM?8r;!O1Z=Nh;6{_D_-e`6(OqBt$&G_4s#}6Rr@N*x2{Gsow@~alt zDvXJNin!4dO_V{XbTZx`4ABcUYyzq=CINTH!y6@_MjF!VAq-QH1-)J`8&oq?akLL;#430w zdwm;_DX;~?5K)wRULPY)0o-K^h{oqtknv$H8Z4`}+BRepDlT{4aZnVgANuG&yzgq& zZI>di0__r4I~w&A0D%WHPN9r4PzRsG*xQGl6y_*Kuh&DIj!DR8cg|S_s+6g*o<*1r z!r5hjWG1Yw2lA2k-uL}=>UV(^m&!HHQrnO{7qvQ$eMqYp0ycqFYmHv7hn=0oD(rY* zdpiW`^$=B)yum?m^r^5z6K5y_$jgNhr4-uv2^p$Y~&Nv%)h^>(0envge)uzNDaP*n!Q8R)GdN&Ow(=L^9xyN5*f7cEdmEFO-C~T-R>X z^GVR?hT(|fSP_60+##W)anZ0LV-*G_AxY;y>o>HDikna5F*t!qrrNtK0}Zzwlm0^` zXr~N`RaMiPJ#7pDTC0GO4W)5bq0qp}CNmlEw1c2c#bTT)uNt9M80JbnABxRFT`}b!3 zAiC~utZm1*dgXbLHaPO=J0X`YX5$1zui@phH{qlPh@&jRlxo{d z%WV9(U-FY6_gZiVRdvir@&kugaNZj&oczXrfjfdV{Kf~q2>`Hm&m&lS%~#_5Cq4p5 z53BdQ2CsU{--G=AC$V+@83-#Jf5$(-f$bf<{Bs`!0BpYVJ8}3!z_I&ZkJVQ{oc*4=AKbu|i`%$%xmT!c z88;lh3bduvcC^UOB2hFGgPd!@9acrM>tF%*zV-+X9(fn;dGsNy9C{VZ+93eIoB!#L z1K}2qz2R%1I;(iwgI@u=bqxpadIY2l9yo9e2k*EK#~=Q3tl#xo92SSS9XW}W0~=U9 zc?tmV&JX?yY;OylL&qQjy!x-c3wJ#BHxWk;*DmiMwuf=(4X3dkIoy2qs!wU^JfOt8 zYkXufo+`e!w35zXtnPS{me6GY01RJAL_t(?(JF4q#+eh~%u|<>%lit5ZY2)_^TQw} zTz~Qgh;D+Y3*r@Ac3P)W6&=4QznKx+cTVXFmqSL1BLm|RJxHucKpGm%RIQv%h%>lC=K zXOqwRVD`UnqT)vYKqEpK37l+RoZ0 z08mU&R$gksope~~Ha-1lT4-yiElopoxs{b>3eC!kEx45w_jW%a%K}v*ZBhj`n@lFc z%(&~=Gp*t_aV6V#qD;kmXG=p{dd_F6KxeZ@ikVO*)zb2TD~oszR)Mz0JisWi4o!dR zGZRFntD)r_)_5D8eY1nMX6EHuiK2^(Q49gX7Tg6@TgqZ`jigE(r{QB|wrLBc4TD5( zwcsv91YyDnNag?Y%x+yD+bAoalPoX_#B`|zchMsXrJ*fh5h|+fEEJ*BQP3=Z-h#WJ zf(xRCp{=gAO*YEXrQ0JH^DeYOR6*CAdE%@vYT z(3T^<`plHG%7<%=BDs0xGcCA_x=1-_8?^{^X78!6C?+tGd*VCaxHZk8(TiE%&6$P0 z)$Yk@Y|24f(jwGV+X@G1btQlRm!>^3i)j@W(d5>Jwn|cvIn3U(x?-Rh|8LquvzUrY zi*_bXaPTG5dp4=Ib^Y)9x)BEdb_?zTH_j&d*-79uJr8gL%YpR{ZpF8LskI8j6n9~| ze5ZkyNEM8EWHkG|4^d)r_7C!K&bpsm`XnwQ!h?0|`%YN9ONQnbG< zPj#lKwneC^#S)qov<=KmSv8>}0S68QxJWxc-GbZD zLEX21BX8De2GG`>nX+c13{Eb7{PgQ?w&2b}a48wvl05_j0g2B(4(Fhl=cDXY;odT; zc-~GkGi42Sj~reVt@yt-b!ZmU<5HznnF-1e6j32VBMmzj#P`f`njJ|5!aipnDcXa- zLKSWgqw4!=Ky8T#8wa~^2iAVD1$RopRSM7nLo4OyBgki%8C8*Kk`WOI$j|=^NuB|* z&fjdq%|I*@<9bw~W2>Qgfa|F3Mi+oQ_r$wTUTncFafKZUtR{3i8cK1JzAAxs6ud)V z68NNEA_A8JECLaNOC~dMkpn5J4Y0EgV%_|pooZ&v@yqeeH3n7`XL9N1WrP7KJ ztSD%uJg`g|xSWG_5a8VkH~?y*xXvZ%oCFXdkO;&%I17;BQUHqp;vB>Z#tsdeG?K9@ zV>6qX5?EO=2#oIi^y!EGTMKU4XjGCHth=IM0-YqcLjtM?m%0Bs|J=8_{UrJ_L|r*~ zCQ5v+_~d$&!0Z6H$iZ2G4%Bcv;G{6^R8>Da9@^v&JVWwSE# zeJD7HW^`AKj{>Ao0_32j;%g6a@;b8+DYkuRol9U%AWdhSatyHZYr9mv(=4}E5cgu} zj`H)Ni@-rj1}26_7bf?nm9Yr3Q`;a=SX~R;N8Wqi_v7&yfqUiBD{};Qb@uyU0WsjB z7?P+e5y0SFsLMkOB-Q~`_%2Dv=rcJcjK$Vr^Nxdvo#4vV?OfJJKMGio+_{itaP;M7 zb)PG%e0;71N424yo!Z`Y@}OvU{`AEKFnr9biWKQ{L&UpfA|#cBo0=xD~Yu+9eB zGW)83xj4MBf^NrL`^bAA_|aJ%`nfmGI*0FtS>Ig1Fh=f$RNbz|DpNr_JBz@IaQB^u zL@WL7SswDagM09Sw`1WKnqd(Y?+c@fKW_R4*&!jwZ~n}C@B8$^fXljrjR(JWVc2Zi z;Z8(mT4-t78z(1-(!nk^4t2w8!KwGm`uNWk+>M9c1=T&Yu;MDSfVI5At(S|rp$3^& zjQj6CB#P9#KYp6Rg#lM}4&dmcf4_AIv+@fQ$1PNdBGl+IzW<)X!mNJzBac7u$$1>> zxq*B9E58e>a{%qquwN+E1xzzN`%WBN$LgAS<%!21eBZnd(OkgYc=+pa@V>V$E?_ci zSj$_3($F?!5!TiNoY-8Cdv^N`^E~u32Y2n{V>tfT-oJbbDNU(bxdzqn=vYN)E3#`0 zmnt*F2J+4nvCp1nHije*N%1&1H` zTR8fLZ<))m#Rc{Vb=<;aXdCjiCyuXU<52h7)!@{ldwG}SjTy`_i*82||hgNW6b1m%I?T6;k$uJh&wUdvPS5>_NHY*4Yy&A#BU0B_G9aQ(= z@@i@m-DdUeZ8>W&6x!-%T_;eu_wGY3Fy>7k{nm$H+3PyccYWOtpk1mh{$2+v2VRxA z%Bt`@EwoibUx9)+x%ktk@B7pJPzP<&yE@s>dh)biz%T60NQ8SvRiPcyt>aZ z7*;-NK+Q!Ex*d(pSFPdb;Z*_2XIgM?3#vl9wiaOX$f_LL=z<_mlhNPz#OVh~#{hVAXeI|5Q1KhZ_jX(bV7ZCR1x&Nm(z4d_#Dq9ZPz%UMPtYGul zx-iq0B6{MA2|w6WI?&q=Tp}vK10V;F0w7REfdQ~qU3tZ&!Hfar1)~;99aMkPC`;_#kn0~jzruoX0=0vYevy6FkO{c z?!9qi`z>dlxj@c3SnJ@Nz*&KH4!!Mg$ovu&%t0+fEaMBP0j<)EBO5C?c4Spdpq*0u zDQDgHe)N5({@`{ICVl*lgI-;`0tEtzG78KDt=K2e&;-SlDO2I%L;?pA zh&Tvf1+j0LA_R#zCp*k!A+imk9usaU(3T4H6=K{J!48Ss08x*~U9nJ+Sh~PUoCCcC z0NB9`0C4>2yU#Xt3-tRx_Jx16bF24N7ru09swT9Iqg19Yc!D(;4sFLMY;1IK^vJ3N zfe~`{j|0X3_NN{{^{cnz6;+>l{T)xT;%x%m(3-Z0=n4S9$pruqh4U;Tuyi4YiU4~N zN^O&MS0v&aUBlOY{PbOy7besNfwR#Z;%Uu>9|oZ{hOxfh!J+kz96T66DHRj&88Y~> zkDPw+*KYTE(jWcShhE<{xr$K9$mA%})Y&oSv>CtQJ$G$LY>Qz9%Ax@bW0*7(gb>5Y z8D;pt>mdGxpZca#PcKq6wNZs#+`5{ID>Gc(ue^2rmK@zY{2$1<|2?uog`WAz_nmra z(d(%Ncc|hvX%(b7)}0e5{>u-)_rc#;_G)Uu9d^04acx^5Ro0a1Csn(&;0|4!*b-Jj znmkWRm+i#171V+|3#%YgZ8oW4)+%lb?pSb}4~I!Zytm-C;Ev>WFdQ~ZSftW!q*dG& z+%Zk}l2$>Q*Fu?4qPVtxT5w0xGo4kC*=^b?ZVT>ss}RlPgedi`v{s=7x29FtJs-xb zfst~%Ypp^H?#RVeQCyiZ%hE;_T5xA)6=W7r4{e*Z;I`lnSs1j86W-;c+-A&U@_ z%gH`_X3tC#r=cc~jzWY20)fyK6=bx4>q6ktj*JL=Z%$Fy2d>~fr4)6Lfv-Sh>sa9D zcWw#>p1}PV{=2|PG35IJHxhcu>U(Ls+Ism~c-Vk^eSO&+T%0_uEZl6^Ts`da&qRno zAPSJ8jHHfV!D*0h4)M_1o1Gr>A&tp-cd*#g>eS-!O`>}rB5?#GA~rG&76q1;8MeX} zy1GJ`PWoM32ETYe>bpp?IaSUIFvlin*nDTI&GgFKWbW|G+QUnOaM{wl68)jtKKJF_ zr`uUaUmqWz+olaM?!N@$FN_Evlu#`c4U~hY<#&#YNTAQ3HFZt1%&1S~g`sD%s{4>X z)S3IIxNkVvj^7r$HHJzbBlj(O#Cwj}GP6E!;nHSX%W8tmbwIXN(~z1r5xg;j7lLC{ zxXgLZtFB1@!JSHmHX7!5Y+`#aE!nd^2}k#Jx7s-7+;h7<^WQpRiQjU+zh9>MIq8O( zu!ERW2)kC5MuLXODwt2G5f|GTDMJGy zc#?DnMzd&f9Gm)~R7@i(tI%qUVAqCu_gKYmJA3Vd?=20Wj6??M5$$ROs`Lpoj_A-x zrGYV2?|)pS{b}DhKU?hMAn1$it7-llIjDqV@vh{6)@!iUoM088S9t6ZxZa58fs=eb zuI{Uax#=)iE7Vh`Wj-*(cji9H;AGe~3X!9ZL~m;~z+T|C5C^4yHpdE86hSFqwdJ%& z;M($AY|{okrO+Da>N+{OBbQO=INM(sWZ{fKQ4gvi-Pw((jj?VU4f z8h=*^wB;zwPGPPa%nUDKW@voYnD`VB3qnB&MLwfuW}_w3)}8+cm;8I5Mybo{Gu4q-ntfGfMMm7%*m%QUII7$2 z*yoY)aqiIJf?|1u+0iMS(i%Kpo^yE-e3%(aqZ(|Tp?~zKn;?@)ZtX^v`38w}8jHh5 z8~uR8@*G|#y_`iZH_R6z?wNabP!*E|^1en^+h| zZX(E)&P51YO?CD!_QOtmg!PJj$+~?8&_^c6;jkWPbDw$(j_D0E5HFodo8l`N5Qevk7bKn_YUsc2(7Gm(Yq?hiY#^_G2Ivxg|KEpbH`ipEHwR>)~d&G zZIwyujN58&l*$=qQxz`Tc8@VM!N(Kz%#LCY@%-HG)8D+RK>HR}L zG}PeJ9$Fdx#F@%Dm-WT}K_`?pih8jZ4T4C3TgI(xekJB|yF;f#lDD@lm3_mP5MUz* zjTaO6;;i7Ev*{DiB#bJNz2`Nz*R%4_Z{vb<{kGw-F` z9`HVFcJObYFF`rsl@cDJF=X#+3d+ zxU$5l5&!xc%)`rD+R*SGnoKq{`{++1;)kU=Imy7xJn;F0NtDy~F8rmXB}?g~Ki}>P zByupIMKSI?mO^SYjMs^DsmX|y)ZCTo;$J21=AFI|we&ohl;Qk_bqgey<3N9))kb;S zq&Vw-a(Vu=CWHmL+M68cZ1d#w{KF#66A`AoN=0f_hk+=?l&Q@a)$$Fs!}qj5xls7> zlD@d4>>H}npPD|`;1{RA1i0Yk>9%}>X`G>25Z`S5dv9IK()@UkDt;OvFE2g90gYmR zt@tx#-Tkj@s;u{27l^JQiFbatOLmtT#n14nNlE&_e+&ddZX72HM2XW)$%(0*5o$_7 zmGMwQ`7fnQN4jCkuoBwZIImsa%%(vv-e~tP_kUV?l8jv25cmxEVAcJ6g6QFixbMxk zJ%l(flJfjSPia7fYc5ds^G=*^Q=W2Ec zrzGOX@rILR+`PQKOB=e$CRJ7K9i3&IoR|><#jfw}2F~xS%*{d7)%}NV6hph=+_VT7 zF>r*0gd^+>5~jgo|NdR2ef~VO!W>Pr6of0=_Zswc@n^+#XRX%Ay)TMj`+LX>vzC^Y zz`e}n*cv~Cjb4l!KGh+F1tv#@YOYc>0i_-1v?t4k@a?Knd~0GT0Uc^}DT+RH`ue;t zzOyg>MCe$dHpJh3iLO%2NlnG?=-@IuMJik$a&CIE+=f$FSg5(es)$XaD5X*C#f80e z>Vun|1%W_dajL&*nwnya+M@n|L5AsS!pZ0R*#FJ7Gwk7NeelFg&gd@U)Z|YkBSbZhDkQD5~KTr1ezAPLhJUQ1c*n)fYT8YLfPmoluK|js?(=i*aBxsDgTv|% zi%L!1-ZW)+{mSvs@%NtOr0?DFPIYaFJx?#^KRh0T2ER(74X4du4x)JVi?J8OUnDt* zud%kQ6Ct)LSi1!vTSnrP+dDZ8jD2PwePE)`rv7MGrkbI_l2{9+7{;5AFt< zOuN$nN#8h!Rto!U&XEdlUixta4Wmuu@S;9EJQN&%($aQ+eb~2}g~;l^{nj3t9PN|F z6i?Lsrbl?QtRNWdAHqR^;%R(!@DA@et{*C*^+=Y>_vzoFWZ{K`S;rP);9buvb4{#G z)tJ{*eD_<|`4+IAz5K52?>-oRqP5Of#W8yHu7#%TJlGWv9q04)o!`NMxSAS)^O(^v zBfl%789M~2{>A^CS+aGY34haOt291V?{}z`sjCy&%E^QEC+L=tEcjaU@9zH2j|H=Z z?Wy0bSm@{E85S`1!?HQu(B}v#v`=3`eJx>M(-cBle`Fhnp9kJ`ywkNv&hYOtoyZp^ zz}wyRyNn`8EzH2-LI&~h^KOko$)QI1`~w`!jG>IYya1+4TS*V3iuI&@NpIwu$Q395 z?%#EAasUF62>at=ir-U=F*CUh=h{J9n=|368ym63J8$%y19$NLRra{5k@ z7=IeVYkj$0+4ATR%tl6x@N*bITz$#k*ldDBVv#IoLSdp;k&q7%_7Cvi_D}wIxs#Tc z7cW{IOvG<)HPI!pG+#S{yP$~Z7D#4G1W(>mJ=HPOY8YUUR>(K z2ZAhiGZ(Mtc)WK7$%UwM50Q;0_X-+PWqs+g4u^;L1LSYW9cyAI?JnI9wjyo8qGw(E zWD~!7{1ICVfzny;dG%IkSXx~~?%7Cbj7Q<&<-_PuZAgXgNV=F7(QeB8SNJ5N9`K$( z?=1LqMWKkTqboZf`R=~&t|ui#?3u&V|B$xxtq&>HYlFmQTT3_TQs4Fgw$zz;c%DjN zJx1DUIF%xDbE@M^N>OpN{@5_!a>(A%v42iov^=WPs~7$LrS<&nMZEK;gSN^|Rp$2M zY*`hFIGIleX_y4X9-o)550$8>=-JO~T|L;$?SoQj=`3`3Sikc^U$^=?jBk41xWXi2fK_d2Y$^{mBobla4ph_NMdX!9A6X;Dl}i#Jcl zKbR%q*%gz1*r|oU+OZi%t{0I#pB4p3U25nKHCRC}cFse@ZF@O|{4Xe+`G}Rq#>?5MMS>qaN0o3&RNOrtTKB0=)%D{Px=RIV}1kbH?O7a#iwp z-YHLu;Iuq%BAGj^W@?Gtj!^q;r^!dp594N|!ijCvAH{wyP@@lzhqZ}SkmF%uWF3nC z%uG4Xm129c)`X-ka)ax0x}Fps4tr+5SD<<^Nw`WkQ^s7=qbes$<&tUPDTL)M;T9zjA)Ka8w<~=7xW(lb5OI-G`A|e)z z#K7zhok~G0u}dds-4pPfzm(adpr^y^=j{p1-4PKH_b;x&5$MxmgSfSJB^2O6JMcravcQ>We`w_0@px3^>RulS5jmbp9s+wvkIa@kV$&Ydb zc9Ay`|Mm{aulUk+U%&Qk128+;?4W@gRVkD^cLa0cRK=#J+a)4QaLeK@Lj1M5M#N(K z=KSqmUY|moto`)oO1;C5+^X-}i(8v9s9Zw_@A&mzzVqSnIJ&Xuw+@T=J_#BI#`etz z)4t8k&HCjtauONW5OG9U7y)gq|Jr?B6|$h9AiyGlqkhTx;QUyTi<+hJ2t`qaPM<*2TYd+~TqpKhD+$ zuP*jL)7aS526+m(TaC!(bFS~C<7dZA$Yz&cx!my!xY}zKOaYelgF2>`2$@PD7edqi zgrvWJJ7po0%1f+UAV56=?#_nl)Wv1(Vi};k%er(tI==6?s+X@+A@q(WFmH>#>ubf&?XzB7=^BNwA?gcd@LKp=6E-2PN?USNC298Wl zM2g7BAkL7C+SMArqXiE-5%d4cX~4t7#kU-7v=PZVIzER6z1<_d-u%tb2e#_MhK>nR zbNuWw&1h;A)!_gsEu{}JY9ZGCMHGQaCLmpzzjl6Vy?i`I4_*29$4D9$1C&f66nTB^ z^~KKCgS{J1Q)zZ~4V_7`^(4Ve=F_J(81p`JEZ~TTL=MXgDySGY93xYL#e+qdn3-oc zHd2y^`60Dkq-}(Rntj+79@Oq-y|?3U9AOpbtc5e?lafX5*07sj9h%(rwP zX3M=JNt#%iw9l#;r94mwjV)NU;Vh@92U6p#qe(x`^&eHu%+99wdSMTFQ0{yjV{Y9q z3b=>k=i}Q(db=^Z7_zr9v>{0Ny?<3|XAb%h^e`?WCB-O9fz`XYNdX(y8%u-`i3J}a ziD3@{gTcK`(;^Wi8!0D=iLs;2eEF;_nv_J7-)m(Z3<%Zz?l)iVG&fcgKavLxvYJfA z4Si8VUSbehq*3Jh(gV%&b{D&C1?y?*ixb(bt#1+il6_{`l>c{ny-_ zrL)8Sf<l~cQ(ntA@e~VsoQJ! zv&N0ugY#RkbKvDr)ho%4y>HAP%nIG)O&WbzUEW63%@?kqndVq`&%5mINWUk4pWQ$#`{9k>etd_S z5m52o{8% zZezjXZ^o8&57fGzGa-!DsVOy)%Y!n26xDoY=KTH>pOKN#eST?nEeQdYz;ZO5wj{G3 z*f8pE|6-J>Vfena1Nh5Oe&Hw5da#`^yZ8s+H{j~uRfFX`6K*nbOx6z6y|XR%?)Xa_ zPJ`W@3yFB}YEDqUWzz}xohrkqm-uH#H9N#H`}Vb}LoX-xHkt}GPTy^9b@^GDM@avs|##ql0>VV?eW4|^!&sABR|}5 zponRG9P}L}fIH@vz7I=w(3+i3B4ob-4pq*qXU`NL9Qf89B(gI|H=ZN-k*M3}wB28{#7?`c`Brjge0@Ppzped4 z3HFX4KRP;yH(nnX&~wSZIyhA2a>A9{*c==l_SLD2^)-~qvmW1IV!*1=cfa0zkI-Tz z;Wh5fEtZ7W7qQtETwhs1Rbs>-6N!E4@S$Xu%4$^2;&d3pRVfm}!|m-}>u7MjbBRFV zbh>pGGj{;URLb+Q*;C1{0)`F$jE7_j|Fm^{7q%Q14-e1HPXrvB+RNel8mLkzMhZNIpJ-Vj?6S`j%gum0+G~o5MIT3BqhLBV`b}JWP z!oc5X*t2~`2jHc832phf5^ZBwh)_}Q0?bTRp;q2TFjM};JEQd68e?g?l} zU}y0^PCH*Sv?kMab@70rb1Sc~ zz_lGoj?ku#Y}~gY4IiJwwshO{azx zdOIncDNT#wFTu6WPgiLCi99RmxrWK)(A7^@_X{^uE3Wh;K^M#@)%2>c<;&OK(#{xv z9$JHlR|tYK0XqH8vjc#OsV))>q((08%UOAH!ezuzqXyf3j`DC$$}cXtj9*K}fl=p^ zXQo`y`uOVQN{cHrlTmxqqs?zX-0$rrQmC<`h2WcBEi9-Ajvy}mU842x(OX^J-3*#3 zp%<@aqXVA?jh2Ok-c1UE23Z7z*1Pop^kj>iP=Y`BKBo1ilSWz@0(KKQ?>P%|BQ)N$ z2CYIK#?3fF&Wtq*$8T0c;?-)L1s4i>Vx|_uZ-EXGr(y*~yzkl- zYUlwBQ(F^C6&D*o6K`+NJ4OlcIajNK6Yl76zZKjM)gt1)(A$Pl%eHd1*;Ee=AE5=Hp%$6+kR1YA>DZK;*5{^ZE3tBmGL+{CI^jDvCIW&3pjnl!9Loax1tX~1pl4&+n=gC3 z++b+?Ws!liRw{xz2ewp$a6XzPuOXc$J8oom5D8I=I(m_l%ofJ&WRVkqj>}{x7su@d zObiT2?GL<DK)F*Pez+_AXkp#!G=i?oB2^5 zxvBniE2{Qnj>E!Q%jjLmi_-LOC=j_7tLl9*XUgZ90r)H-;Ll}?)yze{^htzbvVX~h zbk(vR1x-AnQ@3=ZP#%l?bnW(Og+j3x!JJl9%-lGyMPvdhbB7qbVge;l^IZ7!Qy+L- zK*Wx=%qvSKM2DazYK;vs5ku_li$8M-U=te!kEldrVBfZhN$}d_FxEC;l<;j(v$9TV zo>Kll3ouDxILZED6Ueat3V_x8I<_UMEX}9Pl z%9}4*)k(~@+q1S!rLyV)+XX7R=%0L8GIG{bHFZbcFBkKu5j5z%cSClUI?Z&jUvXQu zb$^N5R2x_#AH5w^P8$@U(64V#QM0B|>ExC$RMpFDw#ggJWs`l6+M6nXYJjQq)AdQ~237KaimID472QE7Tu-<>k3!w9UU z1^Dx?NP$8c#X#dKg;7M6F9C@@h0d=cJsZU{&BWMn*yyUD(e1`iGDMtzd*HhWw*uHL zF_FUmNJnaXn0|rUn{p}bHK7-h6vyV3!+0(|vXGPl_+aAkoiHEv)An0~M&-siQaLW* zG*~2W>Bp+tPA1luKqvrE;kctu423MeleWiUIo5CWxi4S~pE6I5;;OSnB(t0J7X^$G z6H|7s#zqNUyxjK%6Vhqwt=ezjnwuUwCsOqAUY1xdr*SlN`9|L4&d7!Wd)13vH0KCM)0 zR#EbGBH9-lYYHRG=X1askyk-&RZNfU>yunO^$~m6(1(?4Jc7r<{tgF6fnQ?ee%1!Q zc-TBW`o-maZMLV7ed@Dr77qc-luLfMLW>}^DpmVaH=Eo=_7glu;X|ezWAV21+WBy$ zxiJ&^>G8v`M0R#@3hj9IRWx&axXbqsMxB#Xyep?(khV6$p`oGZfczB;G5n9>zkZY% z*fsB*fCKufqpTKzB04*g0($K~RMfVqO0D<-Z|}w1*Qdav5YPoWn*A*4i~sGq-xqm; z;>Stp?a!Zeb+Oi>`oTI{=y5-P^8MZ2HRy5UB$U8vKqX)s9KaL z0vj-T&g|YmKA63u!!B=MyZ^hBB6xsyCnnjeK(`2P=o17)zKd34i+w!Zp{MgMB#Gnm z=4PIv4-4NyIveY)B|}2QnV6W+UIpCw=-Cdz_t$TM)%qqZ#QzS{VT61l24XO&KeYJE zyu`oQp<6#(M`{)Pa3&1)UNDLN2OyxmvwbgMx(u!&=F^n6eT|#`EI0UF+Zj%b+}vtV zVnM^q^_`Gs7tsF?&d%hzIL7hdP|9(GUS9NDt>0lDL?|+b9`8?l?5{|SdL17Fw^F8y z5IJKKr?GqCTQwQO%ois5E2ja=UQt1ZcI4#nwL1Ra*jVHlJ4~S44}%t5{!9I4u1hk2 z3rW8xM*X$EPBsV2V4H4}d)!-H4XNxQAJ1Y%4U30SbD{u&wV z6p0S>V-C@==B(~63f=)C_b0tDuRUCnGd30FTWh`>=x}}ZAgks+M0;g2jcVH3 zieW)+M(QlRVX^!5ZZVb|@#2IJDB#Ah$+q~;E+P5mf**_qCDf7T`%{I{Ui5Nkk&)3U zL{yRHyMp`X3ukMcbK}g+R(Te4Dn16or4dMaSHbY+6B5o7O@7cVUo4tQ^a2vIeK&ZTWuM&NFasd27OxTU0M$;K*fF?8AD{8Jn9SSI6 z($ZTDLtjQSaE=DAf9rHM*`V(GBwFQ3_S@6+@~sNtlmbINsJB!)CN(21O@q{V4Ta87 zxXaYodtNv1M|Dfuu_Kxaeq3Ilp*{u8q&=DtshoLPqb{8xC`k&j z3DpjlyncGg5epJR0-K{9C7fqQb<;#sCZwdK;lAS-z;Ad&|Jiw^)_RrNV5|MwSzW!X zk_-y=cslj-9LFyb+fh`NH3&~w1PZ{Ssr!IqPFN1kc~6bpp}s+=>ybtE>Gn+4G~7a3 z3i(8e1_HRO+;&s&$`(}Nk>=-`xV7;vSW1rvoC;clHu>olbDUE@K3&-kjJQ#JNj*}x zfG_Db@wgni_quZd%;(GG9KIlbDN+>B(&3@s(`m~mXdJ3D4XU#=OaM)lLGckE7)^?h zBvQ2Rhfu5i{D!uZJd(@PY|1?q9b~_c<6}=Z`{O|sn<2I6;YfJ$n(;$q& z*yB#H%eZ2_`GY2MMTyA+FJK57<}>IhZIEN=LE|(q*>iD^)bg!S(1PIxkIt~a44#omgmQ$msE$LHO{COi3)){_E~ zf*&5VQ$qVBt*o$X4@*mauWkEOQv(1K4mXA#&?9A`OSFgP~pMNQ5ttS7N ze%=TaS$|2ZFz1Nffu_LCBq9UpJ`&^~fc<`bb8Bh(kyWq8&}L-WVz2^i#k|?V$-STh9lS&#ZA<(oNP298MQda2{DH{H(3C#z$qyy z0~_03S>bll_;6z}nwBnJ(&IB5pmHN&lEgZSpxp-w1YS`1cbejU&NSctJE|}}B4HOG z49pGAeEEEnbr=X8qvdsxGfyfxmR5%OBWk zrOsVV#)37-O3TfSi$W#%N8H3Nrz0kqk5423Og_HrpXjTZn1Nru)74GO$c`})_LVBf z^>lQaU0P3Ob?uIOw1QgZHE<7YNdSfgY<&3Ysxd>nrG3mj^UsCAKpvouF3|L zL`wWz0$j5C(Z;?ibN@~SzL>ROXzY=9KjOTK-nO6g%(x-TwNT&&Q z4smhv6wzDo-b7LDq$}NcstsWbCTTxlD7shGVT2)%tE=MyTz6h-j3TexjzGqw=$6^D zZQG7#cKf@?d9u+{%v{F{gjG791JN+7I5#_MSbm?bKr3rM;3B|S(Bv)kf>{eERRDHo z@8AFff=5KURD=!18C}@GltKoWJBeF7q~vQYI#6FNwn2@)^xy!BQi~WYFH0%peK%!i&)}vTujkxEV56}?qa-*AQpq4EL+KTnHgze zQ(5@Ve+Zh&bn?fjh@ix*^_(xYm6b@KnWfpVmw-D6jd;l7^kj_B(WZmr$Dy`wAIeHf zLbFTv%uKl4*{aA}4qdS0uqMST<;>QW_q>EMTokY%ta^U{XRZnGv|L=+_`75+UGVk- zaaq6o`lTguHNkywbRZ#XL(5PO=&Bb_FZQ#nZ8D5QTOeG772gwyPqGL=0EPqn*K>8K zo$p0K3n;VYCP$=Bc5nQGh z#=e^nuS;cu9#%g!IO|S5OU!QOw2F^kjsvTg8dKETJ}^f;A(~6$>jl6hEMFdP7Vnpx z>=%$;s;c83e*73A=$?`pJ#;H!phx=N^$+FtY-ym)6EGYRk&tkbpN5qIDF&KMy7P4> zxQCn^koI^gadO{PFvrOtZ(R-5rySaA;{@MzY+UkEAXAoZ!6&*OEHGPY(arwx{#;_? zXjEQdl*UR+yPG_V)gUAPmR2V34w!3{qN0V&Rf)RX^bL{=ID-Y+ZxBG|4YA1T&ZLL= z&jCfcJy*Anrn*8^yz-kly|Dx+2M}5c9oP!3t_G8kL_!!+Z9XkRCRKnEDJz3JJv|M~ zVgefe`Fhg&lp5~dUm6~*jd(3%HVif;#$_Slw9oko|2ZL)hl5}kPN4`vikmx1W$Y6S zBpQgpcQilgv`Jo+5-Z|y2@PBX? zXjJd6l$V!p)jNPKY4U`Egog3(WO2taI!GN{_%TR@BBzgzQZq8FKpTJ`7T!kz;5y6r zySR10hpMY%^YZcOKfd|L<0*xFbaXVMW0q2IeOU0_j|&k0{yyF? zFfwky^m8rR%AlHRU&mufbc$l2BHovMJDO2jBKrFp)($^&L&)Zbh@j^lz^8sCq^VI z>0)cEQc&x*D!^jcj++FCFRtTRRhun`{v;_P3@Eqcg5gi+J>=ZpUoEhbDpJTmA?h;e z=Git$PEzADKaZ`LEwR7XWo8OT2e!Yb`BPFirPiH?{**U(O?ZZ2w{X~#={T3hX4(lB ze;Z=wxN4r;oca9H84e47Jz8JOz${Fhki{YiWNm(8T&54+0*1<$wzY%Pv*GTbCyk96 z5G^>8p7(PCv97LQ>vOQUnfEdfhy(0^Fp1EFkXy_4_I9_wBkzBci^gyEf*Nmzf~@Ar z0|Elxqrr2y|FaIoYL?qvO`nX$T{E;vi?LEwZT;Ig?lwxBokK1#xQ3+_H0WN(S2!+s z;#Gj6pI(s|{7|W=!(6(zAOr&2F=Kf|H5PbZ}R2m z`-l?2Ni7>@jwLC}nfPQr#v33>{V@`hcWgP^Xamg11NrUVnED_!-Px@hh&Wd79{>7g z5M%IPi0ki~BP@{2_qjti07v~^O-256P44)lFjZQ~AWH%svDVx#x8>`@($=DCN9v^O z7&}u}MB!jH@gDyhN0FWg50S#{U0A^&TcH{DpUc0EY+Zu>J}Uj z=?l-XnME`R5zD9PvuJT5q?NhQ7;N0#`w z7X(k5BFfW|>@KP)4^zJQJWOnF?=pH{mlS$(mm|Rm}c{M<|b7Q92zNLo1dlN zJk2>LVg4w@n&AX}twsSzG2rt@Ldimm=TLKsB#}exkhn-!V9LTkZNTsSAot{Mx9LgAEvTP{G#NzkbMU)%#c>8zR zpC0u`qZ4Zw8jd|BxeLLrp+l6x2Wcojli|y8(FAKSjaQn)7?2{5*?LcXBO06HcdKF((W@B!z01d#QKYW~HGy<8}fD!jRiUER)y#oVz5M+kOGUj}em2fMp1z zA&KX)Ly1LZ%43wI8(d~%7{<9s(A?S;Y;3S8jq;!w&4KNdR*lGU^3~P&_V;g{b;(Z;faf(D*79wf1Fq9%f6+Oo z!yJYvnUs6N5f@dprf&Eiu#efN5Yho*?h=Qtq^Su<^bs7ZFxX10tZN6+(8MKiaF#KZ zgeeL-6HIz?Ac$nce^hxQ<|6WY0Xa9;9J;q-(9>5z<8a+qkL^F|oFBmSkjJEu4glF; zr;qQsZ_R~LbHL{KcntG;_6_&yj6;|q_tO8RpZxx{?E`qC=kf&zQrOzk?Xerj9*t&{ z9r?=+4b=;iSTqIFWdP3f*6}&HM+K8X)|N-xJ$y8pTXz@?i9jIOtn=AJ4qqKr-=_8aiUN?VgOJ9$}XfoElU8a2X9nN=KO=4ttKmy!)x!Zug+^yLm*WgIC zg0W;_h(Aryd(HCO9!}-)qLO#Mi5;boL!$}I{?0u&eQ#@S#=UZM($q0_KD1-{Ruc($ z5#Nd=1c?B8HcKrJ(2x<2bXVZSd^*z7(;B^Mx$T#n`6e0M1vXP{1gr@gX&kg=L8}MK)=lM=oAW5zV|bf*0wel zzrH9^(tbFRcqwg*#XEZMErG)77jpBVI~)**M6M6YQa|$j-TQknlRRlFt*3@jTvGW# zKLi%EY-rdIA#Rvyg-}^r+YGUq!hCd4k-g(=oFUwC#;BY#m(lEcE`9XR)YI9_wJVYg z4(`^>%!@U=rZ*x8KgjwzuqC0Sgkr7u>soMaWM_pV7B_{M|0uW}*h;p9ZN_ZY`+qlk zTszP`_ot#D)goW9X9{vq=1v*V;Yfw223z2hxP5%Qw~oGjmjiqp{9<=R4^I!YKb+%K z4uZkP`QxoU;#+pPya9Y;Ow5-jk2miYC>vBTEE-)JYU8UR4dn>0=2&l6P;twj4k{d! zrI$m`)OZ4-zMaS9!peHUAj4JxJ)HU|H4?jvyA0%d&IM-u3-530)wFOC$Ukl*D`wDH zthTxvI_0v*McQ8C4(jt5?c1NhLuD;lRdogQnX`$v8U910HNu#Ks zsw@qp-GLM{kcEKtXEPDWWT>Q$>^=1A-}MK1}M+!c90CvcqDK!!&$Npty_Mwf} zTmFx{ZlxFvDXlFM1jRMQ$g^|gm5deBkBrli}1Iqm{PTi*0quGX($j8N)+_m zqbNx*5Ie29XFl*)wQK?r3r`)S$&(L}pLG)x0uhY5YAGP^L?Dldg~HB;h1@I75gHa2 zrg5ajQH9Qdt<|@rO#S#>HQjv9s)0|`Wi*i-!$X&sgcuB#0Mwjz!29;tRa$+`D3-vl zfa69w5>$xXZ#Hx$oDp+VTv!3JE+qav*j^IIel9J<0CwF!F7zY= zSrkWZT*mmm>wR-8Hr%yX%|)=0UUc-YGMPG%J-5o*%hN_#cPR|5tSs2fG+8BxA`x%@ z{Tgau(y{^+KFXwK03@*W3GpQuSg6w4CLFeG)DI@!cy*8evfFg0kEkDG5MK;r;FNjA zg%b;sVWxmrA2{TY3BE!ENFAtl%gf6U+x=Vzy+APoFaQy&IdKj={5S5tB}?D{;ln~! zB^^(PzdqIp`rTax*T@&Ugu4oo9J&850lpcAbkQsR3Iha8p9@I-?(R|X3mfJ0DuJ>M z+Uz)$Ii2nB=k-ESnNa-w17_#flFo|AuoU~_o2G|-d#*^Wk1UHti97V1J09SuB=pn6 z!8Yb{aG2Z2?z)Jr)}cu)wVgH2z}p%q;6*AnZGqNty8PpQo1hz{tI6Z8%nRku) zKb39#+^GCP0%hHo@H)%Hh~)R&Y`~;tZDVadwc6HtIZV8D>4!Bl#0uK!q;a%=Z_K6_ z`MuCn4s}i43u=#qys-Ndm?JU8?m^^1*YA@_#A;Z-A|0)>k`ddw+*dUc{D77(knRdLfqK7j=vPFXsiRU0nkwVMB zG*~MX19;qBFQK%ew6I_4*sFd!NjW^9xX2%-@fUY#VC6U6n0OgiJCS*ZJ>LI&iL;S$ zQD8l?cX5fXW*A{-`7Nbe;UrsLoL9G-1}-h!Yc$U0?noKLgz6Lt1{v5Zt8m!7VVC1qQaR+hb6ZoQ{I)YQ~)ooj&+NOO(Q1U674snKMy5{3rn=FByNfjQvNCY(XL|HJfG56hAjARmn zQs|a||3OXPQClTHN$3ViKnwc6-Ih%E$+H*Q;d{;_CvpE*V=xgro9_1jXj63Zg zbfU50UHtM<6kFrOBlEq@=6V`*l5`XL=Dy8@1ao`0_cd?J&U^~(3^r$&2In{(V*aQg zbrNvxyRe#(tc=1S=(~<5Wb7Tw3Cz8_C-?gci_W+65b6>J23E$|3aHcw0|yoyDi+%q zm?D=GbU_2_{!0RpjdR;#1`pw^|8_7dr%gTQ)pk1^-q7~DDiRS+xlca2ny7G;d%HdA zU=m;2(K{S9e>M8_rIjQ@IA_u9&ER;(~6PBLZK)!{^1wDWqU9SRxXeG_CAVNV(Z9kt#S5B zl1>Ve!O{{S>JEh?plWDnluYJVKHd3Ig}pWoJqWjQTKbqE8zc9JG)>X{9RD>0F(Ii| z{%arpe&{!H%o;|%gF;Db!?E1JIX-*Z==^*!@rfWTK`eY0=uhm& z`=8{-!3e}<(|8AvGzOpC4JH8lfjHNQiaInikH|RqVYhz88Tlx83@uP(tdtm6#W{Yw zH^JI(D||{`WmTDl*~O9}$=!)FAY0J)hVzSYVzPHVXFAj$PCk9G83M@Vz@+{1-!y$B z<*AIy*0~AW+SFuGhO5?LGWSp==3R>+lBG4Imuf*HWM9i7-P9pXHJI8k&W8_YQ-}Ez z8JYMITJhKNn^(T)x?1$z137|_9O4Bd%5y}-!TB*<*iY;CJ1$)Fc0nyGFr;qr6dne* z^`C0OatGaTcVwvS?<3=d7GURX1E|^!dj$wPitNHE3L@mFzx^ykPFLsotER&rTM*|i zrm5L7&c$FpVybB)$TN=sn&098W9fWTF_K%gc5~a20-^8tsPK4P92zI9H&NctPZ;wQ z-SO*z6P^Fa%jFNt@q?|tiJYV5>6d}_RT8DSusH3S4z78jQf&uT-CPyEhpS1SIU^Dy zfQFJwlb`->=1t*}C=Lv@@K4{8HM+(rU#`i7a4!`|5N0Jurd}TP&4t{fKg{y^2L6$wb~VB6WdY3G+iSC)t5HyeIDq2A1gkn9)ty~hIKVft-z zUh12;IP&=-my{Lr^jL;x3Rc+5%~o7GtLzl=FfECEp61d55c{`^+EeLhJ)DyhT3rEC z8{7!ezC$!$1ty_gc=##3_JyW)?O?{4ND^AgGhTP>^`P~sBpoyS zyD;ZF!^(zNr=ahS)@%Eu<>lkUU!G>|1VB@;w&RQAbzYki_|z>MqY=-dc;?{X1r1hu zpM1AED=RCDL#6f4O!qrFIZ1?NuQxR}+ehKjlMNn;mP6-u$e=UmFhpsje)$&5`xAWx_necp`^~{FsCFID@8~il={9>B z{a{oc+g50JO$)GISF6>#5>k+J7nnq<$jYL{eX(x{w+?%IdjsDx(stvtNF;Le@JNT> z4bV*7!9ggjU0E7$g&s7>1UB-J1>(3FgIIl3LkFF&?rF{&{WHS)R9{@@s+w5d0i?s~ z>OzPog2=I^X@GkAKE5u37nJ5<$--n|(x=76-}`5}nVS=6C^}6{5aey3-Su{IG7ln~ z0+Sm*)b7q-dX~Ds_k?fkuHuv&e^$OQNhAoKF;qjYakA8H{QUmD6UCmR@i9*owVk{2 zpYMe3K`Vb(7e4sbK814Rp9#S-$%La6(;5J{4Kzle0LoeCpxNq)dc$In@S&+-;*h=?XwiwxN?t~~}DdiDm zigeICi;-cq?CJxNXQO&_HANn#AjlsYqzBV4t(D9-%9>2d$ zY-2FA0ulvfbP6A`?_R1|3?d9osxvQlF6?RLf-29;%#=w z$+@?9Gd6+gy9tyrxDCkqh6d2^1A+5kMV5GoBPp<6RR|lefYnJZ`Y|}@hOw99%EVAj zW;A4&BWv?jJE_o#1n>VOX?3`|dplz2=qN@`W~HHcS1xH|VLISCsB?r7uD=vpXRWVu z>_68v9KBW?QQh^Suf$tD+_M6ZMc_T_>Y6Z)XHafrK0|A-zQUO%=SJqW-^42g&xVFx z_|@Flpd&enTc6BihCO*|@8g3B(7QB}Q1q|q0ep5{97i321HpLqulLs8N|46qI8oUY z*Zkw(D-P(4Whr=fh@Ed!UhISE5m?cdFlo}x&aKWZd)P@R%_mh=*`tR&%bg`OrPS2a zpg0=Otw$n}E!!W9Sh=p$bBD#*CZbEYxoWQMN|UoefddZFgwa*PiM z+L98*Woy_V%@c{)afE~fGi?_t>g81yI1G_e5A|e#NpN@bMd1SH9DO6%f>?f|vLQ}F zb!(v^gXId>9Z*j%S`kUZhT&gA+z?+kgmWeJ1>vZbMA>sEZ10-ji1uAsT!9tX@qy&iX+&sVacnip%W$1pL!T3g+vysX;mD)-ynZ3-; zIhIxClrM=8^IxjQH49XJbV*Ya2Juf$FgPgjwzmSMg}Hx0W_vd!o=Mo7oF>u%E+#Xk zrn-O24A%%M*>4wODgCYEqEqDJ7lqfT1|stRjt=H5SxUEMoFpv82eB_u6_ScilP~2c zd;a(0%g4T*coWNBqQI)mRk6(AVQ-;)ALt&H4rE8f*l^y-NrOyo+6}&6V{31BFsEqW}N^ diff --git a/companion/src/images/simulator/X9LITE/right_rotary_encoder.png b/companion/src/images/simulator/X9LITE/right_rotary_encoder.png new file mode 100644 index 0000000000000000000000000000000000000000..3d9f7cf824fc00eef50d2179426e579898a8a1b5 GIT binary patch literal 9958 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 literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9LITE/top.png b/companion/src/images/simulator/X9LITE/top.png index 427ee09119beca5a0de1ec7c645da58cf731f9f3..bd15db2b7e0e42f0d67ea97a145fa071d093df1f 100644 GIT binary patch literal 3913 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 From a86c70c26c287c1b315226c752ac1562e754f134 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 25 Sep 2019 11:05:03 +0200 Subject: [PATCH 033/257] Fix and cosmetics --- radio/src/gui/480x272/model_setup.cpp | 48 ++++++++++++-------------- radio/src/pulses/modules_helpers.h | 14 ++++---- radio/src/targets/horus/CMakeLists.txt | 4 +-- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index ed166cb1e..fa48cd9de 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -69,17 +69,13 @@ enum MenuModelSetupItems { #if defined(HARDWARE_INTERNAL_MODULE) ITEM_MODEL_SETUP_INTERNAL_MODULE_LABEL, ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE, -#if defined(INTERNAL_MODULE_MULTI) ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS, -#endif ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS, - ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND, + ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM, ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS, -#if defined(INTERNAL_MODULE_MULTI) ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND, -#endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA, #endif @@ -545,21 +541,21 @@ void onModelAntennaSwitchConfirm(const char * result) #if defined(HARDWARE_INTERNAL_MODULE) #define INTERNAL_MODULE_ROWS \ LABEL(InternalModule), \ - MODULE_TYPE_ROWS(INTERNAL_MODULE), \ - MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) \ - MODULE_CHANNELS_ROWS(INTERNAL_MODULE), \ - IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), \ - MODULE_OPTION_ROW(INTERNAL_MODULE), \ - MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) \ - EXTERNAL_ANTENNA_ROW \ - MODULE_POWER_ROW(INTERNAL_MODULE), \ - IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), /* Range check and Register buttons */ \ - IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* Module options */ \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 1 */ \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 2 */ \ - IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* Receiver 3 */ + 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*/ \ + 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 */\ + 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 */ \ + EXTERNAL_ANTENNA_ROW /* ITEM_MODEL_SETUP_INTERNAL_MODULE_ANTENNA */ \ + MODULE_POWER_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER */ \ + IF_INTERNAL_MODULE_ON(FAILSAFE_ROWS(INTERNAL_MODULE)), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE */ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 1), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_REGISTER_RANGE */ \ + IF_PXX2_MODULE(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_OPTIONS*/ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1 */ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2 */ \ + IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_3 */ #else #define INTERNAL_MODULE_ROWS #endif @@ -1432,7 +1428,7 @@ bool menuModelSetup(event_t event) } break; #if defined(HARDWARE_INTERNAL_MODULE) - case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND: + case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND: { @@ -1665,7 +1661,7 @@ bool menuModelSetup(event_t event) break; #if defined(MULTIMODULE) -#if defined(INTERNAL_MODULE_MULTI) +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND: @@ -1675,7 +1671,8 @@ bool menuModelSetup(event_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTI_AUTOBIND); g_model.moduleData[moduleIdx].multi.autoBindMode = editCheckBox(g_model.moduleData[moduleIdx].multi.autoBindMode, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; -#if defined(INTERNAL_MODULE_MULTI) + +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: @@ -1687,7 +1684,8 @@ bool menuModelSetup(event_t event) lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, statusText); break; } -#if defined(INTERNAL_MODULE_MULTI) + +#if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: @@ -1718,7 +1716,7 @@ bool menuModelSetup(event_t event) mod_cell->setModelName(g_model.header.name); break; #if defined(HARDWARE_INTERNAL_MODULE) - case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND: + case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE: if (menuHorizontalPosition != 0) break; case ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE: diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 6a2a6a34b..8b03d419e 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -339,24 +339,24 @@ inline bool isModuleRxNumAvailable(uint8_t moduleIdx) return false; } -inline bool isModuleFailsafeAvailable(uint8_t idx) +inline bool isModuleFailsafeAvailable(uint8_t moduleIdx) { #if defined(PXX2) - if (isModuleISRM(idx)) + if (isModuleISRM(moduleIdx)) return true; #endif - if (isModuleXJT(idx)) - return g_model.moduleData[idx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16; + if (isModuleXJT(moduleIdx)) + return g_model.moduleData[moduleIdx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16; #if defined(MULTIMODULE) - if (isModuleMultimodule(idx)){ - MultiModuleStatus& status = getMultiModuleStatus(idx); + if (isModuleMultimodule(moduleIdx)){ + MultiModuleStatus& status = getMultiModuleStatus(moduleIdx); return status.isValid() && status.supportsFailsafe(); } #endif - if (isModuleR9M(idx)) + if (isModuleR9M(moduleIdx)) return true; return false; diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 065e4d6ba..81f4a21c2 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -110,8 +110,8 @@ if(INTERNAL_MODULE_PXX2) endif() if(INTERNAL_MODULE_MULTI) - add_definitions(-DHARDWARE_INTERNAL_MODULE) - add_definitions(-DINTERNAL_MODULE_MULTI) + add_definitions(-DHARDWARE_INTERNAL_MODULE) + add_definitions(-DINTERNAL_MODULE_MULTI) endif() include_directories(${RADIO_SRC_DIRECTORY}/fonts/480x272 gui/${GUI_DIR} gui/${GUI_DIR}/layouts) From e3a9c1ddb6f2623e06cf5d9cacb100f85b3abc7a Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 25 Sep 2019 13:43:18 +0200 Subject: [PATCH 034/257] Introduce delayed failsafe check for multi --- radio/src/opentx.cpp | 5 ++++- radio/src/pulses/modules_helpers.h | 5 ----- radio/src/targets/taranis/hal.h | 6 +----- radio/src/telemetry/multi.cpp | 6 ++++++ radio/src/telemetry/multi.h | 15 ++++++++------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 16419655d..3dfff66a8 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -869,7 +869,10 @@ static void checkRTCBattery() void checkFailsafe() { for (int i=0; i= 2019) - #define INTERNAL_MODULE_PXX2 -#else - #define INTERNAL_MODULE_PXX1 -#endif + #if defined(PCBXLITE) || defined(PCBX9LITE) #define INTMODULE_RCC_APB1Periph 0 #define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1 diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 87944a862..2caf121f8 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -73,6 +73,12 @@ static void processMultiStatusPacket(const uint8_t *data) multiModuleStatus.patch = data[4]; multiModuleStatus.lastUpdate = get_tmr10ms(); + if (multiModuleStatus.requiresFailsafeCheck == true) { + multiModuleStatus.requiresFailsafeCheck = false; + if (multiModuleStatus.supportsFailsafe() && g_model.moduleData[EXTERNAL_MODULE].failsafeMode == FAILSAFE_NOT_SET) + POPUP_WARNING(STR_NO_FAILSAFE); + } + if (wasBinding && !multiModuleStatus.isBinding() && multiBindStatus == MULTI_BIND_INITIATED) multiBindStatus = MULTI_BIND_FINISHED; } diff --git a/radio/src/telemetry/multi.h b/radio/src/telemetry/multi.h index 1b439ea24..de61bb745 100644 --- a/radio/src/telemetry/multi.h +++ b/radio/src/telemetry/multi.h @@ -118,17 +118,18 @@ struct MultiModuleStatus { uint8_t patch; uint8_t flags; + uint8_t requiresFailsafeCheck; tmr10ms_t lastUpdate; void getStatusString(char* statusText); - inline bool isValid() { return (bool)(get_tmr10ms() - lastUpdate < 200); } - inline bool supportsFailsafe() { return (bool) (flags & 0x20); } - inline bool isWaitingforBind() { return (bool) (flags & 0x10); } - inline bool isBinding() { return (bool) (flags & 0x08); } - inline bool protocolValid() { return (bool) (flags & 0x04); } - inline bool serialMode() { return (bool) (flags & 0x02); } - inline bool inputDetected() { return (bool) (flags & 0x01); } + inline bool isValid() const { return (bool)(get_tmr10ms() - lastUpdate < 200); } + inline bool supportsFailsafe() const { return (bool) (flags & 0x20); } + inline bool isWaitingforBind() const { return (bool) (flags & 0x10); } + inline bool isBinding() const { return (bool) (flags & 0x08); } + inline bool protocolValid() const { return (bool) (flags & 0x04); } + inline bool serialMode() const { return (bool) (flags & 0x02); } + inline bool inputDetected() const { return (bool) (flags & 0x01); } }; extern MultiModuleStatus multiModuleStatus; From 3bb16f9d57f1a0a3a92fc3924a58f41718d9f5b1 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 25 Sep 2019 13:45:59 +0200 Subject: [PATCH 035/257] Still needed --- radio/src/pulses/modules_helpers.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 1bd6a1984..d80a32860 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -346,6 +346,11 @@ inline bool isModuleFailsafeAvailable(uint8_t idx) return true; #endif +#if defined(MULTIMODULE) + if (isModuleMultimodule(idx)) + return multiModuleStatus.isValid() && multiModuleStatus.supportsFailsafe(); +#endif + if (isModuleXJT(idx)) return g_model.moduleData[idx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16; From 149edf95b8929d4268fc0687af73d3272e124edc Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 25 Sep 2019 13:48:15 +0200 Subject: [PATCH 036/257] Cosmetics --- radio/src/opentx.cpp | 2 +- radio/src/pulses/modules_helpers.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 3dfff66a8..345449ab9 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -869,7 +869,7 @@ static void checkRTCBattery() void checkFailsafe() { for (int i=0; i Date: Wed, 25 Sep 2019 13:49:19 +0200 Subject: [PATCH 037/257] Cosmetics --- radio/src/pulses/modules_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 108be6f57..3bc69e3bc 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -348,7 +348,7 @@ inline bool isModuleFailsafeAvailable(uint8_t idx) if (isModuleXJT(idx)) return g_model.moduleData[idx].subType == MODULE_SUBTYPE_PXX1_ACCST_D16; - + #if defined(MULTIMODULE) if (isModuleMultimodule(idx)) return multiModuleStatus.isValid() && multiModuleStatus.supportsFailsafe(); From 1045e0dae4a21506c529aa54fdd605f41350b7db Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 25 Sep 2019 17:59:27 +0200 Subject: [PATCH 038/257] X9lite simu (#6830) * #6821 - Skin of the X9-Lite Companion simulator (#6822) * X9Lite simulator code * missing files * fine tune * Revert "missing files" This reverts commit a181775f3d8b030757e3871e7aaec40fb9b0df8a. * Remove unused images --- .../src/images/simulator/X9LITE/Readme.md | 29 ++++++++++ .../src/images/simulator/X9LITE/bottom.png | Bin 252 -> 4609 bytes .../src/images/simulator/X9LITE/left.png | Bin 17744 -> 12536 bytes .../src/images/simulator/X9LITE/left_exit.png | Bin 16804 -> 12453 bytes .../src/images/simulator/X9LITE/left_menu.png | Bin 17224 -> 12441 bytes .../src/images/simulator/X9LITE/left_page.png | Bin 16873 -> 12439 bytes .../images/simulator/X9LITE/left_scrnshot.png | Bin 17800 -> 12479 bytes .../src/images/simulator/X9LITE/right.png | Bin 19197 -> 10117 bytes .../src/images/simulator/X9LITE/right_ent.png | Bin 18890 -> 11523 bytes companion/src/images/simulator/X9LITE/top.png | Bin 8615 -> 3913 bytes .../simulation/simulateduiwidgetX9LITE.cpp | 21 ++++---- .../src/simulation/simulateduiwidgetX9LITE.ui | 50 +++++++++--------- 12 files changed, 63 insertions(+), 37 deletions(-) create mode 100644 companion/src/images/simulator/X9LITE/Readme.md diff --git a/companion/src/images/simulator/X9LITE/Readme.md b/companion/src/images/simulator/X9LITE/Readme.md new file mode 100644 index 000000000..46b4f4f4b --- /dev/null +++ b/companion/src/images/simulator/X9LITE/Readme.md @@ -0,0 +1,29 @@ + +# X9-Lite skin for the Companion simulator +![X9-Lite Image for Companion](X9-Lite_Companion_image.png "X9-Lite") + +## The different parts of the image + +The image is divided into 4 pieces: top, bottom, left and right. +For the images concerned, there is the version with the activated element and the version without the activated element (such as a button, a rotary encoder, clicking on the rotary encoder). + +| File name | What is this image ? | +|:---------------------|:----------------------------------------------| +| `bottom.png` | central lower band | +| `center_LCD.png` | central LCD 256x128px (useless for simulator) | +| `left.png` | left part with inactive elements | +| `left_exit.png` | left part with the EXIT button activated | +| `left_menu.png` | left part with the MENU button activated | +| `left_page.png` | left part with the PAGE button activated | +| `left_scrnshot.png `| left part with the SCREENSHOT button activated| +| `right_ent.png` | right part with the ENT button activated | +| `right_rotcoder.png` | right part with the Rotary Encoder actuated | +| `right.png` | right part with inactive elements | +| `top.png` | central upper band | +`X9-Lite_Companion_image.png` is the image displayed here. + +When turning the rotary encoder, it is possible to make a motion effect by displaying `right_rotcoder.png` and `right.png`. + +## Software used : +- **Inkscape** : vector drawing software (http://www.inkscape.org/) +- **Gimp** : image editor (http://www.gimp.org/) \ No newline at end of file diff --git a/companion/src/images/simulator/X9LITE/bottom.png b/companion/src/images/simulator/X9LITE/bottom.png index 3f709a449487f743fd35b0575b564584a3ca8bd6..43f26ab49b801821691963d8725a9621e87f7a29 100644 GIT binary patch literal 4609 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 delta 237 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 Hu0mjfNwc7c diff --git a/companion/src/images/simulator/X9LITE/left_exit.png b/companion/src/images/simulator/X9LITE/left_exit.png index 0d7cd5b5b40cd2345b21bb5899dbccc89b0ce7b1..16a7dfda997c5d060503512e11f216adbc23dff5 100644 GIT binary patch literal 12453 zcmV;WFj~)vP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{03ZNKL_t(|+U=ctbX-?`@4vr& z&Y6d1MkC33*p~c~Y{xhxp(HppZb(R)@Jb4yA%TRIk_V6!Xl}TL)s|bXOGC-cT5T3L z7bqc6!mEh`6bk80!v&JifD@dD^Ylx8$+m3C8jVJyd7Q`o-9Kg|&q(t)=gdRWX!csN zephws(<3D>z9t$~<2l0En0b;}BGlAkZ6_L1>n; zMKw+Ei?0lm^9twbU-=(!&L+;^p1+Cb0K|C*=N`%hKr3;rxxezSH|KLM3^C{JQ91Op zo^r>s7HoRs$~DIhj*G(wPR+T+W+?(~RV9aQZe%BivU8>6!W=sXws2di==tP;>+z^a zCroi@|EVU44vJXBy{m(}V%O*6YJcgRb9j6jrsC-)g^r;msvAFCR>oYm5_W!HjB+Z@ zwQHrh=W5yn^K2f}Sy8!C*h`oW&N=1sM(o1xsul;d1TcumS&L^>T%Uz@a%Ah;v}aw> z;lwQ95}$LHTWW$^O=y|HLIBdL4uJDl4{UoEE(@ET(>gi647^LMm{X@Qb>c-NPQ8M3 z^eBw@2&`1hHa#jcTM7w9!m2$qj-3uX58ShjtFrT3V*tcU7hGmc9{nB0_dJTk$(Jj# z@W9S!u2R(MY1_Lo5A?ok|xmw3?wa)I`CadI%a|O0>T?gs$BN%%8Z(%0K zYvVl-L{o}GrRAy<%5_v-E@B#R30t@fu%+&uih$do%o_0#4E^HsH3Jp^gb)-{#6s+< z*wrp<$DXa=R_2)34qsk0vTK$t1IK^$MVN_5O|K&aC?aYJE!XLoYVprDn?VKdVz@yG z9(nHDNJS3T{5mQG#>G4;t(#Y+RW)nN`GdJge^0Y}|Lh9{<{a~vmWW~~K_v!wRHWVTjAKH|!gey}Z7V%k z%-v*}5>wGML|s(&0H#j7P`4Ua1&iZ~s@9mtGz;wfcuoxasR&6CgiUObtWYskbEzUrD#vI71Hl`Ic17${G zaR%Tlyrym;9!(>iH0RuKtt&P)HV7*{Szl;-_OBiq8rVONsB)c5Vs`zS*Uk$==8PSg zG$m9`K+_bE%nZ1QkOejeR-&2Nij;#F=h(S3@Xj&?rcDPuZ6PtKLr)kbzg8{5O^)uV z`zS`;zMaflzrTNhsUFwu`fOvXBbO{Q4BdihNGK{nRh794I}I!4;7YU9eOhT}V4eOg zp{FELQ#y=P`L+L)d*T|D^u)3HLp%Mbi9ictxl+BxZ#Gu?as^#1ONNnVn7RZ6peX{R zh%+inIZ)AD)dtS^dzl%g$uLp|jHETAwDuZNZRh5g@zHsLmdR2TAq-R29J-pHxCYl} zrV5T_unDA12|*G}3_%$mE^^?VW!1tmC8Q-GO@?VOSjw!)fCW{gk(?iBB}-jVg;o`4 z>&hwD{yJ4N3K?>GPz46`?777mHDm@L&)BRpiobwg_p&tR2U-G>iXsB_7Ba3i>FoY^ zwle~+&|G9NFzsK>@fs{xkIe!pBJ=FUgsO;|^0T;XUDVfaRLjzU^BpqK5}#JpMxIGu zsauVgHYE!ZT2&dYiPAOz>lJ~xAo!)mgjTRTr7R|;P zMJ$!nK-j99C-WNswr?l%qu<}xz)HC=8sI8c^@i$ z?+qAlA;&q(Q;I4=O%!i>dtsO++LkTD+VvZXLOQ!>9uG8+ z2fU=wG)E$@uSZ_{YD*>UaGkgs-)z%ru(PiZg#uL{*d~p@r1S zQLRhtdGIE*CHDf%czw?vw03l0THIoRmPnjz?3rHm8MPhQ@oBVs(uhPNNTk!~Te}WkpTDZNqbLfxSFC{Q^W)H= zLs-+-jiG=41f*U&=X}OIfEdy=Q60%yf>Ntb48u%LATc$C&gCoWdUwIrR!mM#LQ@4|`yX%k+L-Yk zNX0s;)g-3Z(kStv7ojK$NC+tNFraM-1YnsK(qsD?{#nmRt7R&Ov?VkUqiXM*4aDL1 z`{(8Rczr%Mu8zeGZQqI`2ZUJU-#&Ua#sXj|AuSW8B@r69yy4vk`IHi~+wO&Gw)6Ze zwcXoYx$PFjCMJ+hOxX@wRE?6FiX$4GKydBbAXMMdF%L4MF|t&pISzB%!j_$TC0bUU zkBNy1B;)l7f0<4skeHf+rG?S6?Jo=T67`qb+i$-ekw^raH*dzJmtKlUB!c(9|NVI2 zfd?=&G=#yyK@1KK!teKEY-|h{UU(rq9uM~H*#p1dkK@NP3G=$TGOxf(LMvJ7>SBAr zK(#-f94PR>)&C1J*o$~9hD2-vENe4sj+v2+Pa-iDM=WV!^;P!)1xQqxv+hzv#>S9{O~6Q}syyg2kc>?r7L8&G z9awwKgAkrzVYuh1<9yLPtjjCMPG$C@tZnsx1Kz0@sc00bcpRp#!!k`sX=OusPUl&Wkd_70(2+_^VQM0Z zspvSOV`GTK(xCqLV(s;hp#AKtZFoNBuk6~j3r{`uRNl6K_=kVMu3fvZYu7GxcW3l* zcz76J`qGzX_W8y)zJZrtei@HH{x}|Z;DOQ&@#7B<{^0oWi4UC|i5GnWTqqd<=LEUn zyq)uRWuA4e{QYuI!lkY;`(j-D8fSK8=iep!hkscx&#s*gEuZ^$-tA<=AkJJj`?pLd zF#5tHh#z_yoIDMMB)lFEh(tEbeI_#w1CW*l-7sKT4ED6ayYkKGIQIik{hfK;=G=S9 zKELd}2*FUOcB@g2Jo=YNj_$4cdHsGrm>H?m8Pn>I-gO=B`O<&OHxD4?iER7>s+ywJ z$s{OysRBC`Jf_foRqA7frv=?xZbbK%8?zu=NR1wXJ{5sAbsAQB3PSNhZRvp0(gAPB zItay+9~s=?^IWVe7m~^1!J6}+RRkUPXzIc;C+Df9AL0H1w>yl7fHpKplCxX)guf}rr zMFZ6|F9ny^%DzK;v@%O_sZJnKC9Q;Z-yr=e<{kQRTn(^7#J zjFhdQ9pn~-Dn3}Mc8!s%ueETMmX-{(6SgMJ)Usteo>%K)Nw}TYw)0fy&EcOzXca*x zm15AknWRlst~^KTO0FcD&=@vtBbI_oZ%K%wno3*ht}VolOvq9z3uZoZy8K|){ak(O4*nL&;g`|nOT*^@ys84PSA%JqNa+@IgE1Tfv}KzRShWSdt_?2j16~@?f^b|b zvy|KoQ57v;$vb$~nVg(ByDv@Kdqo>cHW6}_gf>3(JjP!9F;@5{u)238ykRf6wH3)^ z63Ju|hG8H%m4*-keoaM3YYX~UwLmCQ80klG;+YdTGA7Zo;azAQxU8wPbIk)B@sN;9mThZO!jW=)XhGp%RWcVtNuBJV@z-`h+?aNvz7v|p{|^u%hI4mQCo zc=A%F#%z<&#Ve(W!KX3ut9!6%pdZJM9m7;2iH@#Ltm^D?^|%y8L2I}Tt>HG9hJiyz zj)0i4Y5f`;dHM^OTKgV!oOgYZ@4iG_USqz21FB;4+uEJ)YI`tdcbrcSJrpkHNM=o5 zCuQpR%Q*Ib{~o<7mgA+DUV`HFqIb<2_*(+iQ5j7`XU}qk+B@+2p1oMMtOM!&|Az5b zepI;8Efts7BiE8%^@$=>uX9kLUnN%CmN~J5sl{d@iUU9V?^wBV1r8oMgw_262(^Z5 zQgI%y7kz8j;^e7Q=_vFJUUc^K)EwB{($m|AbUF>0iXb&BRxI%nf)-LHYnn8~?TT4jcCAel!Okgd zGCO(nd4MGni3CF7a9t}=Q51j(9*-CC!%xgoT3$NP5+Pb{{sC3C(a~V6dZvU8wI%1> zYdSUzMN#1M%}*Y$KrjR$1kA)38od;SRw!aftG3eC!gj6Vyx&4*g5B=b8(I!#o=JW& zANIJE5~{yr)@E8d(5gZl@OTs#Ah>jUl~q@pkzmT12zIZX-DcNM8(MQdBm**==%e06 z8U}Pdjo{k1E!}|_lN|JTYO^ZW?TT5d!5x%r0)))`16xm0L15)Mn2g1sr;>H8L_<#_ znM#3tZSZw(UXYHNQl+J(1;RmI=HlK15_`NJmEEad6)1G_8QHrBvZ1WA!F3XVZrxR% zM=EVVPp4s-W_=V^O6Z9MCSx&lzxB?!;xkVmKK9sS7#<$Rkt0WN|NZv^0B*kdX6U+( z<;#}?0D60S@w?ys4m)@5#PQ?D@t*g*2ivx7Lo%71Nkw||%{SYJR#WwtHBHQuGq%E{ z(&VyL6qt+a#3oc*I)5(= zD*)itS6`h;2EBXt?zuf$sf#kRsVTx^n3g@7=6ltFt815@a^`jph8FC^Ss(d6BCq`? zMxOo#T9PSvecsF*TAzRBg+STDJTte}(hcZ_j>*XcTKX?T|CP4`B+5Ucc}Rd4kH;}S zK8{2p0aaCT<&{_Bl1nbZ(9jTWx#bpIcinaP>}NlV?|tukc;%H>U>F9z@|CZ^G)?sP z_s`_Yeel5tao>IS+3y8!{?6XW;NeL7RKh6H_3*6JpJyI+-lkb;LGwQ=k{YyN3eqC! zL5p6q;E88_#6`cK>eZn5)VY_*P3<`=n__;N(ab-wgTKS+7k>mRvLAl02b!jVh(JPQ zezK`XGr4gY%yK4Qu3;ERBvas)6=>b~F0^fW7kGMvn3K+Q=4<5s4M0<@n!#DCG^2$| z;WVSO6-i)B)kJ$~$#SvQr9z1;s>J0!ccQk_o2#Typ>X$KZC~{Hw2ErY zp3|v>SHPuv!jAjPR#1)xnEB6330hU+8J}NecZ8A~dTn2$qC5#jJp|N{HQs3R4@yES z+VE?iN3H)7hHA%2BAfoKLcZW;sL#a(?S1dw5F=4$&WPJp43$JUEJt?9NiufK1ZpU$ zZL~SHWnX!*L~mi%*_*Z`Z<>2|yLw zz2p>Jt`WiYY#7W-6IuZH=WEyhl~+{{uIvd^X4g_JYLpx?YZQRtq&-VoQV?(Bx;EUUJ5%!K?6 zO!I_W6;H^Zr420rtk|>u^T8G`=7a*RWrRaFySp|Ma+^r=jaWlKyL~&E3_0faYmV*O zx&L(;1et88ZL#}s0B$3UVYmrxrYI02WwScc0+1A!(;5p{6pL0q8*NIkYiNmhR8!q` z;gy;Q<-HK($U#x+?QbIna9gs_3Pnvh_SaU)L?}tD6SXY|E-hAjF#pCIEor0cw2Tay zrZT-O*QtI=Wn3(sc_}|*W6@Q`H7e=I5lkK54Kq0oGdT%qBtWVMinkT2zYX4H>(SD4 zcEyjP(FS4_-3lPA|gJRV0R5`ho` zp->2I#zBn!?4v;U7W8bpqwLV6skCR5RwqTcV$LqN)lu65A3Fk<95*{@>Nxb%zkw%y z7(S1J6DLmCf^_a9Ca9_kRaN2l`@zgeCX|01T_oe z*kM@dI1Iyp-|w&QXj)Za7zR9=irD`DY$|Qh%2Y8@Hlw4{)wFK2(x5^! zp~PW!g?8%1Yfuygs;asUd0$EKdc9CJ4e9a24R6%ChSrjN+>T9Ktx`XaCx(^42wPhGogBdkUO* z6im~AzvrB4_-Yyx+A&}Hs8AH!K@TemxZz4|$@a-gwF|q;ZPbO-nQXwXxsb_M57ZGzx}dZfkGgeOad({ z(6!~Z%FVMXmbbq3t@y<+elhd&$AA3C`07``ipws$49k}<$4`Fp6Rcgk77suCFmAl@ z#=L#6zWVCoy;?=YG8?KYyoMpm^ICG|mfNf}H20O&ocRVe(&fy$u{rY;9JI^TS9}J8 zQ)7sqdKtlB5Hgz!tQJL46r@rqB)J7^uez^zJU2K1uYVqrj&=)p|QY)|0u$5 zm8P5LT`zY4=6sG+|NFj#(dQn)=+1AVy{!$*JTqsuTIxzfh{a-{_DxuO`4_Vdcp>R* zro81XZ^4coI{*M5{NM-idBzN~OTeIC$`2>G4BF z4^N@f9#v^iz_1BL&NM+cGr!8r0O5Qw|o@K*KEs6ZR&QYTkEoU^Jd(A_uT-1AN}Y@ z`1GegjeGCC7tcQXEWY{8Z{i*Act?Gq1!1?}tNuyVo{Jr>?5b_0;8xKXZ0XsA{ttW^ z01(~#D@6DFKUfooL1qF38Z!|901yF5L_t)F$gEJ9R?%rwLP`n4Gy%m23M@xp-8QUx z!eP}rop%S$%G$<>`u!B6NHIS&bjh7<4;q92|(V1byN1;!Sz)Xy1 z7BvPs;R$wuNy$kPjYYStHX4oMx#ynC+cq>bH1qc>ue>q?^R(IY!V53d7Fwm1e&aK% zoE)ztQ*%FbVkS6~^!gPo*abDvHDe|qC!2UxN`tMpsmM=z-@7-&7{rQjo;IeMIl#&) zW5H>Oc6_)Ctfr~%2R0tGnN}>veMMq=xqf~XWn3h8;1+5t3%WaAx?w>phE^5IivcIl zmZqq3wJr5QDR2uM#?5fC4XU&xeh~_K*$uDmr;t0%Z(AH(D%*e-QK3>sZ4=s=Vg&T> z1OlEKR6sTI+uEyKnr$Nxa)Ny{OT$6?t@myk76PWnY1SJDS!t+*n?ag7tn?J5sbfye zYa)l>&Ta*bqEL<1_|&SLg~k40(7QP@o~*&c&Id;tDWoDNp+`@_OeZpLj)VZR6H^pl z3%qST@U|_7(7Y(=*D4w{Y5p>hFAy(WgWI$KG!+lEwfWd>HQ7;HHVwp&?Zx=sok)xv zftj8Hz+jeO%LKCoz_3zNNRAvvbl*-)o!AeS1{?)ZM(zu-rg_k?(5kKc<<@}DxiZ-d zyJ#jS5!t&FsmMvNlmJ_$gtSb1=%u`9a??d&=i;s?vxTi6A!MT?bA zVB+9zu(akNXX@q8OT^R3`hwugOK?Vl=;a7 zyQ#!jX%55+mZ0X{jyC?}(c=@4l3hL6{E0M-i9@>!t1AIQ5FYru8=&T_iPB9AH~;PT zQ0QelOAC`nUq*QS1#{!p*0GLR^30q90w4&;L`)TV=2fAIW*NXGq{Xl#U|DSQ$#N6g zLgn6TS4BSh{e4H;TD@x{(Nx7l=G6EIq@F%AXM}-Ziw7hC!?5tF4_<`xHular)yJ;c zhOh7V4K$Am$-q=1tFFwj^aS+SX?R*Y%Y$1*mlrdGt;|FiLC6MBKJ$CpQ$fXieA6?% zz+hIu*;=zK3Db};OxbXG73u;l0BDM`y{9YqFOg`r*s_o~bua^Mp-ABcx^By`AXLSb z`-_>uW=2^RB9O?gKqvq%Wyz&d=bFxI#taES2nDJt;9)>d8!+_3@HP{Llqg^Q;J|~o zesAynEq>LLNSdzI*3y$;GoAO;x4dx;F1>JL-XYJuHiU;Cdme{RjA7l%PTX+i`8aoD zFE$UX005l5egz)*(bL#-aAXEenNC3(>5LC|`gL!qN!84dh6M;fD8hEgBWYTIHN8wG z^OFng9B^~hmWl(LS>Zqs%$T+`1OvjSLGwr$X$yLq^A=N*Xe?-}{&h&G|9i#q)(YA- z!HAvC>m!K(WmeSjpFQyk{>T6MIo@{u0KWLCtMJx0ufu2m>8JS5r(e%+mC7u~6%mYh zq<{@erJY7H1Fxl`9z2T!7ZRo4u#(`Cb& zF7)-ZW8aaHGUrbgb`p>s)h(dHoOv@R1fX~o2u(m}1SkX+fF&3v0D~C@OQbD{lqKN{ zdEgIv5Q`--F_AzlmPBkag~`bj;_)=%@ieC5X-viS%wzmK2|MmPJ z*7bJcn_svAYgcxZF+nA?U`J8gpzKgAcaj7;z<~>ga@TzcXn`=o{eLjmWrgya9DHp1VfXfi z;UU7SyN@k;a8EsRKgM7GSzWGGmlu3ryJ6##f|Q5Xt!j5v-)#fuffN<_3l4?-pBzkt zq9U~BjrQ7Y85ty(KaE^E-}E6UzHs9}3jp`uu;D|YfHvCGWj~>@(7b3{{|6wURFLL~ zK#Gdi{x?CW8j8lLZ}dLA#zpal(6i;%#)1|AQZjkYik^@e3fh15r?#}BWAhdW)mzdH zR**R%pm=@gIBN@3f3OUvR36@H0oc0$h|-i|=;`L$K`dVi_s ze)Q%27k=O`sI}F9aU_zkJpqYGz!PeRzq1dD#|LRy*>z(K5+V}>QBk1<+tAXp2BB4N zfEMZi%?gfZUtk>&=F*UD4f&uDVf0k2VW1@v2(9@;q{a@ym>gcb-h)ErW8XipV=Ad% zvv2UUvzc>z=8w#4d)rfcprLU!dA;Hp0Q-j!i^2o2#qnDeBhiBr#h1JOPI zvAE5H{DIl}YkfXt?^=f*g*i#+OR=+_d19LdH44MuvJ0-Ms8~U&Q8kW8BPa(AGWM`lE zr+Md&p^li5JaKer!aE*y7*;7~>LA&w- zq)s1j{a_b_1pN7qL+9#-@xtqSM@3q<975{`TohgHS97yA=ZW{O48sfHl_dgg9>A#y zBu>2wJvszEb{x`3L7K_M11$jD^4-0s29Jz)$Kwv)UsnQd5!H3gCOdnwy(`1;fbr_? z<7k#eV$;rPL2lx~mWp0y$1bhr%PEnaAapr;4=+j(_w7+$a98eDP(F4gU2 z*n;cg7NcikA>GW!es-c$#1sEyn(~9XX{jei;}ngi?1x#J?ZdU%-wQ$T`<&0xXly(Q!?fHD&I)V@ z1Uy)`rX9ck&0yWXpU10W{Tq4^YV{+X)U(0m7}AokB+tZHFmwwnB@BZBWMX)M8HSnt zoy`Pq8WxxtrkRP1?qvRQ6WSV-KmXSQ7n+jqmMs5BH>DUo9T(%{X_$r9pE&?G18p0g zePVBAkA~duOayrS9wsw_3F0f!iKB@IF)W=K*sGg6=dWI^!IP{!%I&%5uaj-v!H?emp^e|F#&BBKVlm0)}5oDIb~WIz)jr*gUB#4@iGkE1Q=u(63h~o$+cf2R;%*Q zA6)+v06zhMPyAs2ds|j&pI+G$+GkN)az6WzIEs3T>_FnMK&710jM@&ihz3QL2+U6P2%LQkdvP!|9&bGvDB z3xh+87TVnMmFqYB6u?gb;A217yRoaI<>rod-_@t61vXW0GV?kQWZe}lPm!( zm6Fq{^;bns)L_osd#_y;0T6L}yov@Z_g{b3J^+7}{mHn}b_}lasaAin>BB6!`IOB33HU2svGmS$^St>+n0(>!QGYu9^VxRuwc zS-1s@Y$|ON+JZvMkcDhosy>)bPuVmNn$S8M@No6d>GYIB6%e3gvwpJAqxlE`mWT^g zS+Mu#@%vyZRx>z46WSaoOzXGdWy{EYwDB4a$w(j&ZlejDwX<1MO=xGzeIMR%oP>CN z>wDkJ!S?nAb#DW2J`Yk_!;f4`db6gQHf>&6bM&0^v;pl0%li7R6hiSi$!%9NMair~ jobY*D|EO6*XUhKv?gbD3$4x{p00000NkvXXu0mjfH%ioY literal 16804 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 diff --git a/companion/src/images/simulator/X9LITE/left_menu.png b/companion/src/images/simulator/X9LITE/left_menu.png index b97ba1da4e1cf9c131a1ee43c44aaf61cb3cabdc..db1cbd768141ad25dfb5a3542b9cfefb98a799ec 100644 GIT binary patch literal 12441 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 XTn*4bGRA1^00000NkvXXu0mjfo=(-# literal 17224 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

-`${ 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 V>t({inE3zz002ovPDHLkV1mA7)}H_X literal 16873 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 G*#7~ZB1)S)~8~02y>e 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 JPDHLkV1mfT+#CP^ literal 17800 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

9)OFKScV6APdgS3J|_~r%o zr1gJp+Y>Auw{^#yTlbN$k?}~NmiXuG-qfp{z!#W+S{x)CMlp3FB102IG1B&RC7PjM z+?#PY23~#AUsBBRHvMlPCfuHJO<8w!}8TyymE>I}9yM#t&*X4-s+Q;Fi_RZa5%?N z;W3o>N1zhLF!#J*I%FUTL53diV;FNZ!+=N;V|sq<7w2-W7YeV zX_V^fetz&D&tRO5(B3QDjRv{%70@6Odp{Tp05Ev??%n^H@tlO0t(2I947QN6VEAO{ z3l{aCSv286X4{4QswV8$r`v%qB!S2ovj`*vZKc8GwPD5y$Vh>>8^y1V2~J@R6ou>U?if|Zs2)Y6gK1-SjHYx*jT;+XuGG*Caabs)X*1|bG9hBL z5$j$Q#7{SQ@n@-2^1bf_f-7cagP0QNq`Wy=^?tlUgu=v?>5Sq(qp=P*dxVGMh$`I+ z6OwgeB7&f&O9_Ad`h`;8vFzJykrzZE3oO-Xa%$>7w*(zwu;pI!_zDE{F!V(bI@#D* zWo`A3_X+gKYWFSe?k5o$20lNR-loG4q_`XfM8UxWd;RD79hb{rNXYKX@{|lTBKkt% zcXEBtgT-iHSmk#hsa|R1%*<$#l9E&fMp^EwK0@bR_oo~Ba_%#WcsM5Wb2uimcqhiF zbySwuAF0EPo?Gmb%y}tasdJSiF$!r+PM7MXUhMaqtRDoR!glh$11Eg*f4+Qe-6Z$? zi3va;f!DvYhfDPoX8Fo@`fVpV2-5Dg-&A5aZ5Kd6w0;BBUe{q}pJ{?z+uhlHqQ60p zyEAOhRn6Ble$}MjZ~AQD9`QV;wH$x4D4uSPJyJnm@DVX6h+(H7l2|Mfl?Vj#y+7?+ zH65YaebV4rbFf=(LZDA)99a2Czvc4da+ts|Xjp6Ist!}>cWZrq^KCo^)fK}XpYD=t z7>YMJFUB@u4Bvd^t;G_v@QZkxp=@(9DNI8gWNb`IaMX$nW^`<I{}RdKvM)nQd6cXFEJ=mdPHKMLo&+GpP@h& z3V8`DrD;zk{rJ0}cJ} zw3n`Xgijd$9xXEO-)c2E75ua=OzS`LFkPI?S*o`uxI5S@uwAS39pp*jalnt3KjsLm;ON7G-Y zWtt9;^Du^S1Uxy#5^Thhwx{FD^C{V*!29MV+)WKt`NAFHSA-=x?0)oCRwHLCw5QPV)4 zkrJ}H<|FcwYOOB4+@QzDM_|H|4K%WSb_WDS{8fO`e7rxALXxGWEW>)fzOJ*svGB6B zaT@xlDS{r>MitCfx8M5m^77j$QhiLtz6R0a0z>R~gSnjeb>Ds$x5cy=m3))S(GZ!a zWKp-C1w<0DftIX@=w}6Mk~=4h)o)Ueh=M}=Ssf}hRtQZ$2{?c2H`(slMtoHj10dy6 zltSnTmsaWN>5-BZ1@^RT!yx>;c1}Zo(56%|J+4n+71DkOH;RoduB?Fz9P#?u@-h*ry(v}Es9x&e#F1d_A zuYAhizkj2S)4uSKeRSv;yf7+XR;pcd(HIj_&D` z){=qh`#+f|-X8w@;pj;S4R9VzxJXo}AXc09iFMb`d?2{}h{F#?r{UlsO8c4oJFw!s zx?PW{2rupeV|Z$GNhveC+{uFwtx{(%@ybg8$Zg-2m!&p7jc>CpJie!mUx=}MC)3Gx z9>xm_Sc~2nIq{1Y^tl^MB5;U$dYS&SgC>m3uhl{tQ-1rXq@e;WTcLaq1nHl=j!z?9 zMhEH!VOCWCJv*AA>uywvr;vXLA%OYmW16gJm4PvK(eadJ`y0^BUGwDDnd*cDpfiiD z#fcpNB@@buBGVUAdBU(+A&0Ye(+hLkt*HNS-}Ck{9nh1?V?tI|bmn}zcuuMsS#0LY zGZ)DS$ptk#tYDunb|Wgll?DV4qJtcI99CN*vot5uZ!7jYrZU?JzZO)Tmew?>E4elF z^V9HexTRCVn27kLI%}Wa$YU&#dL=L+tJe{#P>SV;<^#MKol4eVc`hQk>&B4Q*3*{8 z_efO2-WQSp7K@nDb`&FI8PQOf#;|c|5a(31Q4Wb{i4Od+?f-iLu$9!!%q@2ke9!xS zboq#;o44uL@Hw{B+Z2!;lt2)JtxO|;%0W`AB^q(y7Sx=VK%e5+8hhbdBb$9|nsMlE zn1C>nii&D|q(Y4y#d1)-|45H%-lkz|u`Q{5N&SFw}$noa+wbYwdq{7=8HZCdp zr)f2X#z^2tzflQn$>P#tk+kAAAM-R7HFb47`%d7<>XjN)&1-7;V{C+|@BxeMoS^FQ zqRophDlTk#K1DvATNRLhaJ3KRlMKXurkI9I!uG%4nBE@PCL7Rz` zkuU%Th6bIk)WZn%kT^JKEqjToV-K98IO7^|RnlOi#5{e7JPDD23O$No zowQ6@sSvjzwg^f7nnDSbmPUSg{3#e^^SD?;=-EUAbQ?bRbL8mnm}98oktnfpq3`Md zI4=5jpBUxun*QUFs>}6cqLK9W{y{q|Yi$K>DURdX z&gW@t`}R>cagH)QJ0;{3qYkARgK^|+bSONU$w-SmC}^UJL667DNG#<`QTXDHsEP{a z2YnX=mD!og*+k(&pyt=X2;VE+e&~0%3_}0=;(jS%DmLuZ6Sj3YUBpW9&7JkL^R+>- zdQ7;gZfBaj+}Du{omNHg5v;O=j5F&(jZS#qKm-{*HT=Q-d3<&@VVb7e(u#+#$Hj12 zD%DUYlR6g+FjZq#j%|QS!k>NNSA-xgJDuK(FA)kjJzC-mXA=&Bz7d^nLY@7mp5h%x z7mt7zxX;EKHi#8pmZm=%mQ0)74i~gwzk-|EJw%W)8-2FgvYpXv>wHD>9+eJIjB9{H z29_y?&q`(en+_d+17NNq$_k+sBVi8ij>F#ooof{+t<^aY5juF*naUGx-#?0gMO%pl z%n6w5{^8xIeCzBBI2 z<^`kztHpYXCqpl?m6x~sB&?)a98{!VP6OQ=Rb8_;3;n9Zv;Z1+t;{4AzPnVmKXpfGPFwyCtnh+A9wg9@xHfoNq zuBsj%UQ!vVQuJjh;cQi*csJuik2)qHqln2ytTlW{%B0Q6RW;TMSwVCL5ub;|iAJ?k zVH=MLl4#YI6Q8oGdN^<~cdAe@7d+k7WrT{+k~COSkpI z7Z+&xPLLRT!U+NnFS2E`ZDiw0i=?qKMm7Q|5s0#^WLsJks{5M& z9#CS!b=iq;d%Rl(0#>#n^+L4)%Fn%!fwP1o_t)m;at5XkP)Wem`TBlCg8VQ*lJq?L z)$1*qS_I0>8E^6`V)G!BVZ7~n#TF`4m#FHFFyAs3%YV*W%xQNN18~s5mYp|o5Dr31 z>Bi;wTioZN;p+AkZ(OXlNFFp!E%;bUCc9wM7h9N-0t^Ui!y6vE_cwv#AkqDLWZIls zaY>2sEkwPXi8+#=vw8ZLQVhd@ssU==2+YrIkqp<#KKNAXBDuvHtsi!H=N+#e4}Lj_NVfB(eRHh#1nhne5u zei7;>Ul^-nE2QaH)sL_K&Rw*!Q?Z!z7!O4TtC)c#`6cnsVzn+AJoKUGcKD(9+vDiu zWCSD;*FaATY-nF?G1u^*mIi+CyHr!_Rn(q85ns6AUjMY`gW?!;MKa@`6 zck*#u?@fOY$hM=RUxwGBw%!4z>Lud#L?Ho(ImqPmm9)C|kDOc%iQ4=gFuxYPiT=CS zigrSufFWQ{l!8(-%Pxo z`3DaAPHy`z?#2HzABe?)6D5Gv$us2?q=3;xBZ|?zXdjOX{guZKU)ysDje5EY4}_eC zDFOBZy8pH%jLForho9Cvl1n@j5FcKXKEk<>1_fLz7+iIRAVLy5?d?C!#$+`rd;PgRUPSvBy$k|`^jNvJPN2zPt-pP{ zoL?{*xjVzX{S*6dwXOkIr0u%>#A)`db*FUIaijncv;A)@PS=}};P1}{03@uep@XQM zzU}fODJwlLYKZ4^e-e4) zdq14J-eF3YdjgZOijpxNemo{yWl#^T%VpoMZNK^_i%i^U-hHtEh&EQM-Tre2rWtdAl*n$O$yP@#1}MFA%iXhzY3#(r0ga+5UB{p4B@{gDU!mfsn^>9 zWvA2dQpzCQ1$DNNULA!{-^`f3(6BnkoH_?nSXW?8{K>MddppQ;zTD~yEB?C_f)1?w zpwg0p(sq3QfY*;5p67$qSk&Yc>{zcKkVQr&bEaGTeRrFzpa2L(DHBrGj&EL4vXqyX z*wx`_x(-pNnNtmrP?nJO;hSM&`;(ibjRP%2(n*X~Lo9%MaDQa#;JpPNIpqtLkRXWE zB8B~@MO$lYOOpyRr7%^M?iXhi(l|vGRy+ZB9P|w2L%F-~6lPy$I#8@+Smb8%a6GoiJ(0)Ea;fQ# zepO_&s9NAkFU8dm`$YC75d8M3LP|%6BBL}p46~P$Q5X_W6iyh3L^Yl|UkBDrLM8mt zP3MhMbFRH{cp(k$`*{a|iv%M!eg0S473}c*KBgD2_ut{~3asvzzp70uvtKqjignw6uLdd4at2zQ3rj81`*NN8n`;>yXO9hQ{|CT@ zI}V#Uv(5D9{+FV~mS$lL)=yEVk*LHHiw^6T=V1s=uFiw!f<9Y02v|-|?*U4($vLT^ z@WcVQ+S=OalGAQAs~4SEugsmlwZ6uiUc6=<+o)-36gs}YJrKAOXQGtJwFNQQ(xuDr z*Er{)+aD`QDqjNnxfOooH?g3K9Kr4sCS>_5o)(lKd~lG{%p|x{qVD#=C9wV3;dG-O zhP~&VxS5mFiJF@GPCrbt_hRJ4=Kz;qN%pGW@IB@mP$sVpd?wiNdvz}^Dck8n6Y2#( z`_LaiQRdyhED$esMQuMMXV7i}=lTCt);kX-+qy66EQV#A-0BY|2h2*KUgChnz2xKaR5taf)Xiy>b3`80u!OOM_TEu~_Q?IWV zhx27<(9O-4pS@&1)62@qULMOaZ{P7>4Cco&_1ijjM~}rIcHS@OQa2k2U~5YqUG0#9 zgmT&7ECH8tn$r{cxJ!~(XILoLU{86g5OCH0tUC707Z-fqB5|a}Npr)9vNRD=ZEnx{ z*e}fwU2}sPQo){PbLJ<3o|K-OpgEE-1PJMI`uv_^fNb_R4O0RG=KV4<=?u`4fhg%% z#jM)^yZL$`>~#@}1_HI}1^Tb;M^!TeNZ45!1Ay`ueh*|%XoObe-}SvD%(t0(v4Ly? zWvGxF2b3PGk!@|^Og4tcLKnR;>+S0LDQ$S&DmOc1RKTBPGJ1!%8JOst{tfeBA~SgPOTr+)J`#9t6v;)^ zKYo^!1V6k!Jb!omvye;?N`|4$RjezL;UqtH#hV-^_v^`h1oZ{T%sN(ZEER@`HOi#J zTT{5|a?KUNd9iAh4R*M>3k8%*T%w-8!dZ@#*M08>Gd(wl8WV+L0Cr8vNKaoncmt$o zz>nabE~ltC{C#KG_;IEL*KJy|?PSB3bq}zbX(UF7sAH!Q@_*==inKKJ!$1?h3M=5+ z6A?*u;M>kD-kGNZvsz4&g^`kuXR;VW?~3$ZYAkn4w8YvLaY<_BS4wcr*5_-c{Mb-S zx2K;NITaD-f4D|F0HD|4(*4E&;D0Ct@@6wNnb*tl;WU8crvz`YsetQcnHxxa;C7OJ z>BBM_3{pI_zD*Rm#m@EKh8u`L8f}Vz)camn(EXTjs;cG0jXKc94|8$zMn zl3noU1hd5Bl)IB`pHQp)GyY!Y>j*Ed#-I9k977L0q1PwdCi_Ly+-sMjP#JQknzMB(9dh3}Vl&llhOX`(|m55%2~$$%*_1wKGT`V;#IZHXs+Lj+pmRXFeXCih{F)SuY|CgP?TT;5&bg> z$}cgf)=B&qZQfEJsI4`FuFIjox6m)=Kj6JPJjEA$hq$Fq`Lh)}g)HLEx~GJmzz(eh z%w11(RBtzVOAXdoAO*gjmzSGNE>EUh-z&+ufZO>GhCSVv8k$8_#jt?OB+@V-8W0HJ z5Xx5VV+wJPc3nt~mb@m?v9!D-utg;>sAFPT1Ny`AyGFuQK!ZaOv9N$K%fM^hAySV?IGT4E>+twsKNCGHe(i+E*Zc=_BCuV;$vKdEcYMUYIxn zsDJGIkzk!l*Za1=G4%4r7z5S-H2LEqrHX^lQrVFB3`E4iWQs2#8;ld$ zBB$KOa^~9FU8@4fD%SL%wv9g_`Rmx@Q;9}Z*OXKeu@tN$66xlCf8Ul0OQ9Lvx7Dd26|(ehr_-K4}I%-&M9Dm$wovuM1{T4qs>4;PH;-06vdVV zjA3}}mcPV$FSvQ}gMKvAB$NJEQgYjEr{$P#Ls5mLjJ!cOj|oPZfueGrbUBIR5`8VO z9s;K`>4aGld&5#EkVNu-{-^p<3knKo0NE4LNjU!`A3oJ{jY#Z&ObcSkYQh%e=*LR% zu4I4;?Se`7VUoq9RF-gXVA>!N-k58Qr6#HrFBF9w(;ijXq

OAP%Cju~zPUMr~Ya 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 diff --git a/companion/src/images/simulator/X9LITE/right_ent.png b/companion/src/images/simulator/X9LITE/right_ent.png index 3292fb0e54f791f8339e8a2354d108814a704a48..1640129f8b37bae00b98539f63a003f5582418e9 100644 GIT binary patch literal 11523 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 diff --git a/companion/src/images/simulator/X9LITE/top.png b/companion/src/images/simulator/X9LITE/top.png index 427ee09119beca5a0de1ec7c645da58cf731f9f3..bd15db2b7e0e42f0d67ea97a145fa071d093df1f 100644 GIT binary patch literal 3913 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 diff --git a/companion/src/simulation/simulateduiwidgetX9LITE.cpp b/companion/src/simulation/simulateduiwidgetX9LITE.cpp index 640945bcf..6941a308d 100644 --- a/companion/src/simulation/simulateduiwidgetX9LITE.cpp +++ b/companion/src/simulation/simulateduiwidgetX9LITE.cpp @@ -8,24 +8,21 @@ SimulatedUIWidgetX9LITE::SimulatedUIWidgetX9LITE(SimulatorInterface *simulator, ui(new Ui::SimulatedUIWidgetX9LITE) { RadioUiAction * act; - QPolygon polygon; ui->setupUi(this); // add actions in order of appearance on the help menu QPoint ctr(70, 91); - polygon << polyArc(ctr.x(), ctr.y(), 50, -90, 90) << polyArc(ctr.x(), ctr.y(), 22, -90, 90); + act = new RadioUiAction(0, QList() << Qt::Key_PageUp << Qt::Key_Up, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU_ICN); - addRadioWidget(ui->leftbuttons->addArea(polyArc(ctr.x(), ctr.y(), 20), "X9LITE/left_menu.png", act)); + addRadioWidget(ui->leftbuttons->addArea(QRect(80, 20, 40, 35), "X9LITE/left_menu.png", act)); act = new RadioUiAction(3, QList() << Qt::Key_PageDown << Qt::Key_Down, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE); - addRadioWidget(ui->leftbuttons->addArea(polygon, "X9LITE/left_page.png", act)); + addRadioWidget(ui->leftbuttons->addArea(QRect(80, 65, 40, 35), "X9LITE/left_page.png", act)); - polygon.clear(); - polygon << polyArc(ctr.x(), ctr.y(), 50, 90, 270) << polyArc(ctr.x(), ctr.y(), 22, 90, 270); act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT); - addRadioWidget(ui->leftbuttons->addArea(polygon, "X9LITE/left_exit.png", act)); + addRadioWidget(ui->leftbuttons->addArea(QRect(80, 130, 40, 35), "X9LITE/left_exit.png", act)); m_scrollUpAction = new RadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Equal << Qt::Key_Left, SIMU_STR_HLP_KEYS_GO_LFT, SIMU_STR_HLP_ACT_ROT_LFT); m_scrollDnAction = new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Right, SIMU_STR_HLP_KEYS_GO_RGT, SIMU_STR_HLP_ACT_ROT_RGT); @@ -34,7 +31,7 @@ SimulatedUIWidgetX9LITE::SimulatedUIWidgetX9LITE(SimulatorInterface *simulator, m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); addRadioWidget(ui->rightbuttons->addArea(polyArc(88, 92, 33), "X9LITE/right_ent.png", m_mouseMidClickAction)); - addRadioWidget(ui->leftbuttons->addArea(QRect(9, 154, 30, 30), "X9LITE/left_scrnshot.png", m_screenshotAction)); + addRadioWidget(ui->leftbuttons->addArea(QRect(30, 154, 30, 30), "X9LITE/left_scrnshot.png", m_screenshotAction)); m_backlightColors << QColor(215, 243, 255); // X9LITE Blue m_backlightColors << QColor(166,247,159); @@ -45,10 +42,10 @@ SimulatedUIWidgetX9LITE::SimulatedUIWidgetX9LITE(SimulatorInterface *simulator, setLcd(ui->lcd); QString css = "#radioUiWidget {" - "background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1," - "stop:0 rgba(255, 255, 255, 255)," - "stop:0.757062 rgba(241, 238, 238, 255)," - "stop:1 rgba(247, 245, 245, 255));" + "background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1," + "stop:0 rgba(255, 255, 255, 255)," + "stop:0.757062 rgba(241, 238, 238, 255)," + "stop:1 rgba(247, 245, 245, 255));" "}"; QTimer * tim = new QTimer(this); diff --git a/companion/src/simulation/simulateduiwidgetX9LITE.ui b/companion/src/simulation/simulateduiwidgetX9LITE.ui index 94dbaa08b..4432f8ae3 100644 --- a/companion/src/simulation/simulateduiwidgetX9LITE.ui +++ b/companion/src/simulation/simulateduiwidgetX9LITE.ui @@ -6,7 +6,7 @@ 0 0 - 570 + 650 208 @@ -18,14 +18,14 @@ - 570 - 208 + 603 + 235 - 570 - 208 + 603 + 240 @@ -60,14 +60,14 @@ - 157 - 186 + 173 + 210 - 157 - 186 + 173 + 210 @@ -85,14 +85,14 @@ - 256 - 128 + 602 + 129 - 424 - 128 + 602 + 129 @@ -110,14 +110,14 @@ - 157 - 186 + 174 + 210 - 157 - 186 + 174 + 210 @@ -135,14 +135,14 @@ - 256 - 48 + 258 + 35 - 256 - 48 + 258 + 35 @@ -160,14 +160,14 @@ - 256 - 10 + 258 + 46 - 256 - 10 + 258 + 46 From 35425c9ffd0a9591987a63e3ec3c1badd3dbcd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Charpentier?= Date: Wed, 25 Sep 2019 18:01:00 +0200 Subject: [PATCH 039/257] Lapin fou/fr translation otx 230 (#6828) * Initial version. * Updated French translation. --- companion/src/translations/companion_fr.ts | 538 +++++++-------------- 1 file changed, 174 insertions(+), 364 deletions(-) diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index dad20a00a..90dd8e36b 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -95,7 +95,7 @@ Edit Settings - Éditer les réglages + Éditer les paramètres @@ -197,7 +197,7 @@ Manche Droit: Profondeur, Direction The profile specific folder, if set, will override general Backup folder - Dossier de sauvegarde spécifique au profil courant, si défini remplace le réglage de l'application + Dossier de sauvegarde spécifique au profil courant, si défini remplace le paramètre de l'application @@ -207,12 +207,12 @@ Manche Droit: Profondeur, Direction If set it will override the application general setting - Si défini, remplace le réglage de l'application pour ce profil + Si défini, remplace le paramètre de l'application pour ce profil if set, will override general backup enable - Si défini, remplace le réglage de l'application pour ce profil + Si défini, remplace le paramètre de l'application pour ce profil @@ -362,7 +362,7 @@ Manche Droit: Profondeur, Direction Releases (stable) - Officielle (stable) + Officiel (stable) @@ -407,7 +407,7 @@ Manche Droit: Profondeur, Direction Other Settings - Autres réglages + Autres paramètres @@ -422,7 +422,7 @@ Manche Droit: Profondeur, Direction Application Settings - Réglages de l'application + Paramètres de l'application @@ -438,7 +438,7 @@ Manche Droit: Profondeur, Direction Enable automatic backup before writing firmware - Sauvegarder les réglages et modèles automatiquement lors des transferts + Sauvegarder les paramètres et modèles automatiquement lors des transferts @@ -649,12 +649,12 @@ Manche Droit: Profondeur, Direction AVAILABLE: Radio settings of unknown age - DISPONIBLE: Réglages enregistrés à une date inconnue + DISPONIBLE: Paramètres enregistrés à une date inconnue AVAILABLE: Radio settings stored %1 - DISPONIBLE: Réglages enregistrés le %1 + DISPONIBLE: Paramètres enregistrés le %1 @@ -665,7 +665,7 @@ Manche Droit: Profondeur, Direction Select your Models and Settings backup folder - Sélectionner le dossier dans lequel une sauvegarde des réglages et modèles sera placée automatiquement lors de chaque opération + Sélectionner le dossier dans lequel une sauvegarde des paramètres et modèles sera placée automatiquement lors de chaque opération @@ -1030,7 +1030,7 @@ Manche Droit: Profondeur, Direction Application Settings - Réglages de l'application + Paramètres de l'application @@ -1040,7 +1040,7 @@ Manche Droit: Profondeur, Direction Radio and Models settings - Réglages Radio et Modèles + Paramètres Radio et Modèles @@ -2029,48 +2029,48 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Erreur de conversion du champ %1 - + Switch Interrupteur - + Switch L'interrupteur - + cannot be exported on this board! n'est pas supporté sur cette carte ! - + Source - + Source %1 cannot be exported on this board! La source %1 n'est pas supportée sur cette plateforme ! - + OpenTX only accepts %1 points in all curves OpenTX n'accepte que %1 points au maximum entre toutes les courbes - + OpenTx only accepts %1 points in all curves OpenTX n'accepte que %1 points au maximum entre toutes les courbes - - + + OpenTX on this board doesn't accept this function OpenTX ne supporte pas cette fonction sur cette carte - + OpenTX doesn't accept this radio protocol OpenTX ne supporte pas ce protocole radio @@ -2079,25 +2079,21 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import DebugOutput - Debug Output Sortie débogage - <html><head/><body><p>Enable or disable the filter. If the button won't stay enabled, it is likely there is a syntax error in the Regular Expression entered.</p></body></html> <html><head/><body><p>Activer ou désactiver le filtre. Si le bouton ne reste pas actif, c'est qu'il y a probablement une erreur dans la <i>Regular Expression</i>.</p></body></html> - Filter: Filtre: - <html><head/><body><p>Enter filter text here. Click the help/info button for details about using the filter. </p><p> To <b>remove a remembered entry</b> from the filter list, first choose it, and then press <code>Shift-Delete</code> (or <code>Shift-Backspace</code>) key combination.</p></body></html> <html><head/><body><p>Entrer le filtre ici. Cliquer sur le bouton d'aide/info pour plus de détails sur l'utilisation du filtre. </p><p> @@ -2105,61 +2101,51 @@ Pour <b>retirer un filtre de l'historique</b>, sélectionnez-le - Buffer: Tampon: - Number of lines to keep in display. Nombre de lignes du tampon. - Filter &Help Filtre &Aide - Show information about using the filter. Affiche les informations concernant l'usage du filtre. - Word &Wrap Renvoi &Ligne - Toggle word wrapping on/off. Retour automatique à la ligne on/off. - &Clear &Effacer - Clear the output window of all text. Effacer tout le texte dans la fenêtre de sortie. - Enable &Filter Activer &Filtre - Turn the filter on/off. Basculer le filtre on/off. @@ -2553,37 +2539,37 @@ Si vide, la ligne est toujours active. Source Folder: - Dosssier Source: + Dosssier "Local": Destination Folder: - Dossier Destination: + Dossier "Radio": %1%2 Both directions, to destination folder first - %1%2 Bidirectionnel, en commençant par le dossier Destination + %1%2 Bidirectionnel, en commençant par "Radio" %1%2 Both directions, to source folder first - %1%2 Bidirectionnel, en commençant par le dossier Source + %1%2 Bidirectionnel, en commençant par "Local" %1 Only from source folder to destination folder - %1 Uniquement du dossier Source vers le dossier Destination + %1 Uniquement de "Local" vers "Radio" %1 Only from destination folder to source folder - %1 Uniquement du dossier Destination vers le dossier Source + %1 Uniquement de "Radio" vers "Local" How to handle overwriting files which already exist in the destination folder. - Comment gérer l'écrasement des fichiers qui existent déjà dans le dossier Destination. + Comment gérer l'écrasement des fichiers qui existent déjà dans le dossier de destination. @@ -2805,17 +2791,17 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Source folder not found. - Dossier Source non trouvé. + Dosssier "Local" non trouvé. Destination folder not found. - Dossier Destination non trouvé. + Dosssier "Radio" non trouvé. Source and destination folders are the same. - Les dossiers Source et Destination sont les mêmes. + Les dossiers "Local" et "Radio" sont les mêmes. @@ -3143,7 +3129,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Write Models and Settings to Radio - Transférer les réglages et modèles vers la radio + Transférer les paramètres et modèles vers la radio @@ -3158,7 +3144,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Allows Companion to write to older version of the firmware - Permet à Companion de transférer des réglages à une ancienne version de firmware + Permet à Companion de transférer des paramètres à une ancienne version de firmware @@ -3173,7 +3159,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Backup before Write - Sauvegarder les réglages actuels avant d'écrire + Sauvegarder les paramètres actuels avant d'écrire @@ -3218,12 +3204,12 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Wrong radio calibration data in profile, Settings not patched - Données de calibration incorrectes dans le profil, les réglages ne seront pas transférés + Données de calibration incorrectes dans le profil, les paramètres ne seront pas transférés Wrong radio setting data in profile, Settings not patched - Données de configuration incorrectes dans le profil, les réglages ne seront pas transférés + Données de configuration incorrectes dans le profil, les paramètres ne seront pas transférés @@ -3252,7 +3238,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Cannot check Models and Settings compatibility! Continue anyway? - Impossible de vérifier la compatibilité des réglages et modèles ! Continuer quand même ? + Impossible de vérifier la compatibilité des paramètres et modèles ! Continuer quand même ? @@ -3305,7 +3291,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Allows Companion to write to older version of the firmware - Permet à Companion de transférer des réglages à une ancienne version de firmware + Permet à Companion de transférer des paramètres à une ancienne version de firmware @@ -3315,7 +3301,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Backup and restore Models and Settings - Sauvegarder et restaurer les réglages et modèles + Sauvegarder et restaurer les paramètres et modèles @@ -3411,7 +3397,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Cannot convert Models and Settings for use with this firmware, original data will be used - Impossible de convertir les réglages et modèles pour ce firmware, les données originales vont être utilisées + Impossible de convertir les paramètres et modèles pour ce firmware, les données originales vont être utilisées @@ -3421,7 +3407,7 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1 - Impossible de restaurer les réglages et modèles sur la radio. Le fichier peut être récupéré ici: %1 + Impossible de restaurer les paramètres et modèles sur la radio. Le fichier peut être récupéré ici: %1 @@ -3928,7 +3914,7 @@ p, li { white-space: pre-wrap; } Radio settings - Réglages Radio + Paramètres Radio @@ -3945,12 +3931,12 @@ Communs à tous les modèles d'une même EEPROM. Store calib. and hw settings in selected profile - Sauver étalonnage et réglages hw dans profil + Sauver étalonnage et paramètres hw dans profil Retrieve calib. and hw settings from profile - Lire étalonnage et réglages hw du profil + Lire étalonnage et paramètres hw du profil @@ -4849,7 +4835,7 @@ p, li { white-space: pre-wrap; } Beeper Mode - Réglage des bips + Paramètre des bips @@ -6065,7 +6051,7 @@ Les colonnes contenant l'altitude "GAlt" et la vitesse "GSpd Show fuses dialog - Afficher les réglages des fusibles + Afficher les paramètres des fusibles @@ -6204,18 +6190,18 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Write Models and Settings To Radio - Transférer les réglages et modèles vers la radio + Transférer les paramètres et modèles vers la radio Write Models and Settings to Radio - Transférer les réglages et modèles vers la radio + Transférer les paramètres et modèles vers la radio Read Models and Settings from Radio - Lire les réglages et modèles depuis la radio + Lire les paramètres et modèles depuis la radio @@ -6265,7 +6251,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Save a complete backup file of all settings and model data in the Radio - Créer une copie de sauvegarde de tous les réglages et modèles de la radio + Créer une copie de sauvegarde de tous les paramètres et modèles de la radio @@ -6337,7 +6323,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Open Models and Settings file - Ouvrir un fichier de réglages et modèles + Ouvrir un fichier de paramètres et modèles @@ -6348,7 +6334,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Read Models and Settings From Radio - Lire les réglages et modèles depuis la radio + Lire les paramètres et modèles depuis la radio @@ -6388,7 +6374,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Models and Settings read - Lecture des modèles et réglages + Lecture des modèles et paramètres @@ -6403,12 +6389,12 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Local Folder - Dossier local + Dossier "Local" Radio Folder - Dossier Radio + Dossier "Radio" @@ -6439,13 +6425,13 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Create a new Models and Settings file - Créer un nouveau fichier de réglages et modèles + Créer un nouveau fichier de paramètres et modèles Save Models and Settings file - Enregistrer le fichier de réglages et modèles + Enregistrer le fichier de paramètres et modèles @@ -6465,7 +6451,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Close Models and Settings file - Fermer le fichier de réglages et modèles + Fermer le fichier de paramètres et modèles @@ -6480,7 +6466,7 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Create a new Radio Settings Profile - Créer un nouveau profil de réglages et modèles + Créer un nouveau profil de paramètres et modèles @@ -6490,12 +6476,12 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b Duplicate current Radio Settings Profile - Dupliquer les réglages radio du profil actuel + Dupliquer les paramètres radio du profil actuel Delete the current Radio Settings Profile - Supprimer les réglages radio du profil actuel + Supprimer les paramètres radio du profil actuel @@ -6536,17 +6522,17 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b No Companion release candidates are currently being served for this version, please switch release channel - Aucune version "candidate" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal officiel + Aucune version "candidate" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" No nightly Companion builds are currently being served for this version, please switch release channel - Aucune version "nightly" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal officiel + Aucune version "nightly" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" No Companion release builds are currently being served for this version, please switch release channel - Aucune version "officielle" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal officiel + Aucune version "officielle" de Companion n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "candidate" ou "nightly" @@ -6556,17 +6542,17 @@ Nous recommandons de lire attentivement les notes de version à l'aide du b No firmware release candidates are currently being served for this version, please switch release channel - Aucun firmware "candidate" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal officiel + Aucun firmware "candidate" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" No firmware nightly builds are currently being served for this version, please switch release channel - Aucun firmware "nightly" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal officiel + Aucun firmware "nightly" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "officiel" No firmware release builds are currently being served for this version, please switch release channel - Aucun firmware "officiel" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal officiel + Aucun firmware "officiel" n'est actuellement disponible sur ce serveur, veuillez commuter sur le canal "candidate" ou "nightly" @@ -6654,22 +6640,22 @@ Do you wish to continue? Export Application Settings.. - Exporter les réglages de l'application... + Exporter Préférences Application... Save all the current %1 and Simulator settings (including radio profiles) to a file. - Enregistrez tous les réglages actuels %1 et du simulateur (y compris les profils radio) dans un fichier. + Enregistrez tous les paramètres actuels %1 et du simulateur (y compris les profils radio) dans un fichier. Import Application Settings.. - Importer les réglages de l'application... + Importer les paramètres de l'application... Load %1 and Simulator settings from a prevously exported settings file. - Charger les réglages %1 et les réglages de Simulation depuis un fichier précédemment exporté. + Charger les paramètres %1 et les paramètres de Simulation depuis un fichier précédemment exporté. @@ -6804,17 +6790,17 @@ Do you wish to continue? Please save or close all modified files before importing settings - Veuillez sauvegarder ou fermer tous les fichiers modifiés avant d'importer les réglages + Veuillez sauvegarder ou fermer tous les fichiers modifiés avant d'importer les paramètres <html><p>%1 and Simulator settings can be imported (restored) from a previosly saved export (backup) file. This will replace current settings with any settings found in the file.</p><p>An automatic backup of the current settings will be attempted. But if the current settings are useful then it is recommended that you make a manual backup first.</p><p>For best results when importing settings, <b>close any other %1 windows you may have open, and make sure the standalone Simulator application is not running.</p><p>Do you wish to continue?</p></html> - <html><p>%1 et les réglages du simulateur peuvent être importés (restaurés) à partir d’un fichier d’exportation (sauvegarde) préalablement sauvegardé. Ceci remplacera les réglages actuels par tous les réglages trouvés dans le fichier.</p><p>Une sauvegarde automatique des réglages actuels sera tentée. Mais si les réglages actuels sont utiles, il est recommandé de commencer par une sauvegarde manuelle.</p><p>Pour obtenir de meilleurs résultats lors de l'importation des réglages,<b> fermez les autres fenêtres %1 que vous avez éventuellement ouvertes et assurez-vous que l'application autonome Simulator n'est pas en cours d'exécution. </p><p>Souhaitez-vous continuer? </p></html> + <html><p>%1 et les paramètres du simulateur peuvent être importés (restaurés) à partir d’un fichier d’exportation (sauvegarde) préalablement sauvegardé. Ceci remplacera les paramètres actuels par tous les paramètres trouvés dans le fichier.</p><p>Une sauvegarde automatique des paramètres actuels sera tentée. Mais si les paramètres actuels sont utiles, il est recommandé de commencer par une sauvegarde manuelle.</p><p>Pour obtenir de meilleurs résultats lors de l'importation des paramètres,<b> fermez les autres fenêtres %1 que vous avez éventuellement ouvertes et assurez-vous que l'application autonome Simulator n'est pas en cours d'exécution. </p><p>Souhaitez-vous continuer? </p></html> Confirm Settings Import - Confirmer les réglages d'importation + Confirmer les paramètres d'importation @@ -6834,17 +6820,17 @@ Do you wish to continue? The settings could not be imported. - Les réglages n'ont pas pu être importés. + Les paramètres n'ont pas pu être importés. <html><p>New settings have been imported from:<br> %1.</p><p>%2 will now re-initialize.</p><p>Note that you may need to close and restart %2 before some settings like language and icon theme take effect.</p> - <html><p>Les nouveaux réglages ont été importés depuis:<br> %1. </p><p>%2 sera maintenant réinitialisé.</p><p>Notez que vous devrez peut-être fermer et redémarrer %2 avant que certains réglages tels que la langue et le thème d’icône prennent effet.</p> + <html><p>Les nouveaux paramètres ont été importés depuis:<br> %1. </p><p>%2 sera maintenant réinitialisé.</p><p>Notez que vous devrez peut-être fermer et redémarrer %2 avant que certains paramètres tels que la langue et le thème d’icône prennent effet.</p> <p>The previous settings were backed up to:<br> %1</p> - <p>Les réglages précédents ont été sauvegardés sous:<br> %1 </p> + <p>Les paramètres précédents ont été sauvegardés sous:<br> %1 </p> @@ -6879,7 +6865,7 @@ Do you wish to continue? Edit Settings - Éditer les réglages + Éditer les préférences @@ -6962,7 +6948,7 @@ Do you wish to continue? Settings - Réglages + Paramètres @@ -7102,17 +7088,17 @@ Do you wish to continue? Edit Radio Settings - Éditer réglages radio + Éditer paramètres radio Copy Radio Settings - Copier les réglages radio + Copier les paramètres radio Paste Radio Settings - Coller les réglages radio + Coller les paramètres radio @@ -7275,7 +7261,7 @@ Do you wish to continue? Models and Settings written - Modèle et réglages écrit + Modèle et paramètres écrit @@ -7341,7 +7327,7 @@ Do you wish to continue? Open backup Models and Settings file - Ouvrir la sauvegarde de réglages et modèles + Ouvrir la sauvegarde de paramètres et modèles @@ -7779,7 +7765,7 @@ Mixage actif par défaut si non-renseigné. Heli - Réglages hélico + Paramètres hélico @@ -9831,7 +9817,7 @@ Mixage actif par défaut si non-renseigné. <html><head/><body><p>No Radio was found!</p><p>Make sure that you hold the lower trim buttons towards the center while you turn it on.</p><p>Then connect the USB wire.</p><p><span style=" font-family:'arial,sans-serif'; font-size:13px; font-style:italic; color:#222222; background-color:#ffffff;">Note: if you have a Taranis that has not had the firmware upgraded to 2.0 then this version of Companion will not work.</span></p></body></html> - <html><head/><body><p>Aucune radio détectée !</p><p>Veuillez vous assurer de maintenir les 2 trims horizontaux vers l'intérieur lors de la mise sous tension de la radio.</p><p>Ensuite connecter le câble USB.</p><p><span style=" font-family:'arial,sans-serif'; font-size:13px; font-style:italic; color:#222222; background-color:#ffffff;">Note: Cette version de Companion ne doit être utilisée pour éditer des réglages que si la version du firmware de la radio est au moins 2.0.</span></p></body></html> + <html><head/><body><p>Aucune radio détectée !</p><p>Veuillez vous assurer de maintenir les 2 trims horizontaux vers l'intérieur lors de la mise sous tension de la radio.</p><p>Ensuite connecter le câble USB.</p><p><span style=" font-family:'arial,sans-serif'; font-size:13px; font-style:italic; color:#222222; background-color:#ffffff;">Note: Cette version de Companion ne doit être utilisée pour éditer des paramètres que si la version du firmware de la radio est au moins 2.0.</span></p></body></html> @@ -9843,43 +9829,36 @@ Mixage actif par défaut si non-renseigné. RadioOutputsWidget - Form Formulaire - View: Vue: - Logical Switches Inters Logiques - Global Variables Variables Globales - Channel Outputs Sorties Voies - Mix Outputs Sorties Mixages - L o g @@ -9890,7 +9869,6 @@ L - G l o @@ -9902,7 +9880,6 @@ G - C h a @@ -9918,7 +9895,6 @@ E - M i x @@ -9934,12 +9910,12 @@ E FM%1 - PV%1 + PV%1 GV%1 - VG%1 + VG%1 @@ -10748,16 +10724,6 @@ E TELE - - - Internal - Interne - - - - External - Externe - Setup @@ -10948,7 +10914,7 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo Profile Settings - Réglages du profil + Paramètres du profil @@ -11301,181 +11267,151 @@ Profil ID: [%1]; Radio ID: [%2] SimulatorMainWindow - OpenTx Simulator Simulateur OpenTX - View Vue - Radio Window Fenêtre radio - Reload... Recharger... - Tools Outils - Toolbar Barre d'outils - Reload Lua Scripts Recharger le script Lua - Reload the Lua environment on the simulated radio. Recharger l'environnement Lua dans le simulateur. - F7 - Reload Radio Data Recharger les données radio - Reload all radio data without restarting the simulator. Recharger les données radio sans redémarrer le simulateur. - F9 - Key Mapping Raccourcis clavier - Show keyboard maping reference. Afficher les raccourcis clavier. - F1 - Joystick Settings Paramètres Joystick - Open joystick configuration settings dialog. Ouvrir la boite de dialogue de la configuration du Joystick. - F3 - LCD Screenshot Capture LCD - Save a screenshot of the current simulated LCD screen. Enregistrez une capture de l'écran LCD actuellement simulé. - F8 - Dock In Main Window Ancrer dans la fenêtre principale - Show the radio in the main window or as a separate "floating" window. Afficher la radio dans la fenêtre principale ou comme une fenêtre "flottante" séparée. - Menu Bar Barre de menus - Show or hide the top menu bar. Afficher ou masquer la barre de menus. - Alt+M - Constrain Width Contraindre la largeur - Set radio widget width to be a fixed size. Défini la largeur du widget radio comme étant une taille fixe. - Constrain Height Contraindre la hauteur - Set radio widget height to be a fixed size. Défini la hauteur du widget radio comme étant une taille fixe. @@ -11556,25 +11492,21 @@ Profil ID: [%1]; Radio ID: [%2] SimulatorStartupDialog - OpenTX Simulator - Startup Options Simulateur OpenTX - Options de démarrage - Simulator Startup Options: Options de démarrage: - Radio Profile: Profil Radio: - Existing radio profiles are shown here.<br /> Create or edit profiles using the Companion application. Les profils existants sont affichés ici.<br /> @@ -11582,13 +11514,11 @@ Créer ou éditer les profils avec l'application Companion. - Radio Type: Type de Radio: - Existing radio simulators are shown here.<br /> The radio type specified in the selected profile is used by default. Les simulateurs radios existants sont affichés ici.<br /> @@ -11596,31 +11526,26 @@ Le type de radio choisi par défaut est celui défini dans le profil selectionn - Data Source: Source Données: - Data File: Fichier Données: - Data Folder: Dossier Données: - SD Image Path: Dossier Image SD: - Radio data (.bin/.eeprom/.otx) image file to use. A new file with a default image will be created if necessary.<br /> <b>NOTE</b>: any existing EEPROM data incompatible with the selected radio type may be overwritten! Fichier de données utilisé (.bin/.eeprom/.otx).Un nouveau fichier avec une nouvelle image sera créé si nécessaire.<br /> @@ -11628,7 +11553,6 @@ Le type de radio choisi par défaut est celui défini dans le profil selectionn - Select data file... Choisir le fichier de données... @@ -11636,15 +11560,11 @@ Le type de radio choisi par défaut est celui défini dans le profil selectionn - - - ... - Directory containing RADIO and MODELS folders to use.<br /> New folder(s) with default radio/model will be created here if necessary. Chemin contenant les dossiers RADIO et MODELS à utiliser.<br /> @@ -11652,13 +11572,11 @@ Un (ou plusieurs) dossier peut être créé ici si nécessaire. - Select data folder... Sélectionner le dossier de données... - Directory containing the SD card image to use.<br/> The default is configured in the chosen Radio Profile. Dossier contenant l'image de la carte SD.<br/> @@ -11666,31 +11584,26 @@ La valeur par défaut est configurée dans le profil radio sélectionné. - Select SD card image folder... Choisir le dossier contenant l'image de la carte SD... - Select which of the data sources (File/Folder/SD Card) you would like to start the simulator with. Choisir la source (Fichier/Dossier/Image SD) du type de donnée utilisé par le simulateur. - File Fichier - Folder Dossier - SD Path Image SD @@ -11719,7 +11632,6 @@ La valeur par défaut est configurée dans le profil radio sélectionné.SimulatorWidget - Companion Simulator Simulateur Companion @@ -11855,7 +11767,7 @@ La valeur par défaut est configurée dans le profil radio sélectionné. &Reset to default - &Réglages par défaut + &Paramètres par défaut @@ -12487,104 +12399,104 @@ Trop d'erreurs, abandon. TelemetryPanel - + FrSky S.PORT - + FrSky D - + FrSky D (cable) FrSky D (câble) - + Telemetry screen %1 Ecran de télémesure %1 - + Source - + Low Alarm Alarme basse - + Critical Alarm Alarme critique - + Winged Shadow How High - + Winged Shadow How High (not supported) Winged Shadow How High (non supporté) - + Alti Alt - + Alti+ Alt+ - + VSpeed Vitesse verticale - - - + + + A1 - - - + + + A2 - - + + A3 - - + + A4 - - + + FAS - + Cells Velm - + --- @@ -12622,254 +12534,249 @@ Trop d'erreurs, abandon. - - Mod. - - - - + Add Addition - + Average Moyenne - + Min - + Max - + Multiply Multiplication - + Totalize Totalisation - + Cell Element LiPo - + Consumption Consommation - + Dist Distance - + Cells Sensor : Capteur d'éléments: - - - - - - - - + + + + + + + + --- - + GPS Sensor : Capteur GPS: - + Alt. Sensor : Capteur d'altitude: - + Sensor : Capteur: - + V - + A - + mA - + kt - + m/s - + ft/s - + km/h - + mph - + m - + ft - + °C - + °F - + % - + mAh - + W - + mW - + dBm - + g - + ° - + Rad - + mL - + US fl.Oz. - + Raw (-) Chiffres bruts (-) - + RPM Tours/minute - + Precision Précision - + Ratio - + Blades Pales - + Offset Décalage - + Multiplier Multiplicateur - + Auto Offset Offset auto - + Filter Filtre - + Persistent Persistant - + Positive - + Logs @@ -12901,121 +12808,101 @@ Trop d'erreurs, abandon. TelemetrySimulator - Telemetry Simulator Simulateur de télémesure - VFAS - RSSI - Simulate Simuler - Replay SD Log File Rejouer le fichier de Log SD - Replay rate Vitesse - |> - <| - > - <- - X - 1/5x - 5x - No Log File Currently Loaded Pas de fichier de Log chargé - Setting RSSI to zero simulates telemetry and radio link loss. Régler le RSSI à zéro simule la perte de liaison radio et de télémétrie. - Set RSSI to zero when paused. Régler le RSSI à zéro lors d'une pause. - Stop sending telemetry data when the Telemetry Simulator window is hidden. Arrêtez d'envoyer des données de télémétrie lorsque la case est cochée. - Pause simulation when hidden. Pause la simulation. - Load Charger - Row # Timestamp Ligne # @@ -13023,7 +12910,6 @@ Horodatage - RxBt @@ -13031,9 +12917,6 @@ Horodatage - - - V / ratio @@ -13051,140 +12934,105 @@ Horodatage - - - - - - - - - - - - - <html><head/><body><p><br/></p></body></html> - - Volts - Db dB - Curr Courant - Amps - Cels Elément - A1 - A2 - ASpd - - km/h - A3 - GAlt - - Meters Mètres - A4 - GSpd - Tmp1 - RAS - Hdg - Lat,Lon (dec.deg.) - dd-MM-yyyy hh:mm:ss jj-MM-aaaa @@ -13192,51 +13040,42 @@ hh:mm:ss - Degrees - Tmp2 - - °C - Date - GPS - Fuel Carburant - % - AccX @@ -13244,65 +13083,52 @@ hh:mm:ss - - - G - Fuel Qty Qté Carburant - ml - AccY - VSpd Vitesse Verticale - m/s - AccZ - Alt Altitude - - RPM - When enabled, sends any non-blank values as simulated telemetry data. Transmet les valeurs non vides au simulateur. @@ -13556,7 +13382,6 @@ Extra long : bips extra longs. TrainerSimulator - Trainer simulator Simulateur d'écolage @@ -13854,7 +13679,7 @@ Extra long : bips extra longs. Manually check the direction of each control surface and reverse any channels that make controls move in the wrong direction. Remove the propeller/propellers before you try to control your model for the first time.<br>Please note that continuing removes all old model settings! - Vérifiez manuellement le sens de chaque commande, et inversez les voies de celles qui répondent dans le mauvais sens. Attention à bien enlever les hélices du modèle avant de l'alimenter la première fois !<br>Veuillez noter que tous les réglages existants du modèle courant seront écrasés ! + Vérifiez manuellement le sens de chaque commande, et inversez les voies de celles qui répondent dans le mauvais sens. Attention à bien enlever les hélices du modèle avant de l'alimenter la première fois !<br>Veuillez noter que tous les paramètres existants du modèle courant seront écrasés ! @@ -14188,85 +14013,71 @@ m2560 for v4.1 boards joystickDialog - Configure Joystick Configuration du Joystick - Ch2 VOIE2 - Ch1 VOIE1 - Ch4 VOIE4 - Ch6 VOIE6 - Ch3 VOIE3 - Ch5 VOIE5 - Ch7 VOIE7 - Ch8 VOIE8 - Instructions - Enable Actif - Cancel Annuler - Back Précédent - Start Démarrer @@ -14277,7 +14088,6 @@ m2560 for v4.1 boards - Ok OK From 2fd12eb75ea1fac88865a90291df77f269342936 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 26 Sep 2019 12:26:05 +0200 Subject: [PATCH 040/257] Fix --- radio/src/gui/480x272/radio_sdmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp index 0534e6bbf..9ec46442b 100644 --- a/radio/src/gui/480x272/radio_sdmanager.cpp +++ b/radio/src/gui/480x272/radio_sdmanager.cpp @@ -282,8 +282,8 @@ bool menuRadioSdManager(event_t _event) #endif POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MULTI); } -#endif } +#endif else if (!READ_ONLY() && !strcasecmp(ext, FRSKY_FIRMWARE_EXT)) { FrSkyFirmwareInformation information; if (readFrSkyFirmwareInformation(line, information) == nullptr) { From cc051ca8a3d97546c7344269c8da829ae19fdd1f Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 27 Sep 2019 09:42:13 +0200 Subject: [PATCH 041/257] Version prep --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f40a9ff6..9d9b3abb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(OpenTX) set(VERSION_MAJOR "2") set(VERSION_MINOR "3") -set(VERSION_REVISION "0") +set(VERSION_REVISION "1") set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) From c62a0def798345ac195baafa8d2dc05de2801e78 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 27 Sep 2019 11:18:07 +0200 Subject: [PATCH 042/257] Release prep --- tools/rc22/build-rc.sh | 71 ----------- tools/rc22/build-sdcard.sh | 50 -------- tools/release22/build-release.sh | 61 ---------- tools/release22/build-sdcard.sh | 50 -------- tools/release22/tts.py | 152 ------------------------ tools/release22/tts_common.py | 14 --- tools/release23/build-sdcard.sh | 77 ++++++++++++ tools/{rc22 => release23}/tts.py | 0 tools/{rc22 => release23}/tts_common.py | 0 9 files changed, 77 insertions(+), 398 deletions(-) delete mode 100755 tools/rc22/build-rc.sh delete mode 100755 tools/rc22/build-sdcard.sh delete mode 100755 tools/release22/build-release.sh delete mode 100755 tools/release22/build-sdcard.sh delete mode 100755 tools/release22/tts.py delete mode 100644 tools/release22/tts_common.py create mode 100755 tools/release23/build-sdcard.sh rename tools/{rc22 => release23}/tts.py (100%) rename tools/{rc22 => release23}/tts_common.py (100%) diff --git a/tools/rc22/build-rc.sh b/tools/rc22/build-rc.sh deleted file mode 100755 index daffff3f2..000000000 --- a/tools/rc22/build-rc.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -set -e - -branch=2.2 -docker=rc22 -workdir=/home/opentx/rc22 -output=/var/www/html/2.2/rc -version=2.3.0 - -# Increment RC index -index=`cat index.txt` -index=`expr $index + 1` -suffix="RC$index" - -cd ${workdir} - -# Create on-demand build environment -cp code/radio/util/Dockerfile . -docker build -t new-${docker} --build-arg OPENTX_VERSION_SUFFIX=${suffix} . -set +e -docker rmi -f ${docker} -set -e -docker tag new-${docker} ${docker} -docker rmi -f new-${docker} - -# Call sdcard generation -code/tools/rc22/build-sdcard.sh - -# Build Linux companion -docker run -dit --name companion -v /home/opentx/${docker}:/opentx ${docker} -docker exec companion sh -c "mkdir -p build && cd build && cmake /opentx/code && cp radio/src/stamp.h /opentx/binaries/stamp-opentx.txt" -docker exec companion rm -rf build -if [ ! -f ${output}/companion/linux/companion22_${version}${suffix}_amd64.deb ]; then - docker exec companion /opentx/code/tools/build-companion-release.sh /opentx/code /opentx/binaries/ - docker exec companion sh -c "cp /build/radio/src/lua/*.txt /opentx/binaries" - cp -f binaries/*.deb ${output}/companion/linux/companion22_${version}${suffix}_amd64.deb - cp -f binaries/lua_fields_*.txt ${output}/firmware -fi -docker stop companion -docker rm companion - -# Request companion compilation on Windows -if [ ! -f ${output}/companion/windows/companion-windows-${version}${suffix}.exe ]; then - cd ${output}/companion/windows - wget -qO- http://winbox.open-tx.org/companion-builds/compile22.php?branch=$branch\&suffix=${suffix} - wget -O companion-windows-${version}${suffix}.exe http://winbox.open-tx.org/companion-builds/companion-windows-${version}${suffix}.exe - chmod -Rf g+w companion-windows-${version}${suffix}.exe -fi - -# Request companion compilation on Mac OS X -if [ ! -f ${output}/companion/macosx/opentx-companion-${version}${suffix}.dmg ]; then - cd ${output}/companion/macosx - wget -qO- http://opentx.blinkt.de:8080/~opentx/build-opentx.py?branch=${branch}\&suffix=${suffix} - wget -O opentx-companion-${version}${suffix}.dmg http://opentx.blinkt.de:8080/~opentx/builds/opentx-companion-${version}${suffix}.dmg - chmod -Rf g+w opentx-companion-${version}${suffix}.dmg -fi - -# Update stamps -cp -f $workdir/binaries/stamp-opentx.txt ${output}/firmware -echo "#define VERSION \"${version}${suffix}\"" > ${output}/companion/companion-windows.stamp -cp -f ${output}/companion/companion-windows.stamp ${output}/companion/companion-macosx.stamp -cp -f ${output}/companion/companion-windows.stamp ${output}/companion/companion-linux.stamp - - -# Clean binaries It will be hosting built on demand firmware -rm -rf $workdir/binaries/* -rm -rf $workdir/binaries/.lock - -# RC is considered as valid ony if we get to that point -echo $index > ${workdir}/index.txt diff --git a/tools/rc22/build-sdcard.sh b/tools/rc22/build-sdcard.sh deleted file mode 100755 index 8fec66805..000000000 --- a/tools/rc22/build-sdcard.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -set -e - -branch=2.2 -workdir=/home/opentx/rc22 -output=/var/www/html/2.2/rc - -# Handle opentx.sdcard.version -sdcard_version="2.2V"$(grep 'set(SDCARD_REVISION' ${workdir}/code/CMakeLists.txt | grep -o '".*"' | sed 's/"//g') -echo ${sdcard_version} > ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version -echo ${sdcard_version} > ${workdir}/code/radio/sdcard/taranis-x9/opentx.sdcard.version -echo ${sdcard_version} > ${workdir}/code/radio/sdcard/taranis-x7/opentx.sdcard.version - -if cmp --silent ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version ${workdir}/opentx.sdcard.version -then - exit -else - cp -r ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version ${workdir} - cd ${workdir} - - # Copy git sdcard data - rm -Rf ${workdir}/sdcard - cp -r ${workdir}/code/radio/sdcard . - - # Get images for Horus - mkdir -p ${workdir}/sdcard/horus/IMAGES - cp /home/opentx/horus-bitmaps/* ${workdir}/sdcard/horus/IMAGES/ - - # Request sound pack generation - ${workdir}/code/tools/rc22/tts.py en csv files - ${workdir}/code/tools/rc22/tts.py fr csv files - ${workdir}/code/tools/rc22/tts.py es csv files - ${workdir}/code/tools/rc22/tts.py it csv files - ${workdir}/code/tools/rc22/tts.py de csv files - ${workdir}/code/tools/rc22/tts.py cz csv files - ${workdir}/code/tools/rc22/tts.py pt csv files - ${workdir}/code/tools/rc22/tts.py ru csv psv files - - # Create sdcards.zips for supported platforms - mv /tmp/SOUNDS ${workdir}/sdcard/horus/ - mkdir ${workdir}/sdcard/taranis-x9/SOUNDS - mkdir ${workdir}/sdcard/taranis-x7/SOUNDS - cp -r ${workdir}/sdcard/horus/SOUNDS ${workdir}/sdcard/taranis-x9/ - cp -r ${workdir}/sdcard/horus/SOUNDS ${workdir}/sdcard/taranis-x7/ - cd ${workdir}/sdcard/horus && zip -r ${output}/sdcard/opentx-x12s/sdcard-horus-${sdcard_version}.zip * - cd ${workdir}/sdcard/taranis-x9 && zip -r ${output}/sdcard/opentx-x9d/sdcard-taranis-x9-${sdcard_version}.zip * - cd ${workdir}/sdcard/taranis-x7 && zip -r ${output}/sdcard/opentx-x7/sdcard-taranis-x7-${sdcard_version}.zip * - rm -Rf ${workdir}/sdcard -fi \ No newline at end of file diff --git a/tools/release22/build-release.sh b/tools/release22/build-release.sh deleted file mode 100755 index 9fbc37e07..000000000 --- a/tools/release22/build-release.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -set -e - -branch=2.2 -docker=release22 -workdir=/home/opentx/release22 -output=/var/www/html/2.2/release -version=2.3.0 - -cd ${workdir} - -# Create on-demand build environment -cp code/radio/util/Dockerfile . -docker build -t new-${docker} . -docker rmi -f ${docker} || true -docker tag new-${docker} ${docker} -docker rmi -f new-${docker} - -# Call sdcard generation -code/tools/release22/build-sdcard.sh - -# Build Linux companion -docker run -dit --name companion -v /home/opentx/${docker}:/opentx ${docker} -docker exec companion sh -c "mkdir -p build && cd build && cmake /opentx/code && cp radio/src/stamp.h /opentx/binaries/stamp-opentx.txt" -docker exec companion rm -rf build -if [ ! -f ${output}/companion/linux/companion22_${version}_amd64.deb ]; then - docker exec companion /opentx/code/tools/build-companion-release.sh /opentx/code /opentx/binaries/ - docker exec companion sh -c "cp /build/radio/src/lua/*.txt /opentx/binaries" - cp -f binaries/*.deb ${output}/companion/linux/companion22_${version}_amd64.deb - cp -f binaries/lua_fields_*.txt ${output}/firmware -fi -docker stop companion -docker rm companion - -# Request companion compilation on Windows -if [ ! -f ${output}/companion/windows/companion-windows-${version}.exe ]; then - cd ${output}/companion/windows - wget -qO- http://winbox.open-tx.org/companion-builds/compile22.php?branch=${branch} - wget -O companion-windows-${version}.exe http://winbox.open-tx.org/companion-builds/companion-windows-${version}.exe - chmod -f g+w companion-windows-${version}.exe -fi - -# Request companion compilation on Mac OS X -if [ ! -f ${output}/companion/macosx/opentx-companion-${version}.dmg ]; then - cd ${output}/companion/macosx - wget -qO- http://opentx.blinkt.de:8080/~opentx/build-opentx.py?branch=${branch} - wget -O opentx-companion-${version}.dmg http://opentx.blinkt.de:8080/~opentx/builds/opentx-companion-${version}.dmg - chmod -f g+w opentx-companion-${version}.dmg -fi - -# Update stamps -cp -f $workdir/binaries/stamp-opentx.txt ${output}/firmware -echo "#define VERSION "'"2.3.0"' > ${output}/companion/companion-windows.stamp -cp -f ${output}/companion/companion-windows.stamp ${output}/companion/companion-macosx.stamp -cp -f ${output}/companion/companion-windows.stamp ${output}/companion/companion-linux.stamp - - -# Clean binaries It will be hosting built on demand firmware -rm -rf $workdir/binaries/* -rm -rf $workdir/binaries/.lock diff --git a/tools/release22/build-sdcard.sh b/tools/release22/build-sdcard.sh deleted file mode 100755 index 7dd386c26..000000000 --- a/tools/release22/build-sdcard.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -set -e - -branch=2.2 -workdir=/home/opentx/release22 -output=/var/www/html/2.2/release - -# Handle opentx.sdcard.version -sdcard_version="2.2V"$(grep 'set(SDCARD_REVISION' ${workdir}/code/CMakeLists.txt | grep -o '".*"' | sed 's/"//g') -echo ${sdcard_version} > ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version -echo ${sdcard_version} > ${workdir}/code/radio/sdcard/taranis-x9/opentx.sdcard.version -echo ${sdcard_version} > ${workdir}/code/radio/sdcard/taranis-x7/opentx.sdcard.version - -if cmp --silent ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version ${workdir}/opentx.sdcard.version -then - exit -else - cp -r ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version ${workdir} - cd ${workdir} - - # Copy git sdcard data - rm -Rf ${workdir}/sdcard - cp -r ${workdir}/code/radio/sdcard . - - # Get images for Horus - mkdir -p ${workdir}/sdcard/horus/IMAGES - cp /home/opentx/horus-bitmaps/* ${workdir}/sdcard/horus/IMAGES/ - - # Request sound pack generation - ${workdir}/code/tools/release22/tts.py en csv files - ${workdir}/code/tools/release22/tts.py fr csv files - ${workdir}/code/tools/release22/tts.py es csv files - ${workdir}/code/tools/release22/tts.py it csv files - ${workdir}/code/tools/release22/tts.py de csv files - ${workdir}/code/tools/release22/tts.py cz csv files - ${workdir}/code/tools/release22/tts.py pt csv files - ${workdir}/code/tools/release22/tts.py ru csv psv files - - # Create sdcards.zips for supported platforms - mv /tmp/SOUNDS ${workdir}/sdcard/horus/ - mkdir ${workdir}/sdcard/taranis-x9/SOUNDS - mkdir ${workdir}/sdcard/taranis-x7/SOUNDS - cp -r ${workdir}/sdcard/horus/SOUNDS ${workdir}/sdcard/taranis-x9/ - cp -r ${workdir}/sdcard/horus/SOUNDS ${workdir}/sdcard/taranis-x7/ - cd ${workdir}/sdcard/horus && zip -r ${output}/sdcard/opentx-x12s/sdcard-horus-${sdcard_version}.zip * - cd ${workdir}/sdcard/taranis-x9 && zip -r ${output}/sdcard/opentx-x9d/sdcard-taranis-x9-${sdcard_version}.zip * - cd ${workdir}/sdcard/taranis-x7 && zip -r ${output}/sdcard/opentx-x7/sdcard-taranis-x7-${sdcard_version}.zip * - rm -Rf ${workdir}/sdcard -fi \ No newline at end of file diff --git a/tools/release22/tts.py b/tools/release22/tts.py deleted file mode 100755 index fc42cfeb6..000000000 --- a/tools/release22/tts.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - - -# This script is a modified version to support Linux TTS fiel genration using PicoTTS - -# Sound pack maintainers (incomplete list) by language alphabetical order -# Czech : Martin Hotar -# French : Bertrand Songis & André Bernet -# English : Rob Thompson & Martin Hotar -# German : Romolo Manfredini (Some corrections by Peer) -# Italian : Romolo Manfredini -# Portuguese : Romolo Manfredini -# Spanish : Romolo Manfredini (With the help of Jose Moreno) - -# from __future__ import print_function - -import os -import sys -import subprocess -import zipfile -from gtts import gTTS -from tts_common import * -board = "taranis" - -reload(sys) -sys.setdefaultencoding('utf8') - -SOURCE_DIRECTORY = os.path.dirname(os.path.realpath(__file__)) -lib_path = os.path.abspath(os.path.join(SOURCE_DIRECTORY, '..', '..', 'radio', 'util')) -sys.path.append(lib_path) - -def generate(str, filename): - if 0: - output = "output.wav" - command = 'pico2wave -l=%s -w=%s "%s"' % (voice, output, str) - os.system(command.encode('utf-8')) - command = "sox %s -r 32000 %s reverse silence 1 0.1 0.1%% reverse" % (output, filename) - os.system(command.encode('utf-8')) - else: - output = u"output.mp3" - tts = gTTS(text=str, lang=voice[:2]) - tts.save(output) - command = "sox --norm %s -r 32000 %s tempo 1.2" % (output, filename) - os.system(command.encode('utf-8')) - command = "rm -f output.mp3" - os.system(command.encode('utf-8')) - -################################################################ - -if __name__ == "__main__": - if "en" in sys.argv: - from tts_en import systemSounds, sounds - - directory = "en" - voice = "en-US" - - elif "fr" in sys.argv: - from tts_fr import systemSounds, sounds - - directory = "fr" - voice = "fr-FR" - - elif "it" in sys.argv: - from tts_it import systemSounds, sounds - - directory = "it" - voice = "it-IT" - - elif "de" in sys.argv: - from tts_de import systemSounds, sounds - - directory = "de" - voice = "de-DE" - - elif "es" in sys.argv: - from tts_es import systemSounds, sounds - - directory = "es" - voice = "es-ES" - - elif "cz" in sys.argv: - from tts_cz import systemSounds, sounds - - directory = "cz" - voice = "cs-CZ" - - elif "ru" in sys.argv: - from tts_ru import systemSounds, sounds - - directory = "ru" - voice = "ru-RU" - - elif "pt" in sys.argv: - from tts_pt import systemSounds, sounds - - directory = "pt" - voice = "pt-PT" - - else: - print("which language?") - exit() - - if "csv" in sys.argv: - path = "/tmp/SOUNDS/" + directory + "/SYSTEM/" - if not os.path.exists(path): - os.makedirs(path) - os.chdir(path) - with open("%s-%s.csv" % (voice, board), "wb") as csvFile: - for s, f in systemSounds: - if s and f: - l = u"" - if board in ("sky9x", "taranis"): - l += u"SOUNDS/%s/SYSTEM;" % directory - l += f + u";" + s + u"\n" - csvFile.write(l.encode("utf-8")) - for s, f in sounds: - if s and f: - l = u"" - if board in ("sky9x", "taranis"): - l += u"SOUNDS/%s;" % directory - l += f + u";" + s + u"\n" - csvFile.write(l.encode("utf-8")) - - if "psv" in sys.argv: - path = "/tmp/SOUNDS/" + directory + "/" - if not os.path.exists(path): - os.makedirs(path) - os.chdir(path) - with open("%s-%s.psv" % (voice, board), "wb") as csvFile: - for s, f in systemSounds: - if s and f: - l = u"SYSTEM|" + f.replace(".wav", "") + u"|" + s + u"\r\n" - csvFile.write(l.encode("windows-1251")) - for s, f in sounds: - if s and f: - l = u"|" + f.replace(".wav", "") + u"|" + s + u"\r\n" - csvFile.write(l.encode("windows-1251")) - - - if "files" in sys.argv: - path = "/tmp/SOUNDS/" + directory + "/SYSTEM/" - if not os.path.exists(path): - os.makedirs(path) - os.chdir(path) - for s, f in systemSounds: - if s and f: - generate(s, f) - os.chdir("..") - for s, f in sounds: - if s and f: - generate(s, f) diff --git a/tools/release22/tts_common.py b/tools/release22/tts_common.py deleted file mode 100644 index 25623b005..000000000 --- a/tools/release22/tts_common.py +++ /dev/null @@ -1,14 +0,0 @@ -NO_ALTERNATE = 1024 -PROMPT_CUSTOM_BASE = 256 -PROMPT_SYSTEM_BASE = 0 -board = "taranis" - -import sys - -def filename(idx, alternate=0): - ext = ".wav" - if isinstance(idx, int): - result = "%04d%s" % (idx, ext) - elif board in ('sky9x', 'taranis'): - result = idx + ext - return result diff --git a/tools/release23/build-sdcard.sh b/tools/release23/build-sdcard.sh new file mode 100755 index 000000000..97a4799b7 --- /dev/null +++ b/tools/release23/build-sdcard.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +set -e +set -x + +workdir=/home/opentx/release23 +output=/var/www/html/2.3/release + +# Handle opentx.sdcard.version +sdcard_version="2.3V"$(grep 'set(SDCARD_REVISION' ${workdir}/code/CMakeLists.txt | grep -o '".*"' | sed 's/"//g') +echo ${sdcard_version} > ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version +echo ${sdcard_version} > ${workdir}/code/radio/sdcard/taranis-x9/opentx.sdcard.version +echo ${sdcard_version} > ${workdir}/code/radio/sdcard/taranis-x7/opentx.sdcard.version + + +if cmp --silent ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version ${workdir}/opentx.sdcard.version +then + exit +else + cd ${workdir} + + # Copy git sdcard data + rm -Rf ${workdir}/sdcard + cp -r ${workdir}/code/radio/sdcard . + + # Get images for Horus + mkdir -p ${workdir}/sdcard/horus/IMAGES + cp /home/opentx/horus-bitmaps/* ${workdir}/sdcard/horus/IMAGES/ + + + # Request sound pack generation + if [[ ! -d /tmp/SOUNDS/fr ]];then + ${workdir}/code/tools/release23/tts.py en csv files + fi + if [[ ! -d /tmp/SOUNDS/es ]];then + ${workdir}/code/tools/release23/tts.py fr csv files + fi + if [[ ! -d /tmp/SOUNDS/it ]];then + ${workdir}/code/tools/release23/tts.py es csv files + fi + if [[ ! -d /tmp/SOUNDS/de ]];then + ${workdir}/code/tools/release23/tts.py it csv files + fi + if [[ ! -d /tmp/SOUNDS/cz ]];then + ${workdir}/code/tools/release23/tts.py de csv files + fi + if [[ ! -d /tmp/SOUNDS/pl ]];then + ${workdir}/code/tools/release23/tts.py cz csv files + fi + if [[ ! -d /tmp/SOUNDS/ru ]];then + ${workdir}/code/tools/release23/tts.py pt csv files + fi + ${workdir}/code/tools/release23/tts.py ru csv psv files + + # Create sdcards.zips for supported platforms + mv /tmp/SOUNDS ${workdir}/sdcard/horus/ + mkdir ${workdir}/sdcard/taranis-x9/SOUNDS + mkdir ${workdir}/sdcard/taranis-x7/SOUNDS + cp -r ${workdir}/sdcard/horus/SOUNDS ${workdir}/sdcard/taranis-x9/ + cp -r ${workdir}/sdcard/horus/SOUNDS ${workdir}/sdcard/taranis-x7/ + cd ${workdir}/sdcard/horus && zip -r ${output}/sdcard/sdcard-horus-${sdcard_version}.zip * + cd ${workdir}/sdcard/taranis-x9 && zip -r ${output}/sdcard/sdcard-taranis-x9-${sdcard_version}.zip * + cd ${workdir}/sdcard/taranis-x7 && zip -r ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip * + + # Create symlinks for other radios + ln -s ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip ${output}/sdcard/sdcard-taranis-xlite-${sdcard_version}.zip + ln -s ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip ${output}/sdcard/sdcard-taranis-x9lite-${sdcard_version}.zip + ln -s ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip ${output}/sdcard/sdcard-jumper-t12-${sdcard_version}.zip + + # remove LUA stuff for 9x platform + rm -Rf ${workdir}/sdcard/taranis-x7/SCRIPTS + rm -Rf ${workdir}/sdcard/taranis-x7/FrSky-utilities + cd ${workdir}/sdcard/taranis-x7 && zip -r ${output}/sdcard/sdcard-9xarm-${sdcard_version}.zip * + + rm -Rf ${workdir}/sdcard + cp -r ${workdir}/code/radio/sdcard/horus/opentx.sdcard.version ${workdir} +fi diff --git a/tools/rc22/tts.py b/tools/release23/tts.py similarity index 100% rename from tools/rc22/tts.py rename to tools/release23/tts.py diff --git a/tools/rc22/tts_common.py b/tools/release23/tts_common.py similarity index 100% rename from tools/rc22/tts_common.py rename to tools/release23/tts_common.py From 4b2b6b82a65f26f43e0d5cadf4352aa66bc9b0df Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:22:39 +0200 Subject: [PATCH 043/257] Last minute cosmetics... --- radio/src/gui/common/stdlcd/radio_hardware.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index eb73fbd7a..a62bd9f08 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -632,7 +632,10 @@ void menuRadioHardware(event_t event) break; case ITEM_RADIO_BACKUP_EEPROM: - lcdDrawText(LCD_W / 2, y, BUTTON(STR_EEBACKUP), attr | CENTERED); + if (LCD_W < 212) + lcdDrawText(LCD_W / 2, y, BUTTON(STR_EEBACKUP), attr | CENTERED); + else + lcdDrawText(HW_SETTINGS_COLUMN2, y, BUTTON(STR_EEBACKUP), attr); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = EDIT_SELECT_FIELD; eepromBackup(); @@ -640,7 +643,10 @@ void menuRadioHardware(event_t event) break; case ITEM_RADIO_FACTORY_RESET: - lcdDrawText(LCD_W / 2, y, BUTTON(STR_FACTORYRESET), attr | CENTERED); + if (LCD_W < 212) + lcdDrawText(LCD_W / 2, y, BUTTON(STR_FACTORYRESET), attr | CENTERED); + else + lcdDrawText(HW_SETTINGS_COLUMN2, y, BUTTON(STR_FACTORYRESET), attr); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { s_editMode = EDIT_SELECT_FIELD; POPUP_CONFIRMATION(STR_CONFIRMRESET, onFactoryResetConfirm); From 2265805ce6b578fb9c938c33b59fcf84629ca42e Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:47:44 +0200 Subject: [PATCH 044/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 4b96009dd..e03a17272 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1540,3 +1540,4 @@ Thomas Halenbeck (monthly) Sjoerd Dost Ralph Gustafson Herbert Feix +Robert Costford From 9032631e3751ca776636b894cc64062b55e741a3 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:48:15 +0200 Subject: [PATCH 045/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index e03a17272..96fb0de16 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1541,3 +1541,4 @@ Sjoerd Dost Ralph Gustafson Herbert Feix Robert Costford +Taavi Tuisk From a886a33c52362302647ca7e4d64bef3d3b8bb525 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:48:49 +0200 Subject: [PATCH 046/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 96fb0de16..9ae408f06 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1542,3 +1542,4 @@ Ralph Gustafson Herbert Feix Robert Costford Taavi Tuisk +Carlos Quian From 4440f3a78434c135158a8a8ae0a2f94d229cbafc Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:51:14 +0200 Subject: [PATCH 047/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 9ae408f06..87855f63a 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1543,3 +1543,4 @@ Herbert Feix Robert Costford Taavi Tuisk Carlos Quian +Noah Reinhart From 13c837bded0d07f5c277c756e17a4d6378892309 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:51:51 +0200 Subject: [PATCH 048/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 87855f63a..d6d666b9a 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1544,3 +1544,4 @@ Robert Costford Taavi Tuisk Carlos Quian Noah Reinhart +Timothy Fry From b46e55771325bd7be502f6ba66f049c339ca4cab Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:52:15 +0200 Subject: [PATCH 049/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index d6d666b9a..58dba02f6 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1545,3 +1545,4 @@ Taavi Tuisk Carlos Quian Noah Reinhart Timothy Fry +Marc Stelzner From 313024a461eabc4275f589b5f18dbaeb6ced512f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:55:26 +0200 Subject: [PATCH 050/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 58dba02f6..4115ff8d3 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1546,3 +1546,4 @@ Carlos Quian Noah Reinhart Timothy Fry Marc Stelzner +NXGRAPHICS From a946ed456e2cf7bdbabfb8dd29e5245c0a194fc6 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:56:17 +0200 Subject: [PATCH 051/257] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 4115ff8d3..46a533e49 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1547,3 +1547,5 @@ Noah Reinhart Timothy Fry Marc Stelzner NXGRAPHICS +AIR-RC + From 1f612fbeffe3bfa46b0081be2778af38bb87ec43 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:57:12 +0200 Subject: [PATCH 052/257] Update CREDITS.txt --- CREDITS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CREDITS.txt b/CREDITS.txt index 46a533e49..33a500477 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1548,4 +1548,4 @@ Timothy Fry Marc Stelzner NXGRAPHICS AIR-RC - +Nicolas Deshaies From 982cd8e2d7cf7a36895a501f0462f04a168b4b0a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:57:39 +0200 Subject: [PATCH 053/257] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 33a500477..9ee200129 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1549,3 +1549,5 @@ Marc Stelzner NXGRAPHICS AIR-RC Nicolas Deshaies +Jean-Francois Delhove + From c170efd9ed4af4978530769bed5c44fb64d08c50 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:58:14 +0200 Subject: [PATCH 054/257] Update CREDITS.txt --- CREDITS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CREDITS.txt b/CREDITS.txt index 9ee200129..656f19a7c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1550,4 +1550,4 @@ NXGRAPHICS AIR-RC Nicolas Deshaies Jean-Francois Delhove - +Hugo Daniel Farneti From b8b6f2c22f7e979232190a121939678a72e93814 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 11:59:42 +0200 Subject: [PATCH 055/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 656f19a7c..568313c56 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1551,3 +1551,4 @@ AIR-RC Nicolas Deshaies Jean-Francois Delhove Hugo Daniel Farneti +RC electronic products From 809e28472d33f078b1753058e6ed18335761e907 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 12:00:12 +0200 Subject: [PATCH 056/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 568313c56..decbe9fe2 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1552,3 +1552,4 @@ Nicolas Deshaies Jean-Francois Delhove Hugo Daniel Farneti RC electronic products +Adrian Andrei From f6f79cc2a8a9d46b51f46e1493c60b960917780e Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 12:00:44 +0200 Subject: [PATCH 057/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index decbe9fe2..e0cbb3414 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1553,3 +1553,4 @@ Jean-Francois Delhove Hugo Daniel Farneti RC electronic products Adrian Andrei +Henk van de Kerkhof From 4335f2728975a446819f7547dc78af7cfb4a5865 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 12:01:52 +0200 Subject: [PATCH 058/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index e0cbb3414..c1a1bd35c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1554,3 +1554,4 @@ Hugo Daniel Farneti RC electronic products Adrian Andrei Henk van de Kerkhof +Daniel Dubovski From 3873c204d500e92277b9e49a36dbe2e1e362cb25 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 12:02:16 +0200 Subject: [PATCH 059/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index c1a1bd35c..e89010e5c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1555,3 +1555,4 @@ RC electronic products Adrian Andrei Henk van de Kerkhof Daniel Dubovski +Hans-Georg Böhm From 9319b48f0e4e9d8e1c79179257c93c1ce3d28721 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 27 Sep 2019 13:38:29 +0200 Subject: [PATCH 060/257] Multi last minute fixes --- companion/src/firmwares/multiprotocols.cpp | 2 +- radio/src/gui/128x64/model_setup.cpp | 8 +++++--- radio/src/gui/212x64/model_setup.cpp | 8 +++++--- radio/src/gui/480x272/model_setup.cpp | 4 +++- radio/src/gui/gui_common.cpp | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/companion/src/firmwares/multiprotocols.cpp b/companion/src/firmwares/multiprotocols.cpp index 41f2e83c8..4ad8ba68a 100644 --- a/companion/src/firmwares/multiprotocols.cpp +++ b/companion/src/firmwares/multiprotocols.cpp @@ -108,7 +108,7 @@ const Multiprotocols multiProtocols { {MODULE_SUBTYPE_MULTI_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_BUGS_MINI, 1, false, STR_SUBTYPE_BUGS_MINI, nullptr}, {MODULE_SUBTYPE_MULTI_TRAXXAS, 0, false, STR_SUBTYPE_TRAXXAS, nullptr}, - {MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, nullptr}, + {MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION}, {MODULE_SUBTYPE_MULTI_V911S, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, nullptr}, {MODULE_SUBTYPE_MULTI_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index b89afc152..0865f6f95 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -1427,9 +1427,11 @@ void menuModelSetup(event_t event) } else { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); - lcdDrawText(MODEL_SETUP_2ND_COLUMN+23, y, "RSSI(", LEFT); - lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT); - lcdDrawText(lcdLastRightPos, y, ")", LEFT); + if (pdef->optionsstr == STR_MULTI_RFTUNE) { + lcdDrawText(MODEL_SETUP_2ND_COLUMN + 23, y, "RSSI(", LEFT); + lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT); + lcdDrawText(lcdLastRightPos, y, ")", LEFT); + } } } } diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index e3a7c66e5..17e250cda 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -1253,9 +1253,11 @@ void menuModelSetup(event_t event) } else { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); - lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT); - lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT); - lcdDrawText(lcdLastRightPos, y, ")", LEFT); + if (pdef->optionsstr == STR_MULTI_RFTUNE) { + lcdDrawText(MODEL_SETUP_3RD_COLUMN+22, y, "RSSI(", LEFT); + lcdDrawNumber(lcdLastRightPos, y, TELEMETRY_RSSI(), LEFT); + lcdDrawText(lcdLastRightPos, y, ")", LEFT); + } } } } diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 69b9ae676..216e20dd6 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1562,7 +1562,9 @@ bool menuModelSetup(event_t event) } else { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].multi.optionValue, -128, 127); - lcdDrawNumber(LCD_W-10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")"); + if (pdef->optionsstr == STR_MULTI_RFTUNE) { + lcdDrawNumber(LCD_W - 10, y, TELEMETRY_RSSI(), RIGHT, 0, "RSSI(", ")"); + } } } } diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 52dc9fd18..4fe9e169c 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -842,7 +842,7 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_HITEC, 2, false, STR_SUBTYPE_HITEC, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_BUGS_MINI, 1, false, STR_SUBTYPE_BUGS_MINI, nullptr}, {MODULE_SUBTYPE_MULTI_TRAXXAS, 0, false, STR_SUBTYPE_TRAXXAS, nullptr}, - {MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, nullptr}, + {MODULE_SUBTYPE_MULTI_E01X, 2, false, STR_SUBTYPE_E01X, STR_MULTI_OPTION}, {MODULE_SUBTYPE_MULTI_V911S, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_GD00X, 1, false, STR_SUBTYPE_GD00X, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_KF606, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, From 543d1eb2caa91433d7eaaa25b2a8d1487f681418 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 27 Sep 2019 13:49:18 +0200 Subject: [PATCH 061/257] Fixes --- radio/src/targets/taranis/hal.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index f98ef983e..99acd429b 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -910,7 +910,11 @@ #if defined(PCBXLITE) #define EXTERNAL_ANTENNA #endif - +#if defined(PCBXLITES) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019) + #define INTERNAL_MODULE_PXX2 +#else + #define INTERNAL_MODULE_PXX1 +#endif #if defined(PCBXLITE) || defined(PCBX9LITE) #define INTMODULE_RCC_APB1Periph 0 #define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1 From 226789d19bb2ac1b9fc21b940b2d04c30106ff9b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 14:16:51 +0200 Subject: [PATCH 062/257] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index e89010e5c..621a72e6b 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1556,3 +1556,5 @@ Adrian Andrei Henk van de Kerkhof Daniel Dubovski Hans-Georg Böhm +Tiberiu Atudorei + From db0d3031c6ff2c99d4d6cce97d9392e0229d2331 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 14:17:51 +0200 Subject: [PATCH 063/257] Update CREDITS.txt --- CREDITS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CREDITS.txt b/CREDITS.txt index 621a72e6b..8c8b99edb 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1557,4 +1557,4 @@ Henk van de Kerkhof Daniel Dubovski Hans-Georg Böhm Tiberiu Atudorei - +Alessandro Apostoli (Yaapu!) From b722eed3b82db2fc447e1515ddafc81d13d75eaf Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 14:22:21 +0200 Subject: [PATCH 064/257] CREDITS.txt updated --- CREDITS.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 279e2d8ed..6d16a5ca1 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1538,3 +1538,23 @@ Johannes Ferschl Piotr Wysocki Thomas Halenbeck (monthly) Sjoerd Dost +Ralph Gustafson +Herbert Feix +Robert Costford +Taavi Tuisk +Carlos Quian +Noah Reinhart +Timothy Fry +Marc Stelzner +NXGRAPHICS +AIR-RC +Nicolas Deshaies +Jean-Francois Delhove +Hugo Daniel Farneti +RC electronic products +Adrian Andrei +Henk van de Kerkhof +Daniel Dubovski +Hans-Georg Böhm +Tiberiu Atudorei +Alessandro Apostoli (Yaapu!) From 8447b3d7ee19fb683d060cbf9c6781974187abb5 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 15:31:03 +0200 Subject: [PATCH 065/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 8c8b99edb..94fafc160 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1558,3 +1558,4 @@ Daniel Dubovski Hans-Georg Böhm Tiberiu Atudorei Alessandro Apostoli (Yaapu!) +Kenneth Bonerigo From 09d9906f18ed1e7e9e39d82dac4f5e793bb4b7ab Mon Sep 17 00:00:00 2001 From: Kilrah Date: Fri, 27 Sep 2019 18:00:50 +0200 Subject: [PATCH 066/257] Tell nightly users that release is available for a few days (RC done manually) --- tools/nightly23/build-nightly.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nightly23/build-nightly.sh b/tools/nightly23/build-nightly.sh index 391f468ac..5e2a16515 100755 --- a/tools/nightly23/build-nightly.sh +++ b/tools/nightly23/build-nightly.sh @@ -36,7 +36,7 @@ docker exec companion sh -c "mkdir -p build && cd build && cmake /opentx/code && cp -f ${workdir}/binaries/stamp-opentx.txt ${output}/firmware # These radios are currently not enabled # echo "#define BLOCK \"x10,x12s\"" >> ${output}/firmware/stamp-opentx.txt -echo "#define ERROR \"MOVE_TO_RC\"" >> ${output}/firmware/stamp-opentx.txt +echo "#define ERROR \"MOVE_TO_RELEASE\"" >> ${output}/firmware/stamp-opentx.txt docker exec companion rm -rf build echo "Check if Linux companion is needed" From 603be3dead13fbe1a772f21599e91ab09eee8309 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 18:03:41 +0200 Subject: [PATCH 067/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 94fafc160..5a145fc7a 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1559,3 +1559,4 @@ Hans-Georg Böhm Tiberiu Atudorei Alessandro Apostoli (Yaapu!) Kenneth Bonerigo +Frits van Voorst From 61eb4705aceaedd937d55fb60578bae1b332d772 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 18:41:14 +0200 Subject: [PATCH 068/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 5a145fc7a..030da766b 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1560,3 +1560,4 @@ Tiberiu Atudorei Alessandro Apostoli (Yaapu!) Kenneth Bonerigo Frits van Voorst +Steven Dodge From 3652eefe4171efe73b432ce83b251a0295171544 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 21:06:22 +0200 Subject: [PATCH 069/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 030da766b..c76df4cef 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1561,3 +1561,4 @@ Alessandro Apostoli (Yaapu!) Kenneth Bonerigo Frits van Voorst Steven Dodge +Christian Buchinger From 59de2e4a762ec9487353688f975328086227882f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Sep 2019 21:07:03 +0200 Subject: [PATCH 070/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index c76df4cef..988740f23 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1562,3 +1562,4 @@ Kenneth Bonerigo Frits van Voorst Steven Dodge Christian Buchinger +Patrick Blanc From a6e212555f15f6a023c1d3378a4bdc3112686189 Mon Sep 17 00:00:00 2001 From: Kilrah Date: Fri, 27 Sep 2019 18:00:50 +0200 Subject: [PATCH 071/257] Tell nightly users that release is available for a few days (RC done manually) (cherry picked from commit 09d9906f18ed1e7e9e39d82dac4f5e793bb4b7ab) --- tools/nightly23/build-nightly.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nightly23/build-nightly.sh b/tools/nightly23/build-nightly.sh index 391f468ac..5e2a16515 100755 --- a/tools/nightly23/build-nightly.sh +++ b/tools/nightly23/build-nightly.sh @@ -36,7 +36,7 @@ docker exec companion sh -c "mkdir -p build && cd build && cmake /opentx/code && cp -f ${workdir}/binaries/stamp-opentx.txt ${output}/firmware # These radios are currently not enabled # echo "#define BLOCK \"x10,x12s\"" >> ${output}/firmware/stamp-opentx.txt -echo "#define ERROR \"MOVE_TO_RC\"" >> ${output}/firmware/stamp-opentx.txt +echo "#define ERROR \"MOVE_TO_RELEASE\"" >> ${output}/firmware/stamp-opentx.txt docker exec companion rm -rf build echo "Check if Linux companion is needed" From d6ddd407fb06fd7aab2565bcb034eee9169002b3 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 09:55:55 +0200 Subject: [PATCH 072/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 988740f23..bf345b864 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1563,3 +1563,4 @@ Frits van Voorst Steven Dodge Christian Buchinger Patrick Blanc +Darrell Carew From e3a12af4c357ddedef09ebec706c08a1f4819e4f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 09:56:28 +0200 Subject: [PATCH 073/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index bf345b864..e1b7804ce 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1564,3 +1564,4 @@ Steven Dodge Christian Buchinger Patrick Blanc Darrell Carew +Philippe Faure From c64f3de63fa57b4bfda763c7219182fd3bb7c0b3 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 09:57:05 +0200 Subject: [PATCH 074/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index e1b7804ce..4c4c4257b 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1565,3 +1565,4 @@ Christian Buchinger Patrick Blanc Darrell Carew Philippe Faure +Marco Lange From aa8a8928f14f33c3c748b82ec436fa72b1072456 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 09:57:21 +0200 Subject: [PATCH 075/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 4c4c4257b..40ffe10be 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1566,3 +1566,4 @@ Patrick Blanc Darrell Carew Philippe Faure Marco Lange +Aaron Tygart From 97743ed2f68b23c68fc4a1a0b462da7d8825bded Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 11:30:23 +0200 Subject: [PATCH 076/257] .idea folder stored on git --- .gitignore | 1 - .idea/.gitignore | 5 +++ .idea/.name | 1 + .idea/codeStyleSettings.xml | 57 ++++++++++++++++++++++++++++ .idea/codeStyles/Project.xml | 31 +++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 +++ .idea/encodings.xml | 6 +++ 7 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/.name create mode 100644 .idea/codeStyleSettings.xml create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/encodings.xml diff --git a/.gitignore b/.gitignore index 44f647bb5..26c155113 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/.idea/ /.*project /.settings /.autotools diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..f108063c7 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +*.iml +misc.xml +modules.xml +vcs.xml +workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 000000000..7a7d96690 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +OpenTX \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 000000000..cc9af5006 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,57 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 000000000..777209761 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,31 @@ + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 000000000..79ee123c2 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 000000000..22f558132 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From b8fa8438ba6c448c00ceee26529fab363553be17 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 28 Sep 2019 13:31:02 +0200 Subject: [PATCH 077/257] Multi telemetry : add Hitec and improve FlySky (#6835) * Add Hitec and update Flysky telemetry * Travis (and sky9x) doesn't like cheating ! * Cosmetics --- radio/src/dataconstants.h | 1 + radio/src/targets/common/arm/CMakeLists.txt | 2 +- radio/src/telemetry/flysky_ibus.cpp | 375 +++++++++++++---- radio/src/telemetry/flysky_ibus.h | 7 +- radio/src/telemetry/hitec.cpp | 433 ++++++++++++++++++++ radio/src/telemetry/hitec.h | 30 ++ radio/src/telemetry/multi.cpp | 130 +++--- radio/src/telemetry/telemetry.h | 1 + radio/src/telemetry/telemetry_sensors.cpp | 7 +- radio/src/translations/cz.h.txt | 15 + radio/src/translations/de.h.txt | 15 + radio/src/translations/en.h.txt | 15 + radio/src/translations/es.h.txt | 15 + radio/src/translations/fi.h.txt | 15 + radio/src/translations/fr.h.txt | 15 + radio/src/translations/it.h.txt | 15 + radio/src/translations/nl.h.txt | 15 + radio/src/translations/pl.h.txt | 15 + radio/src/translations/pt.h.txt | 15 + radio/src/translations/se.h.txt | 15 + radio/src/translations/untranslated.h | 2 +- 21 files changed, 1001 insertions(+), 152 deletions(-) create mode 100644 radio/src/telemetry/hitec.cpp create mode 100644 radio/src/telemetry/hitec.h diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index f4bc25566..4f98da7bd 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -264,6 +264,7 @@ enum TelemetryProtocol PROTOCOL_TELEMETRY_CROSSFIRE, PROTOCOL_TELEMETRY_SPEKTRUM, PROTOCOL_TELEMETRY_FLYSKY_IBUS, + PROTOCOL_TELEMETRY_HITEC, PROTOCOL_TELEMETRY_MULTIMODULE, PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_MULTIMODULE, PROTOCOL_TELEMETRY_LUA diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 04d30f936..063eb54fc 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -143,7 +143,7 @@ endif() if(MULTIMODULE) add_definitions(-DMULTIMODULE) - set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/multi.cpp io/multi_firmware_update.cpp) + set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/hitec.cpp telemetry/multi.cpp io/multi_firmware_update.cpp) endif() if(CROSSFIRE) diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index 208df3cac..77da922f0 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -16,127 +16,253 @@ #include "opentx.h" /* - * Telemetry format from goebish/Deviation/flysky_afhds2a_a7105.c - * - * format from RX: - * AA | TXID | RXID | sensor id | sensor # | value 16 bit big endian | sensor id ...... - * max 7 sensors per packet - * * TXID + RXID are already skipped in MULTI module to save memory+transmission time, format from Multi is: - * AA | TX_RSSI | sensor ... - * - * OpenTX Mapping - * - * instance = sensor id - * - * Additional sensors from https://github.com/cleanflight/cleanflight/blob/master/src/main/telemetry/ibus.c - * + * AA or AC | TX_RSSI | sensor ... */ -#define FLYSKY_TELEMETRY_LENGTH (2+7*4) +#define FLYSKY_TELEMETRY_LENGTH (2+7*4) // Should it be 2+7*6??? +#define ALT_PRECISION 15 +#define R_DIV_G_MUL_10_Q15 UINT64_C(9591506) +#define INV_LOG2_E_Q1DOT31 UINT64_C(0x58b90bfc) // Inverse log base 2 of e +#define PRESSURE_MASK 0x7FFFF -struct FlySkySensor { +struct FlySkySensor +{ const uint16_t id; - const char *name; + const char * name; const TelemetryUnit unit; const uint8_t precision; }; -#define TX_RSSI_ID 300 // Pseudo id outside 1 byte range of FlySky sensors -#define FS_ID_TEMP 0x01 -#define FS_ID_SNR 0xFA -#define FS_ID_NOISE 0xFB -#define FS_ID_RSSI 0xFC -#define FS_ID_ERR 0xFE +// telemetry sensors ID +enum +{ + AFHDS2A_ID_VOLTAGE = 0x00, // Internal Voltage + AFHDS2A_ID_TEMPERATURE = 0x01, // Temperature + AFHDS2A_ID_MOT = 0x02, // RPM + AFHDS2A_ID_EXTV = 0x03, // External Voltage + AFHDS2A_ID_CELL_VOLTAGE = 0x04, // Avg Cell voltage + AFHDS2A_ID_BAT_CURR = 0x05, // battery current A * 100 + AFHDS2A_ID_FUEL = 0x06, // remaining battery percentage / mah drawn otherwise or fuel level no unit! + AFHDS2A_ID_RPM = 0x07, // throttle value / battery capacity + AFHDS2A_ID_CMP_HEAD = 0x08, // Heading 0..360 deg, 0=north 2bytes + AFHDS2A_ID_CLIMB_RATE = 0x09, // 2 bytes m/s *100 signed + AFHDS2A_ID_COG = 0x0A, // 2 bytes Course over ground(NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. unknown max uint + AFHDS2A_ID_GPS_STATUS = 0x0B, // 2 bytes + AFHDS2A_ID_ACC_X = 0x0C, // 2 bytes m/s *100 signed + AFHDS2A_ID_ACC_Y = 0x0D, // 2 bytes m/s *100 signed + AFHDS2A_ID_ACC_Z = 0x0E, // 2 bytes m/s *100 signed + AFHDS2A_ID_ROLL = 0x0F, // 2 bytes deg *100 signed + AFHDS2A_ID_PITCH = 0x10, // 2 bytes deg *100 signed + AFHDS2A_ID_YAW = 0x11, // 2 bytes deg *100 signed + AFHDS2A_ID_VERTICAL_SPEED = 0x12, // 2 bytes m/s *100 signed + AFHDS2A_ID_GROUND_SPEED = 0x13, // 2 bytes m/s *100 different unit than build-in sensor + AFHDS2A_ID_GPS_DIST = 0x14, // 2 bytes distance from home m unsigned + AFHDS2A_ID_ARMED = 0x15, // 2 bytes + AFHDS2A_ID_FLIGHT_MODE = 0x16, // 2 bytes -const FlySkySensor flySkySensors[] = { + AFHDS2A_ID_PRES = 0x41, // Pressure + AFHDS2A_ID_ODO1 = 0x7C, // Odometer1 + AFHDS2A_ID_ODO2 = 0x7D, // Odometer2 + AFHDS2A_ID_SPE = 0x7E, // Speed 2 bytes km/h + AFHDS2A_ID_TX_V = 0x7F, // TX Voltage - // RX Voltage (remapped, really 0x0) - {0x100, ZSTR_A1, UNIT_VOLTS, 2}, - // Temperature - {FS_ID_TEMP, ZSTR_TEMP1, UNIT_CELSIUS, 1}, - // RPM - {0x02, ZSTR_RPM, UNIT_RAW, 0}, - // External voltage - {0x03, ZSTR_A3, UNIT_VOLTS, 2}, - // RX SNR - {FS_ID_SNR, ZSTR_RX_SNR, UNIT_DB, 0}, - // RX Noise - {FS_ID_NOISE, ZSTR_RX_NOISE, UNIT_DB, 0}, - // RX RSSI (0xfc) - {FS_ID_RSSI, ZSTR_RSSI, UNIT_DB, 0}, - // RX error rate - {FS_ID_ERR, ZSTR_RX_QUALITY, UNIT_RAW, 0}, - // 0xff is an unused sensor slot - // Pseudo sensor for TRSSI - {TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_RAW, 0}, - // sentinel - {0x00, NULL, UNIT_RAW, 0}, + AFHDS2A_ID_GPS_LAT = 0x80, // 4bytes signed WGS84 in degrees * 1E7 + AFHDS2A_ID_GPS_LON = 0x81, // 4bytes signed WGS84 in degrees * 1E7 + AFHDS2A_ID_GPS_ALT = 0x82, // 4bytes signed!!! GPS alt m*100 + AFHDS2A_ID_ALT = 0x83, // 4bytes signed!!! Alt m*100 + AFHDS2A_ID_S84 = 0x84, + AFHDS2A_ID_S85 = 0x85, + AFHDS2A_ID_S86 = 0x86, + AFHDS2A_ID_S87 = 0x87, + AFHDS2A_ID_S88 = 0x88, + AFHDS2A_ID_S89 = 0x89, + AFHDS2A_ID_S8a = 0x8A, + + AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX + AFHDS2A_ID_RX_SNR = 0xFA, // SNR + AFHDS2A_ID_RX_NOISE = 0xFB, // Noise + AFHDS2A_ID_RX_RSSI = 0xFC, // RSSI + AFHDS2A_ID_RX_ERR_RATE = 0xFE, // Error rate + AFHDS2A_ID_END = 0xFF, + + // AC type telemetry with multiple values in one packet + AFHDS2A_ID_GPS_FULL = 0xFD, + AFHDS2A_ID_VOLT_FULL = 0xF0, + AFHDS2A_ID_ACC_FULL = 0xEF, + TX_RSSI_ID = 0x200, // Pseudo id outside 1 byte range of FlySky sensors }; -static void processFlySkySensor(const uint8_t *packet) +const FlySkySensor flySkySensors[] = { + {AFHDS2A_ID_VOLTAGE | 0x100, ZSTR_A1, UNIT_VOLTS, 2}, // RX Voltage (remapped, really 0x0) + {AFHDS2A_ID_TEMPERATURE, ZSTR_TEMP1, UNIT_CELSIUS, 1}, // Temperature + {AFHDS2A_ID_MOT, ZSTR_RPM, UNIT_RAW, 0}, // RPM + {AFHDS2A_ID_EXTV, ZSTR_A3, UNIT_VOLTS, 2}, // External voltage + {AFHDS2A_ID_CELL_VOLTAGE, ZSTR_CELLS, UNIT_VOLTS, 2}, // Avg Cell voltage + {AFHDS2A_ID_BAT_CURR, ZSTR_CURR, UNIT_AMPS, 2}, // battery current A * 100 + {AFHDS2A_ID_FUEL, ZSTR_CAPACITY, UNIT_RAW, 0}, // remaining battery percentage / mah drawn otherwise or fuel level no unit! + {AFHDS2A_ID_RPM, ZSTR_RPM, UNIT_RAW, 0}, // throttle value / battery capacity + {AFHDS2A_ID_CMP_HEAD, ZSTR_HDG, UNIT_DEGREE, 0}, // Heading 0..360 deg, 0=north 2bytes + {AFHDS2A_ID_CLIMB_RATE, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2}, // 2 bytes m/s *100 + {AFHDS2A_ID_COG, ZSTR_HDG, UNIT_DEGREE, 2}, // 2 bytes Course over ground(NOT heading, but direction of movement) in degrees * 100, 0.0..359.99 degrees. unknown max uint + {AFHDS2A_ID_GPS_STATUS, ZSTR_SATELLITES, UNIT_RAW, 0}, // 2 bytes + {AFHDS2A_ID_ACC_X, ZSTR_ACCX, UNIT_METERS_PER_SECOND, 2}, // 2 bytes m/s *100 signed + {AFHDS2A_ID_ACC_Y, ZSTR_ACCY, UNIT_METERS_PER_SECOND, 2}, // 2 bytes m/s *100 signed + {AFHDS2A_ID_ACC_Z, ZSTR_ACCZ, UNIT_METERS_PER_SECOND, 2}, // 2 bytes m/s *100 signed + {AFHDS2A_ID_ROLL, ZSTR_ROLL, UNIT_DEGREE, 2}, // 2 bytes deg *100 signed + {AFHDS2A_ID_PITCH, ZSTR_PITCH, UNIT_DEGREE, 2}, // 2 bytes deg *100 signed + {AFHDS2A_ID_YAW, ZSTR_YAW, UNIT_DEGREE, 2}, // 2 bytes deg *100 signed + {AFHDS2A_ID_VERTICAL_SPEED, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 2}, // 2 bytes m/s *100 + {AFHDS2A_ID_GROUND_SPEED, ZSTR_GSPD, UNIT_METERS_PER_SECOND, 2}, // 2 bytes m/s *100 different unit than build-in sensor + {AFHDS2A_ID_GPS_DIST, ZSTR_DIST, UNIT_METERS, 0}, // 2 bytes dist from home m unsigned + {AFHDS2A_ID_ARMED, ZSTR_ARM, UNIT_RAW, 0}, // 2 bytes + {AFHDS2A_ID_FLIGHT_MODE, ZSTR_FLIGHT_MODE, UNIT_RAW, 0}, // 2 bytes index + {AFHDS2A_ID_PRES, ZSTR_PRES, UNIT_RAW, 2}, // 4 bytes In fact Temperature + Pressure -> Altitude + {AFHDS2A_ID_PRES | 0x100, ZSTR_TEMP2, UNIT_CELSIUS, 1}, // 2 bytes Temperature + {AFHDS2A_ID_ODO1, ZSTR_ODO1, UNIT_METERS, 2}, // 2 bytes Odometer1 -- some magic with 330 needed + {AFHDS2A_ID_ODO2, ZSTR_ODO2, UNIT_METERS, 2}, // 2 bytes Odometer2 -- some magic with 330 needed + {AFHDS2A_ID_SPE, ZSTR_ASPD, UNIT_KMH, 2}, // 2 bytes Speed km/h -- some magic with 330 needed + {AFHDS2A_ID_TX_V, ZSTR_TXV, UNIT_VOLTS, 2}, // TX Voltage + {AFHDS2A_ID_GPS_LAT, ZSTR_GPS, UNIT_RAW, 7}, // 4 bytes signed WGS84 in degrees * 1E7 + {AFHDS2A_ID_GPS_LON, ZSTR_GPS, UNIT_RAW, 7}, // 4 bytes signed WGS84 in degrees * 1E7 + {AFHDS2A_ID_GPS_ALT, ZSTR_GPSALT, UNIT_METERS, 2}, // 4 bytes signed GPS alt m*100 + {AFHDS2A_ID_ALT, ZSTR_ALT, UNIT_METERS, 2}, // 4 bytes signed Alt m*100 + + {AFHDS2A_ID_RX_SNR, ZSTR_RX_SNR, UNIT_DB, 0}, // RX SNR + {AFHDS2A_ID_RX_NOISE, ZSTR_RX_NOISE, UNIT_DB, 0}, // RX Noise + {AFHDS2A_ID_RX_RSSI, ZSTR_RSSI, UNIT_DB, 0}, // RX RSSI (0xfc) + {AFHDS2A_ID_RX_ERR_RATE, ZSTR_RX_QUALITY, UNIT_RAW, 0}, // RX error rate + {TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_RAW, 0}, // Pseudo sensor for TRSSI + + {0x00, NULL, UNIT_RAW, 0}, // sentinel +}; + +int32_t getALT(uint32_t value); + +static void processFlySkySensor(const uint8_t * packet, uint8_t type) { + uint8_t buffer[8]; uint16_t id = packet[0]; const uint8_t instance = packet[1]; - int32_t value = (packet[3] << 8) + packet[2]; + int32_t value; - if (id == 0xff) { - // No sensor - return; + //Load most likely value + if (type == 0xAA) + value = (packet[3] << 8) | packet[2]; + else + value = (packet[6] << 24) | (packet[5] << 16) | (packet[4] << 8) | packet[3]; + + if (id == 0) id = 0x100; // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100 + + if (id == AFHDS2A_ID_RX_NOISE || id == AFHDS2A_ID_RX_RSSI) { + value = 135 - value; } - - if (id == 0) { - // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100 - id = 0x100; - } - - if (id == FS_ID_ERR) { // ERR RATE, displayed RQLy and used as RSSI + else if (id == AFHDS2A_ID_RX_ERR_RATE) { value = 100 - value; telemetryData.rssi.set(value); - if (value > 0) - telemetryStreaming = TELEMETRY_TIMEOUT10ms; + if (value > 0) telemetryStreaming = TELEMETRY_TIMEOUT10ms; } - - for (const FlySkySensor * sensor = flySkySensors; sensor->id; sensor++) { - // Extract value, skip header - if (sensor->id == id) { - // The Noise and Signal sensors that are specified in dB send the absolute value - if (id == FS_ID_NOISE || id == FS_ID_RSSI) - value = 135 - value; - else if (id == FS_ID_SNR) { - if (value > 0) { - value += 20; - } - } - else if (id == FS_ID_TEMP) - // Temperature sensors have 40 degree offset - value -= 400; - else if (sensor->unit == UNIT_VOLTS) - // Voltage types are signed 16bit integers - value = (int16_t)value; - setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id, 0, instance, value, sensor->unit, sensor->precision); - return; + else if (id == AFHDS2A_ID_PRES && value) { + // Extract temperature to a new sensor + setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id | 0x100, 0, instance, ((value >> 19) - 400), UNIT_CELSIUS, 1); + // Extract alt to a new sensor + setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, AFHDS2A_ID_ALT, 0, instance, getALT(value), UNIT_METERS, 2); + value &= PRESSURE_MASK; + } + else if ((id >= AFHDS2A_ID_ACC_X && id <= AFHDS2A_ID_VERTICAL_SPEED) || id == AFHDS2A_ID_CLIMB_RATE) { + value = (int16_t) value; // Signed value + } + else if (id == AFHDS2A_ID_GPS_STATUS) { + value = value >> 8; + } + else if (id == AFHDS2A_ID_GPS_FULL) { + //(AC FRAME)[ID][inst][size][fix][sats][LAT]x4[LON]x4[ALT]x4 + setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, AFHDS2A_ID_GPS_STATUS, 0, instance, packet[4], UNIT_RAW, 0); + for (uint8_t sensorID = AFHDS2A_ID_GPS_LAT; sensorID <= AFHDS2A_ID_GPS_ALT; sensorID++) { + int index = 5 + (sensorID - AFHDS2A_ID_GPS_LAT) * 4; + buffer[0] = sensorID; + buffer[1] = instance; + buffer[2] = 4; + memcpy(buffer + 3, packet + index, 4); + processFlySkySensor(buffer, 0xAC); } + return; } + else if (id == AFHDS2A_ID_VOLT_FULL) { + //(AC FRAME)[ID][inst][size][ACC_X]x2[ACC_Y]x2[ACC_Z]x2[ROLL]x2[PITCH]x2[YAW]x2 + for (uint8_t sensorID = AFHDS2A_ID_EXTV; sensorID <= AFHDS2A_ID_RPM; sensorID++) { + int index = 3 + (sensorID - AFHDS2A_ID_EXTV) * 2; + buffer[0] = sensorID; + buffer[1] = instance; + buffer[2] = packet[index]; + buffer[3] = packet[index + 1]; + processFlySkySensor(buffer, 0xAA); + } + return; + } + else if (id == AFHDS2A_ID_ACC_FULL) { + //(AC FRAME)[ID][inst][size] + for (uint8_t sensorID = AFHDS2A_ID_ACC_X; sensorID <= AFHDS2A_ID_YAW; sensorID++) { + int index = 3 + (sensorID - AFHDS2A_ID_ACC_X) * 2; + buffer[0] = sensorID; + buffer[1] = instance; + buffer[2] = packet[index]; + buffer[3] = packet[index + 1]; + processFlySkySensor(buffer, 0xAA); + } + return; + } + for (const FlySkySensor * sensor = flySkySensors; sensor->id; sensor++) { + if (sensor->id != id) continue; + if (sensor->unit == UNIT_CELSIUS) value -= 400; // Temperature sensors have 40 degree offset + else if (sensor->unit == UNIT_VOLTS) value = (uint16_t) value; // Voltage types are unsigned 16bit integers + setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id, 0, instance, value, sensor->unit, sensor->precision); + return; + } + //unknown setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, id, 0, instance, value, UNIT_RAW, 0); } -void processFlySkyPacket(const uint8_t *packet) +void processFlySkyPacket(const uint8_t * packet) { // Set TX RSSI Value, reverse MULTIs scaling setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, TX_RSSI_ID, 0, 0, packet[0], UNIT_RAW, 0); - for (int sensor = 0; sensor < 7; sensor++) { - int index = 1 + (4 * sensor); - processFlySkySensor(packet+index); + const uint8_t * buffer = packet + 1; + int sesnor = 0; + while (sesnor++ < 7) { + if (*buffer == AFHDS2A_ID_END) break; + processFlySkySensor(buffer, 0xAA); + buffer += 4; } } -void processFlySkyTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount) +void processFlySkyPacketAC(const uint8_t * packet) { - if (rxBufferCount == 0 && data != 0xAA) { + // Set TX RSSI Value, reverse MULTIs scaling + setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, TX_RSSI_ID, 0, 0, packet[0], UNIT_RAW, 0); + const uint8_t * buffer = packet + 1; + while (buffer - packet < 26) //28 + 1(multi TX rssi) - 3(ac header) + { + if (*buffer == AFHDS2A_ID_END) break; + uint8_t size = buffer[2]; + processFlySkySensor(buffer, 0xAC); + buffer += size + 3; + } +} + +void processFlySkyTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBufferCount) +{ + if (rxBufferCount == 0) + return; + + if (data == 0xAA || data == 0xAC) { + TRACE("[IBUS] Packet 0x%02X", data); + } + else { TRACE("[IBUS] invalid start byte 0x%02X", data); + rxBufferCount = 0; return; } @@ -148,24 +274,23 @@ void processFlySkyTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBuff rxBufferCount = 0; } - if (rxBufferCount >= FLYSKY_TELEMETRY_LENGTH) { // debug print the content of the packets #if 0 - debugPrintf("[IBUS] Packet 0x%02X rssi 0x%02X: ", - rxBuffer[0], rxBuffer[1]); + debugPrintf(", rssi 0x%02X: ", rxBuffer[1]); for (int i=0; i<7; i++) { debugPrintf("[%02X %02X %02X%02X] ", rxBuffer[i*4+2], rxBuffer[i*4 + 3], rxBuffer[i*4 + 4], rxBuffer[i*4 + 5]); } debugPrintf("\r\n"); #endif - processFlySkyPacket(rxBuffer+1); + if (data == 0xAA) processFlySkyPacket(rxBuffer + 1); + else if (data == 0xAC) processFlySkyPacketAC(rxBuffer + 1); rxBufferCount = 0; } } -const FlySkySensor *getFlySkySensor(uint16_t id) +const FlySkySensor * getFlySkySensor(uint16_t id) { for (const FlySkySensor * sensor = flySkySensors; sensor->id; sensor++) { if (id == sensor->id) @@ -181,7 +306,7 @@ void flySkySetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance) telemetrySensor.subId = subId; telemetrySensor.instance = instance; - const FlySkySensor *sensor = getFlySkySensor(id); + const FlySkySensor * sensor = getFlySkySensor(id); if (sensor) { TelemetryUnit unit = sensor->unit; uint8_t prec = min(2, sensor->precision); @@ -198,3 +323,71 @@ void flySkySetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance) storageDirty(EE_MODEL); } + +uint16_t ibusTempToK(int16_t tempertureIbus) +{ + return (uint16_t) (tempertureIbus - 400) + 2731; +} + +int32_t log2fix(uint32_t x) +{ + int32_t b = 1U << (ALT_PRECISION - 1); + int32_t y = 0; + while (x < 1U << ALT_PRECISION) { + x <<= 1; + y -= 1U << ALT_PRECISION; + } + + while (x >= 2U << ALT_PRECISION) { + x >>= 1; + y += 1U << ALT_PRECISION; + } + + uint64_t z = x; + for (size_t i = 0; i < ALT_PRECISION; i++) { + z = (z * z) >> ALT_PRECISION; + if (z >= 2U << ALT_PRECISION) { + z >>= 1; + y += b; + } + b >>= 1; + } + return y; +} + +int32_t getALT(uint32_t value) +{ + uint32_t pressurePa = value & PRESSURE_MASK; + if (pressurePa == 0) return 0; + uint16_t temperatureK = ibusTempToK((uint16_t) (value >> 19)); + static uint32_t initPressure = 0; + static uint16_t initTemperature = 0; + if (initPressure <= 0) // use current pressure for ground altitude -> 0 + { + initPressure = pressurePa; + initTemperature = temperatureK; + } + int temperature = (initTemperature + temperatureK) >> 1; //div 2 + bool tempNegative = temperature < 0; + if (tempNegative) temperature = temperature * -1; + uint64_t helper = R_DIV_G_MUL_10_Q15; + helper = helper * (uint64_t) temperature; + helper = helper >> ALT_PRECISION; + + uint32_t po_to_p = (uint32_t)(initPressure << (ALT_PRECISION - 1)); + po_to_p = po_to_p / pressurePa; + //shift missing bit + po_to_p = po_to_p << 1; + if (po_to_p == 0) return 0; + uint64_t t = log2fix(po_to_p) * INV_LOG2_E_Q1DOT31; + int32_t ln = t >> 31; + + bool neg = ln < 0; + if (neg) ln = ln * -1; + helper = helper * (uint64_t) ln; + helper = helper >> ALT_PRECISION; + int result = (int) helper; + + if (neg ^ tempNegative) result = result * -1; + return result; +} \ No newline at end of file diff --git a/radio/src/telemetry/flysky_ibus.h b/radio/src/telemetry/flysky_ibus.h index f952f7968..bfb0db640 100644 --- a/radio/src/telemetry/flysky_ibus.h +++ b/radio/src/telemetry/flysky_ibus.h @@ -21,11 +21,14 @@ #ifndef _FLYSKY_IBUS_H #define _FLYSKY_IBUS_H -void processFlySkyTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount); +void processFlySkyTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBufferCount); + void flySkySetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance); // Used by multi protocol -void processFlySkyPacket(const uint8_t *packet); +void processFlySkyPacket(const uint8_t * packet); + +void processFlySkyPacketAC(const uint8_t * packet); #endif diff --git a/radio/src/telemetry/hitec.cpp b/radio/src/telemetry/hitec.cpp new file mode 100644 index 000000000..93a0f6a37 --- /dev/null +++ b/radio/src/telemetry/hitec.cpp @@ -0,0 +1,433 @@ +/* + * 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. + */ + +#include "opentx.h" + +/* Full telemetry +packet[0] = TX RSSI value +packet[1] = TX LQI value +packet[2] = frame number +packet[3-7] telemetry data + +The frame number takes the following values: 0x00, 0x11, 0x12, ..., 0x1C. The frames can be present or not, they also do not have to follow each others. +Here is a description of the telemetry data for each frame number: +- frame 0x00 +data byte 0 -> 0x00 unknown +data byte 1 -> 0x00 unknown +data byte 2 -> 0x00 unknown +data byte 3 -> RX Batt Volt_H +data byte 4 -> RX Batt Volt_L => RX Batt=(Volt_H*256+Volt_L)/28 +- frame 0x11 +data byte 0 -> 0xAF start of frame +data byte 1 -> 0x00 unknown +data byte 2 -> 0x2D station type 0x2D=standard station nitro or electric, 0xAC=advanced station +data byte 3 -> RX Batt Volt_H +data byte 4 -> RX Batt Volt_L => RX Batt=(Volt_H*256+Volt_L)/28 +- frame 0x12 +data byte 0 -> Lat_sec_H GPS : latitude second +data byte 1 -> Lat_sec_L signed int : 1/100 of second +data byte 2 -> Lat_deg_min_H GPS : latitude degree.minute +data byte 3 -> Lat_deg_min_L signed int : +=North, - = south +data byte 4 -> Time_second GPS Time +- frame 0x13 +data byte 0 -> GPS Longitude second +data byte 1 -> signed int : 1/100 of second +data byte 2 -> GPS Longitude degree.minute +data byte 3 -> signed int : +=Est, - = west +data byte 4 -> Temp2 Temperature2=Temp2-40°C +- frame 0x14 +data byte 0 -> Speed_H +data byte 1 -> Speed_L GPS Speed=Speed_H*256+Speed_L km/h +data byte 2 -> Alti_sea_H +data byte 3 -> Alti_sea_L GPS Altitude=Alti_sea_H*256+Alti_sea_L m +data byte 4 -> Temp1 Temperature1=Temp1-40°C +- frame 0x15 +data byte 0 -> FUEL +data byte 1 -> RPM1_L +data byte 2 -> RPM1_H RPM1=RPM1_H*256+RPM1_L +data byte 3 -> RPM2_L +data byte 4 -> RPM2_H RPM2=RPM2_H*256+RPM2_L +- frame 0x16 +data byte 0 -> Date_year GPS Date +data byte 1 -> Date_month +data byte 2 -> Date_day +data byte 3 -> Time_hour GPS Time +data byte 4 -> Time_min +- frame 0x17 +data byte 0 -> COURSEH +data byte 1 -> COURSEL GPS heading = COURSEH*256+COURSEL in degrees +data byte 2 -> Count GPS satellites +data byte 3 -> Temp3 Temperature3=Temp2-40°C +data byte 4 -> Temp4 Temperature4=Temp3-40°C +- frame 0x18 +data byte 0 -> Volt_L Volt=(Volt_H*256+Volt_L)/10 V +data byte 1 -> Volt_H +data byte 2 -> AMP_L +data byte 3 -> AMP_H Amp=(AMP1_*256+AMP_L -180)/14 in signed A +- frame 0x19 Servo sensor +data byte 0 -> AMP_Servo1 Amp=AMP_Servo1/10 in A +data byte 1 -> AMP_Servo2 Amp=AMP_Servo2/10 in A +data byte 2 -> AMP_Servo3 Amp=AMP_Servo3/10 in A +data byte 3 -> AMP_Servo4 Amp=AMP_Servo4/10 in A +- frame 0x1A +data byte 2 -> ASpeed_H Air speed=ASpeed_H*256+ASpeed_L km/h +data byte 3 -> ASpeed_L +- frame 0x1B Variometer sensor +data byte 0 -> Alti1H +data byte 1 -> Alti1L Altitude unfiltered +data byte 2 -> Alti2H +data byte 3 -> Alti2L Altitude filtered +- frame 0x1C Unknown +- frame 0x22 Unknown +*/ + +#define HITEC_TELEMETRY_LENGTH 8 + +struct HitecSensor +{ + const uint16_t id; + const char * name; + const TelemetryUnit unit; + const uint8_t precision; +}; + +// telemetry frames +enum +{ + HITEC_FRAME_00 = 0x00, + HITEC_FRAME_11 = 0x11, + HITEC_FRAME_12 = 0x12, + HITEC_FRAME_13 = 0x13, + HITEC_FRAME_14 = 0x14, + HITEC_FRAME_15 = 0x15, + HITEC_FRAME_16 = 0x16, + HITEC_FRAME_17 = 0x17, + HITEC_FRAME_18 = 0x18, + HITEC_FRAME_19 = 0x19, + HITEC_FRAME_1A = 0x1A, + HITEC_FRAME_1B = 0x1B, + HITEC_FRAME_1C = 0x1C, + HITEC_FRAME_22 = 0x22, +}; + +// telemetry sensors ID +enum +{ + HITEC_ID_RX_VOLTAGE = 0x0003, // RX_Batt Voltage + HITEC_ID_GPS_LAT_LONG = 0x1200, // GPS latitude longitude + HITEC_ID_TEMP2 = 0x1304, // Temperature sensor 2 + HITEC_ID_GPS_SPEED = 0x1400, // GPS speed + HITEC_ID_GPS_ALTITUDE = 0x1402, // GPS altitude sea level + HITEC_ID_TEMP1 = 0x1404, // Temperature sensor 1 + HITEC_ID_FUEL = 0x1500, // Fuel + HITEC_ID_RPM1 = 0x1501, // RPM1 + HITEC_ID_RPM2 = 0x1503, // RPM2 + HITEC_ID_GPS_DATETIME = 0x1600, // GPS date time + HITEC_ID_GPS_HEADING = 0x1700, // GPS heading + HITEC_ID_GPS_COUNT = 0x1702, // GPS count + HITEC_ID_TEMP3 = 0x1703, // Temperature sensor 3 + HITEC_ID_TEMP4 = 0x1704, // Temperature sensor 4 + HITEC_ID_VOLTAGE = 0x1800, // Voltage sensor + HITEC_ID_AMP = 0x1802, // Amp sensor + HITEC_ID_C50 = 0x1803, // Amp sensor C50 + HITEC_ID_C200 = 0x1804, // Amp sensor C200 + HITEC_ID_AMP_S1 = 0x1900, // Amp servo 1 sensor + HITEC_ID_AMP_S2 = 0x1901, // Amp servo 2 sensor + HITEC_ID_AMP_S3 = 0x1902, // Amp servo 3 sensor + HITEC_ID_AMP_S4 = 0x1903, // Amp servo 4 sensor + HITEC_ID_AIR_SPEED = 0x1A02, // Air speed + HITEC_ID_VARIO = 0x1B00, // Vario + HITEC_ID_ALT = 0x1B02, // Vario + TX_RSSI_ID = 0xFF00, // Pseudo id outside 1 byte range of Hitec sensors + TX_LQI_ID = 0xFF01, // Pseudo id outside 1 byte range of Hitec sensors +}; + +const HitecSensor hitecSensors[] = { + //frame 00 + {HITEC_ID_RX_VOLTAGE, ZSTR_BATT, UNIT_VOLTS, 2}, // RX_Batt Voltage + //frame 11 + //frame 12 + {HITEC_ID_GPS_LAT_LONG, ZSTR_GPS, UNIT_GPS, 0}, // GPS position + //frame 13 + {HITEC_ID_TEMP2, ZSTR_TEMP2, UNIT_CELSIUS, 0}, // Temperature sensor 2 + //frame 14 + {HITEC_ID_GPS_SPEED, ZSTR_GSPD, UNIT_KMH, 0}, // GPS speed + {HITEC_ID_GPS_ALTITUDE, ZSTR_GPSALT, UNIT_METERS, 0}, // GPS altitude sea level + {HITEC_ID_TEMP1, ZSTR_TEMP1, UNIT_CELSIUS, 0}, // Temperature sensor 1 + //frame 15 + {HITEC_ID_FUEL, ZSTR_FUEL, UNIT_PERCENT, 0}, // Fuel + {HITEC_ID_RPM1, ZSTR_RPM, UNIT_RPMS, 0}, // RPM1 + {HITEC_ID_RPM2, ZSTR_RPM2, UNIT_RPMS, 0}, // RPM2 + //frame 16 + {HITEC_ID_GPS_DATETIME, ZSTR_GPS, UNIT_DATETIME, 0}, // GPS date time + //frame 17 + {HITEC_ID_GPS_HEADING, ZSTR_HDG, UNIT_DEGREE, 0}, // GPS Heading + {HITEC_ID_GPS_COUNT, ZSTR_SATELLITES, UNIT_RAW, 0}, // GPS count + {HITEC_ID_TEMP3, ZSTR_TEMP3, UNIT_CELSIUS, 0}, // Temperature sensor 3 + {HITEC_ID_TEMP4, ZSTR_TEMP4, UNIT_CELSIUS, 0}, // Temperature sensor 4 + //frame 18 + {HITEC_ID_VOLTAGE, ZSTR_A1, UNIT_VOLTS, 1}, // Voltage sensor + {HITEC_ID_AMP, ZSTR_CURR, UNIT_AMPS, 0}, // Amp sensor + {HITEC_ID_C50, ZSTR_C50, UNIT_AMPS, 1}, // Amp sensor C50 + {HITEC_ID_C200, ZSTR_C200, UNIT_AMPS, 0}, // Amp sensor C200 + //frame 19 + {HITEC_ID_AMP_S1, ZSTR_CURR_SERVO1, UNIT_AMPS, 1}, // Amp sensor + {HITEC_ID_AMP_S2, ZSTR_CURR_SERVO2, UNIT_AMPS, 1}, // Amp sensor + {HITEC_ID_AMP_S3, ZSTR_CURR_SERVO3, UNIT_AMPS, 1}, // Amp sensor + {HITEC_ID_AMP_S4, ZSTR_CURR_SERVO4, UNIT_AMPS, 1}, // Amp sensor + //frame 1A + {HITEC_ID_AIR_SPEED, ZSTR_ASPD, UNIT_KMH, 0}, // Air speed + //frame 1B + {HITEC_ID_VARIO, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 1}, // Vario + {HITEC_ID_ALT, ZSTR_ALT, UNIT_METERS, 1}, // Altitude + + {TX_RSSI_ID, ZSTR_TX_RSSI, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hitec sensors + {TX_LQI_ID, ZSTR_TX_QUALITY, UNIT_RAW, 0}, // Pseudo id outside 1 byte range of Hitec sensors// Pseudo sensor for TLQI + {0x00, NULL, UNIT_RAW, 0}, // sentinel +}; + +const HitecSensor * getHitecSensor(uint16_t id) +{ + for (const HitecSensor * sensor = hitecSensors; sensor->id; sensor++) { + if (id == sensor->id) + return sensor; + } + return nullptr; +} + +void processHitecPacket(const uint8_t * packet) +{ + static uint16_t rssi = 0, lqi = 0; + // Set TX RSSI Value, reverse MULTIs scaling + rssi = ((packet[0] * 10) + (rssi * 90)) / 100; // quick filtering + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, TX_RSSI_ID, 0, 0, rssi >> 1, UNIT_RAW, 0); + telemetryData.rssi.set(rssi >> 1); + if (packet[0] > 0) telemetryStreaming = TELEMETRY_TIMEOUT10ms; + // Set TX LQI Value, reverse MULTIs scaling + lqi = ((packet[1] * 10) + (lqi * 90)) / 100; // quick filtering + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, TX_LQI_ID, 0, 0, lqi, UNIT_RAW, 0); + + const HitecSensor * sensor; + int32_t value, deg, min, sec, alt, amp; + static uint8_t second = 0; + static int32_t last_alt = 0; + static uint16_t last_ms = 0; + uint16_t current_ms; + + switch (packet[2]) { + case HITEC_FRAME_00: + value = (((packet[6] << 8) | packet[7]) * 100) / 28; + sensor = getHitecSensor(HITEC_ID_RX_VOLTAGE); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_RX_VOLTAGE, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_11: + value = (((packet[6] << 8) | packet[7]) * 100) / 28; + sensor = getHitecSensor(HITEC_ID_RX_VOLTAGE); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_RX_VOLTAGE, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_12: + //value=(packet[5]<<24)|(packet[6]<<16)|(packet[3]<<8)|packet[4]; + min = (int16_t) ((packet[5] << 8) | packet[6]); + deg = min / 100; + min = min - deg * 100; + sec = (int16_t) ((packet[3] << 8) | packet[4]); + value = deg * 1000000 + (min * 150000 + sec * 25) / 9; + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_LAT_LONG, 0, 0, value, UNIT_GPS_LATITUDE, 0); + second = packet[7]; + return; + case HITEC_FRAME_13: + //value=(packet[5]<<24)|(packet[6]<<16)|(packet[3]<<8)|packet[4]; + min = (int16_t) ((packet[5] << 8) | packet[6]); + deg = min / 100; + min = min - deg * 100; + sec = (int16_t) ((packet[3] << 8) | packet[4]); + value = deg * 1000000 + (min * 150000 + sec * 25) / 9; + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_LAT_LONG, 0, 0, value, UNIT_GPS_LONGITUDE, 0); + value = packet[7] - 40; + sensor = getHitecSensor(HITEC_ID_TEMP2); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_TEMP2, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_14: + value = (packet[3] << 8) | packet[4]; + sensor = getHitecSensor(HITEC_ID_GPS_SPEED); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_SPEED, 0, 0, value, sensor->unit, sensor->precision); + value = (packet[5] << 8) | packet[6]; + sensor = getHitecSensor(HITEC_ID_GPS_ALTITUDE); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_ALTITUDE, 0, 0, value, sensor->unit, sensor->precision); + value = packet[7] - 40; + sensor = getHitecSensor(HITEC_ID_TEMP1); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_TEMP1, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_15: + value = packet[3] * 25; + if (value > 100) value = 100; + sensor = getHitecSensor(HITEC_ID_FUEL); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_FUEL, 0, 0, value, sensor->unit, sensor->precision); + value = (packet[5] << 8) | packet[4]; + sensor = getHitecSensor(HITEC_ID_RPM1); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_RPM1, 0, 0, value, sensor->unit, sensor->precision); + value = (packet[7] << 8) | packet[6]; + sensor = getHitecSensor(HITEC_ID_RPM2); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_RPM2, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_16: + sensor = getHitecSensor(HITEC_ID_GPS_DATETIME); + value = (packet[3] << 24) | (packet[4] << 16) | (packet[5] << 8) | 0x01; + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_DATETIME, 0, 0, value, sensor->unit, sensor->precision); + value = (packet[6] << 24) | (packet[7] << 16) | (second << 8); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_DATETIME, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_17: + value = (packet[3] << 8) | packet[4]; + if (value <= 359) { // Filter strange values received time to time + sensor = getHitecSensor(HITEC_ID_GPS_HEADING); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_HEADING, 0, 0, value, sensor->unit, sensor->precision); + } + value = packet[5]; + sensor = getHitecSensor(HITEC_ID_GPS_COUNT); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_GPS_COUNT, 0, 0, value, sensor->unit, sensor->precision); + value = packet[6] - 40; + sensor = getHitecSensor(HITEC_ID_TEMP3); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_TEMP3, 0, 0, value, sensor->unit, sensor->precision); + value = packet[7] - 40; + sensor = getHitecSensor(HITEC_ID_TEMP4); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_TEMP4, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_18: + value = (packet[4] << 8) | packet[3]; + if (value) value += 2; // Measured voltage seems to be 0.2V lower than real + sensor = getHitecSensor(HITEC_ID_VOLTAGE); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_VOLTAGE, 0, 0, value, sensor->unit, sensor->precision); + //I'm adding below 3 amp sensors but there is only one really since I don't know how to really calculate them + value = (int16_t) ((packet[6] << 8) | packet[5]); + sensor = getHitecSensor(HITEC_ID_AMP); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_AMP, 0, 0, value, sensor->unit, sensor->precision); + amp = ((value + 114.875) * 1.441) + 0.5; + sensor = getHitecSensor(HITEC_ID_C50); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_C50, 0, 0, amp, sensor->unit, sensor->precision); + amp = value * 3 + 165; + sensor = getHitecSensor(HITEC_ID_C200); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_C200, 0, 0, amp, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_19: + value = packet[3]; + sensor = getHitecSensor(HITEC_ID_AMP_S1); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_AMP_S1, 0, 0, value, sensor->unit, sensor->precision); + value = packet[4]; + sensor = getHitecSensor(HITEC_ID_AMP_S2); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_AMP_S2, 0, 0, value, sensor->unit, sensor->precision); + value = packet[5]; + sensor = getHitecSensor(HITEC_ID_AMP_S3); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_AMP_S3, 0, 0, value, sensor->unit, sensor->precision); + value = packet[6]; + sensor = getHitecSensor(HITEC_ID_AMP_S4); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_AMP_S4, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_1A: + value = (packet[5] << 8) | packet[6]; + sensor = getHitecSensor(HITEC_ID_AIR_SPEED); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_AIR_SPEED, 0, 0, value, sensor->unit, sensor->precision); + return; + case HITEC_FRAME_1B: + alt = (int16_t) ((packet[3] << 8) | packet[4]); + sensor = getHitecSensor(HITEC_ID_ALT); + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_ALT, 0, 0, alt, sensor->unit, sensor->precision); + current_ms = RTOS_GET_MS(); + sensor = getHitecSensor(HITEC_ID_VARIO); + value = (alt - last_alt) * 100; + if ((current_ms - last_ms) < 1000) + value /= (int32_t) (current_ms - last_ms); + else + value = 0; + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, HITEC_ID_VARIO, 0, 0, value, sensor->unit, sensor->precision); + last_alt = alt; + last_ms = current_ms; + return; + case HITEC_FRAME_1C: + case HITEC_FRAME_22: + return; + } + //unknown + value = (packet[6] << 24) | (packet[5] << 16) | (packet[4] << 8) | packet[3]; + setTelemetryValue(PROTOCOL_TELEMETRY_HITEC, packet[2], 0, 0, value, UNIT_RAW, 0); +} + +void processHitecTelemetryData(uint8_t data, uint8_t * rxBuffer, uint8_t &rxBufferCount) +{ + if (rxBufferCount == 0) + return; + + if (data != 0xAA) { + TRACE("[HITEC] invalid start byte 0x%02X", data); + rxBufferCount = 0; + return; + } + + if (rxBuffer[3] == HITEC_FRAME_00 || (rxBuffer[3] >= HITEC_FRAME_11 && rxBuffer[3] <= HITEC_FRAME_1C) || rxBuffer[3] == HITEC_FRAME_22) { + TRACE("[HITEC] Frame 0x%02X", rxBuffer[3]); + } + else { + TRACE("[HITEC] wrong frame 0x%02X", rxBuffer[3]); + rxBufferCount = 0; + return; + } + + if (rxBufferCount < TELEMETRY_RX_PACKET_SIZE) { + rxBuffer[rxBufferCount++] = data; + } + else { + TRACE("[HITEC] array size %d error", rxBufferCount); + rxBufferCount = 0; + return; + } + + if (rxBufferCount >= HITEC_TELEMETRY_LENGTH) { + // debug print the content of the packets +#if 0 + debugPrintf(" rssi 0x%02X lqi 0x%02X: ", + rxBuffer[1], rxBuffer[2]); + for (int i=0; i<5; i++) { + debugPrintf("%02X ", rxBuffer[4+i]); + } + debugPrintf("\r\n"); +#endif + processHitecPacket(rxBuffer + 1); + rxBufferCount = 0; + } +} + +void hitecSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance) +{ + TelemetrySensor &telemetrySensor = g_model.telemetrySensors[index]; + telemetrySensor.id = id; + telemetrySensor.subId = subId; + telemetrySensor.instance = instance; + + const HitecSensor * sensor = getHitecSensor(id); + if (sensor) { + TelemetryUnit unit = sensor->unit; + uint8_t prec = min(2, sensor->precision); + telemetrySensor.init(sensor->name, unit, prec); + if (unit == UNIT_RPMS) { + telemetrySensor.custom.ratio = 1; + telemetrySensor.custom.offset = 1; + } + } + else { + telemetrySensor.init(id); + } + + storageDirty(EE_MODEL); +} diff --git a/radio/src/telemetry/hitec.h b/radio/src/telemetry/hitec.h new file mode 100644 index 000000000..d4c851f4c --- /dev/null +++ b/radio/src/telemetry/hitec.h @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#ifndef _HITEC_H +#define _HITEC_H + +void processHitecTelemetryData(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount); +void hitecSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance); + +// Used by multi protocol +void processHitecPacket(const uint8_t *packet); + +#endif diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index c8e4c7867..13f638faa 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -21,7 +21,8 @@ #include "telemetry.h" #include "multi.h" -enum MultiPacketTypes : uint8_t { +enum MultiPacketTypes : uint8_t +{ MultiStatus = 1, FrSkySportTelemtry, FrSkyHubTelemetry, @@ -30,10 +31,14 @@ enum MultiPacketTypes : uint8_t { FlyskyIBusTelemetry, ConfigCommand, InputSync, - FrskySportPolling + FrskySportPolling, + HitecTelemetry, + SpectrumScannerPacket, + FlyskyIBusTelemetryAC }; -enum MultiBufferState : uint8_t { +enum MultiBufferState : uint8_t +{ NoProtocolDetected, MultiFirstByteReceived, ReceivingMultiProtocol, @@ -43,24 +48,25 @@ enum MultiBufferState : uint8_t { FrskyTelemetryFallbackFirstByte, FrskyTelemetryFallbackNextBytes, FlyskyTelemetryFallback, + HitecTelemetryFallback, MultiStatusOrFrskyData }; #if defined(INTERNAL_MODULE_MULTI) -static MultiModuleStatus multiModuleStatus[NUM_MODULES] = { MultiModuleStatus(), MultiModuleStatus() }; -static MultiModuleSyncStatus multiSyncStatus[NUM_MODULES] = { MultiModuleSyncStatus(), MultiModuleSyncStatus() }; -static uint8_t multiBindStatus[NUM_MODULES] = { MULTI_NORMAL_OPERATION, MULTI_NORMAL_OPERATION }; +static MultiModuleStatus multiModuleStatus[NUM_MODULES] = {MultiModuleStatus(), MultiModuleStatus()}; +static MultiModuleSyncStatus multiSyncStatus[NUM_MODULES] = {MultiModuleSyncStatus(), MultiModuleSyncStatus()}; +static uint8_t multiBindStatus[NUM_MODULES] = {MULTI_NORMAL_OPERATION, MULTI_NORMAL_OPERATION}; static MultiBufferState multiTelemetryBufferState[NUM_MODULES]; -MultiModuleStatus& getMultiModuleStatus(uint8_t module) +MultiModuleStatus &getMultiModuleStatus(uint8_t module) { return multiModuleStatus[module]; } -MultiModuleSyncStatus& getMultiSyncStatus(uint8_t module) +MultiModuleSyncStatus &getMultiSyncStatus(uint8_t module) { return multiSyncStatus[module]; } @@ -140,9 +146,9 @@ static MultiBufferState guessProtocol(uint8_t module) return FrskyTelemetryFallback; } -static void processMultiStatusPacket(const uint8_t *data, uint8_t module) +static void processMultiStatusPacket(const uint8_t * data, uint8_t module) { - MultiModuleStatus& status = getMultiModuleStatus(module); + MultiModuleStatus &status = getMultiModuleStatus(module); // At least two status packets without bind flag bool wasBinding = status.isBinding(); @@ -158,9 +164,9 @@ static void processMultiStatusPacket(const uint8_t *data, uint8_t module) setMultiBindStatus(module, MULTI_BIND_FINISHED); } -static void processMultiSyncPacket(const uint8_t *data, uint8_t module) +static void processMultiSyncPacket(const uint8_t * data, uint8_t module) { - MultiModuleSyncStatus& status = getMultiSyncStatus(module); + MultiModuleSyncStatus &status = getMultiSyncStatus(module); status.lastUpdate = get_tmr10ms(); status.interval = data[4]; @@ -175,17 +181,17 @@ static void processMultiSyncPacket(const uint8_t *data, uint8_t module) #if !defined(PPM_PIN_SERIAL) TRACE("MP ADJ: rest: %d, lag %04d, diff: %04d target: %d, interval: %d, Refresh: %d, intAdjRefresh: %d, adjRefresh %d\r\n", module == EXTERNAL_MODULE ? extmodulePulsesData.dsm2.rest : 0, - status.inputLag, oldlag-status.inputLag, status.target, status.interval, status.refreshRate, status.adjustedRefreshRate/50, + status.inputLag, oldlag - status.inputLag, status.target, status.interval, status.refreshRate, status.adjustedRefreshRate / 50, status.getAdjustedRefreshRate()); #endif } -static void processMultiTelemetryPaket(const uint8_t *packet, uint8_t module) +static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) { uint8_t type = packet[0]; uint8_t len = packet[1]; - const uint8_t *data = packet + 2; + const uint8_t * data = packet + 2; // Switch type switch (type) { @@ -215,6 +221,20 @@ static void processMultiTelemetryPaket(const uint8_t *packet, uint8_t module) TRACE("[MP] Received IBUS telemetry len %d < 28", len); break; + case FlyskyIBusTelemetryAC: + if (len >= 28) + processFlySkyPacketAC(data); + else + TRACE("[MP] Received IBUS telemetry AC len %d < 28", len); + break; + + case HitecTelemetry: + if (len >= 8) + processHitecPacket(data); + else + TRACE("[MP] Received Hitec telemetry len %d < 8", len); + break; + case FrSkyHubTelemetry: if (len >= 4) frskyDProcessPacket(data); @@ -257,7 +277,7 @@ static void processMultiTelemetryPaket(const uint8_t *packet, uint8_t module) // sprintf does not work AVR ARM // use a small helper function -static void appendInt(char *buf, uint32_t val) +static void appendInt(char * buf, uint32_t val) { while (*buf) buf++; @@ -277,8 +297,8 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin uint16_t targetRefreshRate = (uint16_t) (newRefreshRate * ((MIN_REFRESH_RATE / (newRefreshRate - 1)) + 1)); // Overflow, reverse sample - if (lagDifference < -targetRefreshRate/2) - lagDifference= -lagDifference; + if (lagDifference < -targetRefreshRate / 2) + lagDifference = -lagDifference; // Reset adjusted refresh if rate has changed @@ -289,7 +309,7 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin adjustedRefreshRate /= 2; // Our refresh rate in ps - adjustedRefreshRate*=1000; + adjustedRefreshRate *= 1000; return; } @@ -297,16 +317,16 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin int numsamples = interval * 10000 / targetRefreshRate; // Convert lagDifference to ps - lagDifference=lagDifference*1000; + lagDifference = lagDifference * 1000; // Calculate the time we intentionally were late/early - if (inputLag > target*10 +30) - lagDifference += numsamples*500; - else if (inputLag < target*10 - 30) - lagDifference -= numsamples*500; + if (inputLag > target * 10 + 30) + lagDifference += numsamples * 500; + else if (inputLag < target * 10 - 30) + lagDifference -= numsamples * 500; // Caculate the time in ps each frame is to slow (positive), fast(negative) - int perframeps = lagDifference*10/ numsamples; + int perframeps = lagDifference * 10 / numsamples; if (perframeps > 20000) perframeps = 20000; @@ -314,20 +334,21 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin if (perframeps < -20000) perframeps = -20000; - adjustedRefreshRate =(adjustedRefreshRate + perframeps); + adjustedRefreshRate = (adjustedRefreshRate + perframeps); // Safeguards - if (adjustedRefreshRate < 6*1000*1000) - adjustedRefreshRate = 6*1000*1000; - if (adjustedRefreshRate > 30*1000*1000) - adjustedRefreshRate = 30*1000*1000; + if (adjustedRefreshRate < 6 * 1000 * 1000) + adjustedRefreshRate = 6 * 1000 * 1000; + if (adjustedRefreshRate > 30 * 1000 * 1000) + adjustedRefreshRate = 30 * 1000 * 1000; inputLag = newInputLag; } static uint8_t counter; -uint16_t MultiModuleSyncStatus::getAdjustedRefreshRate() { +uint16_t MultiModuleSyncStatus::getAdjustedRefreshRate() +{ if (!isValid() || refreshRate == 0) return 18000; @@ -335,9 +356,9 @@ uint16_t MultiModuleSyncStatus::getAdjustedRefreshRate() { counter = (uint8_t) (counter + 1 % 10); uint16_t rate = (uint16_t) ((adjustedRefreshRate + counter * 50) / 500); // Check how far off we are from our target, positive means we are too slow, negative we are too fast - if (inputLag > target*10 +30) - return (uint16_t) (rate - 1); - else if (inputLag < target*10 - 30) + if (inputLag > target * 10 + 30) + return (uint16_t) (rate - 1); + else if (inputLag < target * 10 - 30) return (uint16_t) (rate + 1); else return rate; @@ -349,17 +370,16 @@ static void prependSpaces(char * buf, int val) while (*buf) buf++; - int k=10000; - while(val/k==0 && k > 0) - { - *buf=' '; + int k = 10000; + while (val / k == 0 && k > 0) { + *buf = ' '; buf++; - k/= 10; + k /= 10; } - *buf='\0'; + *buf = '\0'; } -void MultiModuleSyncStatus::getRefreshString(char *statusText) +void MultiModuleSyncStatus::getRefreshString(char * statusText) { if (!isValid()) { return; @@ -369,12 +389,12 @@ void MultiModuleSyncStatus::getRefreshString(char *statusText) prependSpaces(statusText, inputLag); appendInt(statusText, inputLag); strcat(statusText, "ns R "); - prependSpaces(statusText, adjustedRefreshRate/1000); + prependSpaces(statusText, adjustedRefreshRate / 1000); appendInt(statusText, (uint32_t) (adjustedRefreshRate / 1000)); strcat(statusText, "ns"); } -void MultiModuleStatus::getStatusString(char *statusText) +void MultiModuleStatus::getStatusString(char * statusText) { if (!isValid()) { #if defined(PCBTARANIS) || defined(PCBHORUS) @@ -384,7 +404,7 @@ void MultiModuleStatus::getStatusString(char *statusText) else #endif #endif - strcpy(statusText, STR_MODULE_NO_TELEMETRY); + strcpy(statusText, STR_MODULE_NO_TELEMETRY); return; } if (!protocolValid()) { @@ -399,7 +419,7 @@ void MultiModuleStatus::getStatusString(char *statusText) strcpy(statusText, STR_MODULE_NO_INPUT); return; } - else if(isWaitingforBind()) { + else if (isWaitingforBind()) { strcpy(statusText, STR_MODULE_WAITFORBIND); return; } @@ -419,7 +439,7 @@ void MultiModuleStatus::getStatusString(char *statusText) strcat(statusText, STR_MODULE_BINDING); } -static uint8_t* getRxBuffer(uint8_t moduleIdx) +static uint8_t * getRxBuffer(uint8_t moduleIdx) { #if defined(INTERNAL_MODULE_MULTI) if (moduleIdx == INTERNAL_MODULE) @@ -428,7 +448,7 @@ static uint8_t* getRxBuffer(uint8_t moduleIdx) return telemetryRxBuffer; } -static uint8_t& getRxBufferCount(uint8_t moduleIdx) +static uint8_t &getRxBufferCount(uint8_t moduleIdx) { #if defined(INTERNAL_MODULE_MULTI) if (moduleIdx == INTERNAL_MODULE) @@ -439,8 +459,8 @@ static uint8_t& getRxBufferCount(uint8_t moduleIdx) static void processMultiTelemetryByte(const uint8_t data, uint8_t module) { - uint8_t* rxBuffer = getRxBuffer(module); - uint8_t& rxBufferCount = getRxBufferCount(module); + uint8_t * rxBuffer = getRxBuffer(module); + uint8_t &rxBufferCount = getRxBufferCount(module); if (rxBufferCount < TELEMETRY_RX_PACKET_SIZE) { rxBuffer[rxBufferCount++] = data; @@ -470,8 +490,8 @@ static void processMultiTelemetryByte(const uint8_t data, uint8_t module) void processMultiTelemetryData(uint8_t data, uint8_t module) { - uint8_t* rxBuffer = getRxBuffer(module); - uint8_t& rxBufferCount = getRxBufferCount(module); + uint8_t * rxBuffer = getRxBuffer(module); + uint8_t &rxBufferCount = getRxBufferCount(module); debugPrintf("State: %d, byte received %02X, buflen: %d\r\n", multiTelemetryBufferState, data, rxBufferCount); switch (getMultiTelemetryBufferState(module)) { @@ -523,7 +543,7 @@ void processMultiTelemetryData(uint8_t data, uint8_t module) break; case SpektrumTelemetryFallback: - processSpektrumTelemetryData(module, data,rxBuffer, rxBufferCount); + processSpektrumTelemetryData(module, data, rxBuffer, rxBufferCount); if (rxBufferCount == 0) { setMultiTelemetryBufferState(module, NoProtocolDetected); } @@ -565,15 +585,15 @@ void processMultiTelemetryData(uint8_t data, uint8_t module) case ReceivingMultiStatus: rxBuffer[rxBufferCount++] = data; - if (rxBufferCount > 5 && rxBuffer[0] == rxBufferCount-1) { - processMultiStatusPacket(rxBuffer+1, module); + if (rxBufferCount > 5 && rxBuffer[0] == rxBufferCount - 1) { + processMultiStatusPacket(rxBuffer + 1, module); rxBufferCount = 0; setMultiTelemetryBufferState(module, NoProtocolDetected); } if (rxBufferCount > 10) { // too long ignore TRACE("Overlong multi status packet detected ignoring, wanted %d", rxBuffer[0]); - rxBufferCount =0; + rxBufferCount = 0; setMultiTelemetryBufferState(module, NoProtocolDetected); } break; diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 543af7fd8..35964e893 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -26,6 +26,7 @@ #if defined(MULTIMODULE) #include "spektrum.h" #include "flysky_ibus.h" + #include "hitec.h" #include "multi.h" #endif diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp index 8475eac54..868396536 100644 --- a/radio/src/telemetry/telemetry_sensors.cpp +++ b/radio/src/telemetry/telemetry_sensors.cpp @@ -527,6 +527,9 @@ int setTelemetryValue(TelemetryProtocol protocol, uint16_t id, uint8_t subId, ui case PROTOCOL_TELEMETRY_FLYSKY_IBUS: flySkySetDefault(index,id, subId, instance); break; + case PROTOCOL_TELEMETRY_HITEC: + hitecSetDefault(index, id, subId, instance); + break; #endif #if defined(LUA) case PROTOCOL_TELEMETRY_LUA: @@ -599,10 +602,10 @@ const UnitConversionRule unitConversionTable[] = { { UNIT_KMH, UNIT_FEET_PER_SECOND, 911, 1000}, // 1 km/h = 0.911344415 feet per second { UNIT_MILLILITERS, UNIT_FLOZ, 100, 2957}, - + { UNIT_RADIANS, UNIT_DEGREE, 10000, 175}, // 1 rad = 57.29578 deg { UNIT_DEGREE, UNIT_RADIANS, 175, 10000}, // 1 deg = ‪0,0174533‬ rad - + { 0, 0, 0, 0} // termination }; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index d9afa277a..216934c45 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1166,6 +1166,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 57cb44c00..df3302acd 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1171,6 +1171,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 1a016fe80..053fbb13c 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1172,6 +1172,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index f7b5a5bd6..35bd8bd81 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1191,6 +1191,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 0b2227afc..739b42b9f 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1179,6 +1179,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 1c360d5fd..f0422e135 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1194,6 +1194,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index a348eb001..3fc89e2c2 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1187,6 +1187,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 9d9409127..d7045af55 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1181,6 +1181,21 @@ TR_GYR_VSRCRAW #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 266830874..9a8b40701 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1187,6 +1187,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index bedb80a44..6cf12fe5e 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1176,6 +1176,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 9227959d2..6c2786054 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1187,6 +1187,21 @@ #define ZSTR_ALT "Alt" #define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" +#define ZSTR_TEMP3 "Tmp3" +#define ZSTR_TEMP4 "Tmp4" +#define ZSTR_RPM2 "RPM2" +#define ZSTR_PRES "Pres" +#define ZSTR_ODO1 "Odo1" +#define ZSTR_ODO2 "Odo2" +#define ZSTR_TXV "TX_V" +#define ZSTR_CURR_SERVO1 "CSv1" +#define ZSTR_CURR_SERVO2 "CSv2" +#define ZSTR_CURR_SERVO3 "CSv3" +#define ZSTR_CURR_SERVO4 "CSv4" +#define ZSTR_DIST "Dist" +#define ZSTR_ARM "Arm" +#define ZSTR_C50 "C50" +#define ZSTR_C200 "C200" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" #define ZSTR_VSPD "VSpd" diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 5d7420330..63e0f1295 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -133,4 +133,4 @@ #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 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FSky 2A""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 ""FlyZone" \ No newline at end of file +#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 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FSky 2A""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 ""FlyZone" From 49a7c3531b8e5efdc0e7b90aaa60d51bc9c65dd0 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 13:49:19 +0200 Subject: [PATCH 078/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 40ffe10be..685b14850 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1567,3 +1567,4 @@ Darrell Carew Philippe Faure Marco Lange Aaron Tygart +Frantisek Vajbar From c1570ab033409d8cc2feb332319dba96125dae54 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 14:53:17 +0200 Subject: [PATCH 079/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 8c7828e45..9f52d14d9 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1568,3 +1568,4 @@ Philippe Faure Marco Lange Aaron Tygart Frantisek Vajbar +Mike Perkins From 31ed3cac3e7203105deb094c02c2613851e96d47 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 28 Sep 2019 15:17:41 +0200 Subject: [PATCH 080/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 9f52d14d9..6fe0a9597 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1569,3 +1569,4 @@ Marco Lange Aaron Tygart Frantisek Vajbar Mike Perkins +Knut Einar Kristensen From 3e13b20617a7902e36a9309fde2275f71301d080 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 28 Sep 2019 15:57:28 +0200 Subject: [PATCH 081/257] Cosmetics (#6844) --- radio/src/opentx.cpp | 2 +- radio/src/telemetry/multi.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 4215e81a4..2955e6849 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -870,7 +870,7 @@ void checkFailsafe() { for (int i=0; i Date: Sat, 28 Sep 2019 16:04:29 +0200 Subject: [PATCH 082/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 6fe0a9597..68c087ae0 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1570,3 +1570,4 @@ Aaron Tygart Frantisek Vajbar Mike Perkins Knut Einar Kristensen +Georgios Papadopoulos From e08cc61e279740219b113b818399f715c371ec66 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 29 Sep 2019 11:07:32 +0200 Subject: [PATCH 083/257] Fix for newer version --- .idea/codeStyles/codeStyleConfig.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 79ee123c2..6e6eec114 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,6 @@ \ No newline at end of file From 674c290aefaa5cf2c48a8ebe94f7ada00c25d4c5 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 29 Sep 2019 11:10:27 +0200 Subject: [PATCH 084/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 68c087ae0..491777a68 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1571,3 +1571,4 @@ Frantisek Vajbar Mike Perkins Knut Einar Kristensen Georgios Papadopoulos +He Liu From 2aa256ba5230cb1d66d3f324c2e04ebe267879f3 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 29 Sep 2019 11:14:30 +0200 Subject: [PATCH 085/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 491777a68..a32f60b98 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1572,3 +1572,4 @@ Mike Perkins Knut Einar Kristensen Georgios Papadopoulos He Liu +Andrias Thomsen From 7acc668129b2e1392bce4b0731cea5448a0939d2 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 29 Sep 2019 15:24:18 +0200 Subject: [PATCH 086/257] Fix Visual C compilation --- radio/src/telemetry/flysky_ibus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index 77da922f0..dbc590f5b 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -23,8 +23,8 @@ #define FLYSKY_TELEMETRY_LENGTH (2+7*4) // Should it be 2+7*6??? #define ALT_PRECISION 15 -#define R_DIV_G_MUL_10_Q15 UINT64_C(9591506) -#define INV_LOG2_E_Q1DOT31 UINT64_C(0x58b90bfc) // Inverse log base 2 of e +#define R_DIV_G_MUL_10_Q15 (uint64_t)9591506 +#define INV_LOG2_E_Q1DOT31 (uint64_t)0x58b90bfc // Inverse log base 2 of e #define PRESSURE_MASK 0x7FFFF struct FlySkySensor From a71a7b24f99b9bf36de47434fa95cd2aeb676f81 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 29 Sep 2019 19:50:22 +0200 Subject: [PATCH 087/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index a32f60b98..bd0185fea 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1573,3 +1573,4 @@ Knut Einar Kristensen Georgios Papadopoulos He Liu Andrias Thomsen +Alain Azais From a654be2da1e981b8ec312b9317d29dc601d94719 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 29 Sep 2019 19:50:42 +0200 Subject: [PATCH 088/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index bd0185fea..f4378c9d0 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1574,3 +1574,4 @@ Georgios Papadopoulos He Liu Andrias Thomsen Alain Azais +Alan Stuart From f4c8a608a17ed2aa8f2eb143293977bbb3ddd99c Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 29 Sep 2019 20:02:41 +0200 Subject: [PATCH 089/257] Cleanup SxR scripts --- radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua | 8 ++++---- .../SCRIPTS/TOOLS/img/back.png | Bin .../SCRIPTS/TOOLS/img/delta_b.png | Bin .../SCRIPTS/TOOLS/img/done.bmp | Bin .../SCRIPTS/TOOLS/img/down.png | Bin .../SCRIPTS/TOOLS/img/forward.png | Bin .../SCRIPTS/TOOLS/img/left.png | Bin .../SCRIPTS/TOOLS/img/plane_b.png | Bin .../SCRIPTS/TOOLS/img/planev_b.png | Bin .../SCRIPTS/TOOLS/img/planev_s.png | Bin .../SCRIPTS/TOOLS/img/right.png | Bin .../SCRIPTS/TOOLS/img/up.png | Bin .../SCRIPTS/TOOLS/img/vert-r.png | Bin .../SCRIPTS/TOOLS/img/vert.png | Bin .../taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua | 8 ++++---- .../taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua | 8 ++++---- .../taranis-x9/SCRIPTS/TOOLS/img/back.png | Bin 9229 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/delta_b.png | Bin 9102 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/done.bmp | Bin 1142 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/down.png | Bin 7866 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/forward.png | Bin 10493 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/left.png | Bin 11410 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/plane_b.png | Bin 12743 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/planev_b.png | Bin 13467 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/planev_s.png | Bin 4393 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/right.png | Bin 10388 -> 0 bytes .../sdcard/taranis-x9/SCRIPTS/TOOLS/img/up.png | Bin 10799 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/vert-r.png | Bin 6813 -> 0 bytes .../taranis-x9/SCRIPTS/TOOLS/img/vert.png | Bin 10493 -> 0 bytes 29 files changed, 12 insertions(+), 12 deletions(-) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/back.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/delta_b.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/done.bmp (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/down.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/forward.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/left.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/plane_b.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/planev_b.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/planev_s.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/right.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/up.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/vert-r.png (100%) rename radio/sdcard/{taranis-x7 => horus}/SCRIPTS/TOOLS/img/vert.png (100%) delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/back.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/delta_b.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/done.bmp delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/down.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/forward.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/left.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/plane_b.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/planev_b.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/planev_s.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/right.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/up.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/vert-r.png delete mode 100755 radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/vert.png diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua index c49b78f52..8f69264a0 100755 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua @@ -44,8 +44,8 @@ local configFields = { { "Mounting type", COMBO, 0x81, nil, { "Horz", "Horz rev.", "Vert", "Vert rev." } }, } -local wingBitmapsFile = { "bmp/plane.bmp", "bmp/delta.bmp", "bmp/vtail.bmp" } -local mountBitmapsFile = { "bmp/horz.bmp", "bmp/horz-r.bmp", "bmp/vert.bmp", "bmp/vert-r.bmp" } +local wingBitmapsFile = { "/SCRIPTS/TOOLS/bmp/plane.bmp", "/SCRIPTS/TOOLS/bmp/delta.bmp", "/SCRIPTS/TOOLS/bmp/vtail.bmp" } +local mountBitmapsFile = { "/SCRIPTS/TOOLS/bmp/horz.bmp", "/SCRIPTS/TOOLS/bmp/horz-r.bmp", "/SCRIPTS/TOOLS/bmp/vert.bmp", "/SCRIPTS/TOOLS/bmp/vert-r.bmp" } local settingsFields = { {"SxR functions", COMBO, 0x9C, nil, { "Disable", "Enable" } }, @@ -332,8 +332,8 @@ local function init() if LCD_W == 480 then margin = 10 spacing = 20 - wingBitmapsFile = { "img/plane_b.png", "img/delta_b.png", "img/planev_b.png" } - mountBitmapsFile = { "img/up.png", "img/down.png", "img/vert.png", "img/vert-r.png" } + wingBitmapsFile = { "/SCRIPTS/TOOLS/img/plane_b.png", "/SCRIPTS/TOOLS/img/delta_b.png", "/SCRIPTS/TOOLS/img/planev_b.png" } + mountBitmapsFile = { "/SCRIPTS/TOOLS/img/up.png", "/SCRIPTS/TOOLS/img/down.png", "/SCRIPTS/TOOLS/img/vert.png", "/SCRIPTS/TOOLS/img/vert-r.png" } end pages = { runConfigPage, diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/back.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/back.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/back.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/back.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/delta_b.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/delta_b.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/delta_b.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/delta_b.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/done.bmp b/radio/sdcard/horus/SCRIPTS/TOOLS/img/done.bmp similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/done.bmp rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/done.bmp diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/down.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/down.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/down.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/down.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/forward.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/forward.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/forward.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/forward.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/left.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/left.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/left.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/left.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/plane_b.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/plane_b.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/plane_b.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/plane_b.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/planev_b.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/planev_b.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/planev_b.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/planev_b.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/planev_s.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/planev_s.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/planev_s.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/planev_s.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/right.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/right.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/right.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/right.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/up.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/up.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/up.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/up.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/vert-r.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/vert-r.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/vert-r.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/vert-r.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/vert.png b/radio/sdcard/horus/SCRIPTS/TOOLS/img/vert.png similarity index 100% rename from radio/sdcard/taranis-x7/SCRIPTS/TOOLS/img/vert.png rename to radio/sdcard/horus/SCRIPTS/TOOLS/img/vert.png diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua index c49b78f52..8f69264a0 100755 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua @@ -44,8 +44,8 @@ local configFields = { { "Mounting type", COMBO, 0x81, nil, { "Horz", "Horz rev.", "Vert", "Vert rev." } }, } -local wingBitmapsFile = { "bmp/plane.bmp", "bmp/delta.bmp", "bmp/vtail.bmp" } -local mountBitmapsFile = { "bmp/horz.bmp", "bmp/horz-r.bmp", "bmp/vert.bmp", "bmp/vert-r.bmp" } +local wingBitmapsFile = { "/SCRIPTS/TOOLS/bmp/plane.bmp", "/SCRIPTS/TOOLS/bmp/delta.bmp", "/SCRIPTS/TOOLS/bmp/vtail.bmp" } +local mountBitmapsFile = { "/SCRIPTS/TOOLS/bmp/horz.bmp", "/SCRIPTS/TOOLS/bmp/horz-r.bmp", "/SCRIPTS/TOOLS/bmp/vert.bmp", "/SCRIPTS/TOOLS/bmp/vert-r.bmp" } local settingsFields = { {"SxR functions", COMBO, 0x9C, nil, { "Disable", "Enable" } }, @@ -332,8 +332,8 @@ local function init() if LCD_W == 480 then margin = 10 spacing = 20 - wingBitmapsFile = { "img/plane_b.png", "img/delta_b.png", "img/planev_b.png" } - mountBitmapsFile = { "img/up.png", "img/down.png", "img/vert.png", "img/vert-r.png" } + wingBitmapsFile = { "/SCRIPTS/TOOLS/img/plane_b.png", "/SCRIPTS/TOOLS/img/delta_b.png", "/SCRIPTS/TOOLS/img/planev_b.png" } + mountBitmapsFile = { "/SCRIPTS/TOOLS/img/up.png", "/SCRIPTS/TOOLS/img/down.png", "/SCRIPTS/TOOLS/img/vert.png", "/SCRIPTS/TOOLS/img/vert-r.png" } end pages = { runConfigPage, diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua index c49b78f52..8f69264a0 100755 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua @@ -44,8 +44,8 @@ local configFields = { { "Mounting type", COMBO, 0x81, nil, { "Horz", "Horz rev.", "Vert", "Vert rev." } }, } -local wingBitmapsFile = { "bmp/plane.bmp", "bmp/delta.bmp", "bmp/vtail.bmp" } -local mountBitmapsFile = { "bmp/horz.bmp", "bmp/horz-r.bmp", "bmp/vert.bmp", "bmp/vert-r.bmp" } +local wingBitmapsFile = { "/SCRIPTS/TOOLS/bmp/plane.bmp", "/SCRIPTS/TOOLS/bmp/delta.bmp", "/SCRIPTS/TOOLS/bmp/vtail.bmp" } +local mountBitmapsFile = { "/SCRIPTS/TOOLS/bmp/horz.bmp", "/SCRIPTS/TOOLS/bmp/horz-r.bmp", "/SCRIPTS/TOOLS/bmp/vert.bmp", "/SCRIPTS/TOOLS/bmp/vert-r.bmp" } local settingsFields = { {"SxR functions", COMBO, 0x9C, nil, { "Disable", "Enable" } }, @@ -332,8 +332,8 @@ local function init() if LCD_W == 480 then margin = 10 spacing = 20 - wingBitmapsFile = { "img/plane_b.png", "img/delta_b.png", "img/planev_b.png" } - mountBitmapsFile = { "img/up.png", "img/down.png", "img/vert.png", "img/vert-r.png" } + wingBitmapsFile = { "/SCRIPTS/TOOLS/img/plane_b.png", "/SCRIPTS/TOOLS/img/delta_b.png", "/SCRIPTS/TOOLS/img/planev_b.png" } + mountBitmapsFile = { "/SCRIPTS/TOOLS/img/up.png", "/SCRIPTS/TOOLS/img/down.png", "/SCRIPTS/TOOLS/img/vert.png", "/SCRIPTS/TOOLS/img/vert-r.png" } end pages = { runConfigPage, diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/back.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/back.png deleted file mode 100755 index 2cf3cd699030fd58a55cabcece2ae28eb23644d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9229 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 diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/down.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/down.png deleted file mode 100755 index 8eac8039afe27f1fa89c9020fd63dd013c6f66ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7866 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 Dg)Soz diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/forward.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/forward.png deleted file mode 100755 index de09680b7b01e4a2eef81bc3ae3a87a72d37bf39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10493 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 MO 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 diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/plane_b.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/plane_b.png deleted file mode 100755 index 37abedc3ab047a26097ab9d80680f6188917e997..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12743 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 KRVb4;4gOz9EewSK diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/planev_b.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/planev_b.png deleted file mode 100755 index 4e33f660bee8f51b7a95275e27aba3d22697b474..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13467 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 Y7FS@_-R&vhAQ4DeUL9G9un75o00R|QvH$=8 diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/planev_s.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/planev_s.png deleted file mode 100755 index 48283a2903fe901c880ecef52d8994c35a13587e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4393 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 diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/right.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/right.png deleted file mode 100755 index 01d555394a4d145dda3222a0a8afef08ced25b75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10388 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 AcmMzZ diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/up.png b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/img/up.png deleted file mode 100755 index f033aba553f80ce27f76ba5c1dcb6d8783367820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10799 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 iEB}4L|9|H%ckJBCPo|)(nS9t$53Y6Cf53D1 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 MO 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 Date: Sun, 29 Sep 2019 21:43:15 +0200 Subject: [PATCH 090/257] Switch nightlies to 2.3.1 --- CMakeLists.txt | 2 +- tools/nightly23/build-nightly.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f40a9ff6..9d9b3abb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(OpenTX) set(VERSION_MAJOR "2") set(VERSION_MINOR "3") -set(VERSION_REVISION "0") +set(VERSION_REVISION "1") set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) diff --git a/tools/nightly23/build-nightly.sh b/tools/nightly23/build-nightly.sh index 5e2a16515..f9c13f222 100755 --- a/tools/nightly23/build-nightly.sh +++ b/tools/nightly23/build-nightly.sh @@ -2,11 +2,11 @@ set -e -branch=2.3.0 +branch=2.3.1 docker=nightly23 workdir=/home/opentx/nightly23 output=/var/www/html/2.3/nightlies -version=2.3.0 +version=2.3.1 echo "Increment nightly index" index=`cat index.txt` From 8c3f008f6489f13d2a711f0bf51681c580552ef4 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 29 Sep 2019 21:43:41 +0200 Subject: [PATCH 091/257] Fix TopBar companion handling (#6855) --- companion/src/firmwares/opentx/opentxeeprom.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index a81457e23..4866444cc 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2361,8 +2361,8 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig internalField.Append(new UnsignedField<8>(this, modelData.rssiSource)); if (IS_TARANIS_X9(board)) { - // TODO TOPBAR - internalField.Append(new SpareBitsField<16>(this)); + internalField.Append(new UnsignedField<8>(this, modelData.frsky.voltsSource)); + internalField.Append(new UnsignedField<8>(this, modelData.frsky.altitudeSource)); } internalField.Append(new BoolField<1>(this, modelData.rssiAlarms.disabled)); From 2d581d2f8818f0efecb1fcd6cd0b10e780464d40 Mon Sep 17 00:00:00 2001 From: Kilrah Date: Mon, 30 Sep 2019 09:36:47 +0200 Subject: [PATCH 092/257] Fix building X10 after X12 --- radio/src/targets/horus/CMakeLists.txt | 1 + radio/src/targets/horus/board.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 118426265..4a399531e 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -40,6 +40,7 @@ if (PCB STREQUAL X10) set(FONTS_TARGET x10_fonts) set(LCD_DRIVER lcd_driver.cpp) set(LUA_EXPORT lua_export_x10) + set(INTERNAL_GPS OFF) if (PCBREV STREQUAL EXPRESS) set(FLAVOUR x10express) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 13717068a..f1240fcd3 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -582,7 +582,7 @@ uint8_t gpsGetByte(uint8_t * byte); extern uint8_t gpsTraceEnabled; #endif void gpsSendByte(uint8_t byte); -#if defined(PCBX12S) +#if defined(INTERNAL_GPS) #define PILOTPOS_MIN_HDOP 500 #endif From 234432f463a5fe9e4aa3bac02fd2e40979994018 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 30 Sep 2019 10:50:33 +0200 Subject: [PATCH 093/257] Fix ext module power --- radio/src/gui/480x272/model_setup.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 822841878..c49f8fab1 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1057,7 +1057,8 @@ bool menuModelSetup(event_t event) if (s_editMode > 0) EXTERNAL_MODULE_OFF(); else - EXTERNAL_MODULE_ON(); + if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) + EXTERNAL_MODULE_ON(); } if (attr) { if (s_editMode > 0) { From 97262ec0bf58fb90558dd0f697d78ea8fc345b85 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 30 Sep 2019 11:26:02 +0200 Subject: [PATCH 094/257] Turn off ext module while editing type also on 128 and 212 --- radio/src/gui/128x64/model_setup.cpp | 7 +++++++ radio/src/gui/212x64/model_setup.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 1e8d17c9b..a7d5e777e 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -844,6 +844,13 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_MULTI_PROTOCOLS, multi_rfProto, menuHorizontalPosition==1 ? attr : 0); } #endif + if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) { + if (s_editMode > 0) + EXTERNAL_MODULE_OFF(); + else + if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) + EXTERNAL_MODULE_ON(); + } if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 2f4210af1..c10acaad3 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -830,6 +830,13 @@ void menuModelSetup(event_t event) } } #endif + if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) { + if (s_editMode > 0) + EXTERNAL_MODULE_OFF(); + else + if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) + EXTERNAL_MODULE_ON(); + } if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { From d1f5d8a283301c797abbbeb64aa0bcc0eeb74039 Mon Sep 17 00:00:00 2001 From: Kilrah Date: Mon, 30 Sep 2019 13:09:46 +0200 Subject: [PATCH 095/257] R9M Lite Pro only exists with ACCESS --- radio/src/gui/gui_common.cpp | 3 +++ radio/src/pulses/modules_constants.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 4fe9e169c..db46986bb 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -591,6 +591,9 @@ bool isInternalModuleAvailable(int moduleType) bool isExternalModuleAvailable(int moduleType) { + if (moduleType == MODULE_TYPE_R9M_LITE_PRO_PXX1) + return false; + #if !defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) if (isModuleTypeR9MLite(moduleType) || moduleType == MODULE_TYPE_XJT_LITE_PXX2) return false; diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h index c97649a10..948ee60df 100644 --- a/radio/src/pulses/modules_constants.h +++ b/radio/src/pulses/modules_constants.h @@ -33,7 +33,7 @@ enum ModuleType { MODULE_TYPE_R9M_PXX2, MODULE_TYPE_R9M_LITE_PXX1, MODULE_TYPE_R9M_LITE_PXX2, - MODULE_TYPE_R9M_LITE_PRO_PXX1, + MODULE_TYPE_R9M_LITE_PRO_PXX1, // Doesn't exist MODULE_TYPE_R9M_LITE_PRO_PXX2, MODULE_TYPE_SBUS, MODULE_TYPE_XJT_LITE_PXX2, From c5f13b1a17a6ed9044ed5b0e3a788131c534a389 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 30 Sep 2019 15:45:38 +0200 Subject: [PATCH 096/257] Shift sensor display by +1 to match old display value (#6865) Shift sensor display by +1 to match old display value --- companion/src/firmwares/opentx/opentxeeprom.cpp | 6 +++--- radio/src/gui/128x64/model_telemetry_sensor.cpp | 2 +- radio/src/gui/212x64/model_telemetry_sensor.cpp | 2 +- radio/src/gui/480x272/model_telemetry_sensor.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 4866444cc..1dbfaa7e8 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -1914,7 +1914,7 @@ class SensorField: public TransformedField { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) { _id = sensor.id; _subid = sensor.subid; - _instance = (sensor.instance & 0x1F) | (sensor.rxIdx << 5) | (sensor.moduleIdx << 7); + _instance = ((sensor.instance - 1) & 0x1F) | (sensor.rxIdx << 5) | (sensor.moduleIdx << 7); _ratio = sensor.ratio; _offset = sensor.offset; } @@ -1942,12 +1942,12 @@ class SensorField: public TransformedField { sensor.id = _id; sensor.subid = _subid; if (model.moduleData[0].isPxx1Module() || model.moduleData[1].isPxx1Module()) { - sensor.instance = (_instance & 0x1F) + (version <= 218 ? -1 : 0); // 5 bits instance + sensor.instance = (_instance & 0x1F) + (version <= 218 ? 0 : 1); // 5 bits instance sensor.rxIdx = 0x03; // 2 bits Rx idx sensor.moduleIdx = 0x01; // 1 bit module idx } else { - sensor.instance = _instance & 0x1F; + sensor.instance = (_instance & 0x1F) + 1; sensor.rxIdx = (_instance >> 5) & 0x03; // 2 bits Rx idx sensor.moduleIdx = (_instance >> 7) & 0x1; // 1 bit module idx } diff --git a/radio/src/gui/128x64/model_telemetry_sensor.cpp b/radio/src/gui/128x64/model_telemetry_sensor.cpp index f5870f230..d8a63079e 100644 --- a/radio/src/gui/128x64/model_telemetry_sensor.cpp +++ b/radio/src/gui/128x64/model_telemetry_sensor.cpp @@ -104,7 +104,7 @@ void menuModelSensor(event_t event) if (sensor->type == TELEM_TYPE_CUSTOM) { lcdDrawTextAlignedLeft(y, STR_ID); lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0)); - lcdDrawHexChar(SENSOR_3RD_COLUMN, y, sensor->instance & 0x1f, LEFT|(menuHorizontalPosition==1 ? attr : 0)); + lcdDrawHexChar(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0)); if (attr && s_editMode > 0) { switch (menuHorizontalPosition) { case 0: diff --git a/radio/src/gui/212x64/model_telemetry_sensor.cpp b/radio/src/gui/212x64/model_telemetry_sensor.cpp index 4321f87c3..27e6cd93c 100644 --- a/radio/src/gui/212x64/model_telemetry_sensor.cpp +++ b/radio/src/gui/212x64/model_telemetry_sensor.cpp @@ -114,7 +114,7 @@ void menuModelSensor(event_t event) if (sensor->type == TELEM_TYPE_CUSTOM) { lcdDrawTextAlignedLeft(y, STR_ID); lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0)); - lcdDrawNumber(SENSOR_3RD_COLUMN, y, sensor->instance, LEFT|(menuHorizontalPosition==1 ? attr : 0)); + lcdDrawNumber(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0)); if (attr) { switch (menuHorizontalPosition) { case 0: diff --git a/radio/src/gui/480x272/model_telemetry_sensor.cpp b/radio/src/gui/480x272/model_telemetry_sensor.cpp index 150d3e365..3c23b96af 100644 --- a/radio/src/gui/480x272/model_telemetry_sensor.cpp +++ b/radio/src/gui/480x272/model_telemetry_sensor.cpp @@ -115,7 +115,7 @@ bool menuModelSensor(event_t event) if (sensor->type == TELEM_TYPE_CUSTOM) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ID); lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0)); - lcdDrawNumber(SENSOR_3RD_COLUMN, y, sensor->instance, LEFT|(menuHorizontalPosition==1 ? attr : 0)); + lcdDrawNumber(SENSOR_3RD_COLUMN, y, (sensor->instance & 0x1F) + 1, LEFT|(menuHorizontalPosition==1 ? attr : 0)); if (attr) { switch (menuHorizontalPosition) { case 0: From af5f3586f25c8ea30896632a47cef13e0e3dab76 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 30 Sep 2019 15:55:03 +0200 Subject: [PATCH 097/257] Allow disabling RTC batt check (#6861) Allow disabling RTC batt check --- companion/src/firmwares/generalsettings.h | 1 + .../src/firmwares/opentx/opentxeeprom.cpp | 3 +- companion/src/generaledit/hardware.cpp | 14 + companion/src/generaledit/hardware.h | 1 + companion/src/generaledit/hardware.ui | 284 +++++++++--------- radio/src/datastructs.h | 3 +- radio/src/gui/480x272/radio_hardware.cpp | 10 + .../src/gui/common/stdlcd/radio_hardware.cpp | 7 +- radio/src/opentx.cpp | 3 +- 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 | 1 + radio/src/translations/se.h.txt | 1 + 22 files changed, 200 insertions(+), 139 deletions(-) diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index f3b415ec4..5325119b4 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -140,6 +140,7 @@ class GeneralSettings { unsigned int rotarySteps; unsigned int countryCode; bool jitterFilter; + bool rtcCheckDisable; unsigned int imperial; char ttsLanguage[2+1]; int beepVolume; diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 1dbfaa7e8..8332a7ff0 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2571,7 +2571,8 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type internalField.Append(new SignedField<2>(this, generalData.antennaMode)); else internalField.Append(new SpareBitsField<2>(this)); - internalField.Append(new SpareBitsField<3>(this)); + internalField.Append(new BoolField<1>(this, generalData.rtcCheckDisable)); + internalField.Append(new SpareBitsField<2>(this)); for (int i=0; i<4; i++) { internalField.Append(new SignedField<16>(this, generalData.trainer.calib[i])); diff --git a/companion/src/generaledit/hardware.cpp b/companion/src/generaledit/hardware.cpp index 09f109bda..8868e7766 100644 --- a/companion/src/generaledit/hardware.cpp +++ b/companion/src/generaledit/hardware.cpp @@ -200,6 +200,15 @@ HardwarePanel::HardwarePanel(QWidget * parent, GeneralSettings & generalSettings } else { ui->filterEnable->hide(); + ui->filterLabel->hide(); + } + + if (IS_STM32(board)) { + ui->rtcCheckDisable->setChecked(!generalSettings.rtcCheckDisable); + } + else { + ui->rtcCheckDisable->hide(); + ui->rtcCheckLabel->hide(); } disableMouseScrolling(); @@ -217,6 +226,11 @@ void HardwarePanel::on_filterEnable_stateChanged() generalSettings.jitterFilter = !ui->filterEnable->isChecked(); } +void HardwarePanel::on_rtcCheckDisable_stateChanged() +{ + generalSettings.rtcCheckDisable = !ui->rtcCheckDisable->isChecked(); +} + void HardwarePanel::on_PPM_MultiplierDSB_editingFinished() { int val = (int)(ui->PPM_MultiplierDSB->value()*10)-10; diff --git a/companion/src/generaledit/hardware.h b/companion/src/generaledit/hardware.h index 07ba62c40..8101b784c 100644 --- a/companion/src/generaledit/hardware.h +++ b/companion/src/generaledit/hardware.h @@ -49,6 +49,7 @@ class HardwarePanel : public GeneralPanel void on_txCurrentCalibration_editingFinished(); void on_txVoltageCalibration_editingFinished(); void on_filterEnable_stateChanged(); + void on_rtcCheckDisable_stateChanged(); void on_serialPortMode_currentIndexChanged(int index); diff --git a/companion/src/generaledit/hardware.ui b/companion/src/generaledit/hardware.ui index 79bb36a32..45e8e8da6 100644 --- a/companion/src/generaledit/hardware.ui +++ b/companion/src/generaledit/hardware.ui @@ -7,7 +7,7 @@ 0 0 470 - 1585 + 1618 @@ -57,7 +57,7 @@ - + @@ -169,7 +169,7 @@ - + -49 @@ -192,27 +192,7 @@ - - - - RS2 - - - - - - - - 0 - 10 - - - - Qt::Horizontal - - - - + @@ -231,6 +211,26 @@ + + + + + 0 + 10 + + + + Qt::Horizontal + + + + + + + RS2 + + + @@ -267,7 +267,7 @@ - + Current Offset @@ -284,7 +284,7 @@ - + PPM 2 @@ -312,6 +312,9 @@ + + + @@ -322,6 +325,19 @@ + + + + + + + + + + + + + @@ -342,17 +358,14 @@ - - + + - - - @@ -375,16 +388,6 @@ - - - - - - - - - - @@ -434,6 +437,16 @@ + + + + + + + + + + @@ -447,23 +460,6 @@ - - - - 3 - - - - - - - - - - - - - @@ -471,6 +467,13 @@ + + + + 3 + + + @@ -512,7 +515,7 @@ - + 1 @@ -545,6 +548,19 @@ + + + + + + + + + + + + + @@ -562,19 +578,6 @@ - - - - - - - - - - - - - @@ -589,9 +592,6 @@ - - - @@ -599,6 +599,13 @@ + + + + SI + + + @@ -613,10 +620,10 @@ - - + + - SI + SL @@ -627,13 +634,6 @@ - - - - SL - - - @@ -688,7 +688,7 @@ - + @@ -707,7 +707,7 @@ - + PPM 1 @@ -727,14 +727,14 @@ - + PPM 4 - + @@ -766,6 +766,20 @@ + + + + SB + + + + + + + 3 + + + @@ -788,21 +802,7 @@ - - - - SB - - - - - - - 3 - - - - + PPM Multiplier @@ -903,16 +903,6 @@ - - - - Antenna - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - @@ -933,7 +923,17 @@ - + + + + Antenna + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + PPM 3 @@ -1029,6 +1029,26 @@ + + + + 3 + + + + + + + + + + + + + + + + @@ -1058,26 +1078,6 @@ - - - - 3 - - - - - - - - - - - - - - - - @@ -1113,6 +1113,20 @@ + + + + + + + + + + + RTC Batt Check + + + diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 4c07cdb9c..8a5952bfe 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -735,7 +735,8 @@ PACK(struct RadioData { NOBACKUP(int8_t txVoltageCalibration); uint8_t backlightMode:3; int8_t antennaMode:2; - int8_t spare1:3; + uint8_t disableRtcWarning:1; + int8_t spare1:2; NOBACKUP(TrainerData trainer); NOBACKUP(uint8_t view); // index of view in main screen NOBACKUP(BUZZER_FIELD); /* 2bits */ diff --git a/radio/src/gui/480x272/radio_hardware.cpp b/radio/src/gui/480x272/radio_hardware.cpp index db5fbc759..35bec7cb1 100644 --- a/radio/src/gui/480x272/radio_hardware.cpp +++ b/radio/src/gui/480x272/radio_hardware.cpp @@ -54,6 +54,7 @@ enum MenuRadioHardwareItems { ITEM_RADIO_HARDWARE_SJ, // Gimbal switch right ITEM_RADIO_HARDWARE_BATTERY_CALIB, ITEM_RADIO_HARDWARE_RTC_BATTERY, + ITEM_RADIO_HARDWARE_RTC_CHECK, ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE, ITEM_RADIO_HARDWARE_BLUETOOTH_MODE, ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE, @@ -118,6 +119,7 @@ bool menuRadioHardware(event_t event) 0, /* battery */ READONLY_ROW, /* RTC */ + 0, /* RTC check */ 0, /* max baudrate */ @@ -271,6 +273,14 @@ bool menuRadioHardware(event_t event) } break; + case ITEM_RADIO_HARDWARE_RTC_CHECK: + { + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RTC_CHECK); + uint8_t b = 1 - g_eeGeneral.disableRtcWarning; + g_eeGeneral.disableRtcWarning = 1 - editCheckBox(b, HW_SETTINGS_COLUMN + 50, y, attr, event); + break; + } + case ITEM_RADIO_HARDWARE_BLUETOOTH_MODE: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BLUETOOTH); g_eeGeneral.bluetoothMode = editChoice(HW_SETTINGS_COLUMN+50, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER, attr, event); diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index a62bd9f08..4f8156453 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -151,6 +151,7 @@ enum { #if defined(STM32) ITEM_RADIO_HARDWARE_RTC_BATTERY, + ITEM_RADIO_HARDWARE_RTC_CHECK, #endif #if defined(TX_CAPACITY_MEASUREMENT) @@ -255,7 +256,7 @@ void onHardwareAntennaSwitchConfirm(const char * result) #endif #if defined(STM32) - #define RTC_ROW READONLY_ROW, + #define RTC_ROW READONLY_ROW, 0, #else #define RTC_ROW #endif @@ -510,6 +511,10 @@ void menuRadioHardware(event_t event) lcdDrawTextAlignedLeft(y, STR_RTC_BATT); putsVolts(HW_SETTINGS_COLUMN2, y, getRTCBatteryVoltage(), PREC2|LEFT); break; + + case ITEM_RADIO_HARDWARE_RTC_CHECK: + g_eeGeneral.disableRtcWarning = 1 - editCheckBox(1 - g_eeGeneral.disableRtcWarning, HW_SETTINGS_COLUMN2, y, STR_RTC_CHECK, attr, event); + break; #endif #if defined(TX_CAPACITY_MEASUREMENT) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 345449ab9..3bc6913ad 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -912,7 +912,8 @@ void checkAll() #endif #if defined(STM32) - checkRTCBattery(); + if (!g_eeGeneral.disableRtcWarning) + checkRTCBattery(); #endif if (g_model.displayChecklist && modelHasNotes()) { diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 953330f4b..7eee84f91 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -572,6 +572,7 @@ const char STR_MENU_DISPLAY[] = TR_MENU_DISPLAY; const char STR_MENU_OTHER[] = TR_MENU_OTHER; const char STR_MENU_INVERT[] = TR_MENU_INVERT; const char STR_JITTER_FILTER[] = TR_JITTER_FILTER; +const char STR_RTC_CHECK[] = TR_RTC_CHECK; const char STR_EXIT[] = TR_EXIT; const char STR_MODULE_RANGE[] = TR_MODULE_RANGE; const char STR_RECEIVER_OPTIONS[] = TR_RECEIVER_OPTIONS; diff --git a/radio/src/translations.h b/radio/src/translations.h index 070c11e66..ba36e8d6a 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -851,6 +851,7 @@ extern const char STR_MENU_DISPLAY[]; extern const char STR_MENU_OTHER[]; extern const char STR_MENU_INVERT[]; extern const char STR_JITTER_FILTER[]; +extern const char STR_RTC_CHECK[]; #if MENUS_LOCK == 1 extern const char STR_UNLOCKED[]; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index c839d7d3f..840808917 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1145,6 +1145,7 @@ #define TR_MENU_OTHER "Ostatní" #define TR_MENU_INVERT "Invertovat" #define TR_JITTER_FILTER "ADC Filtr" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 65e3f7cb3..5f57de855 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1150,6 +1150,7 @@ #define TR_MENU_OTHER "Weitere" #define TR_MENU_INVERT "Invertieren" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") // ---------------------------------------------------------------- #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index b2090eaea..20ac2103d 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1149,6 +1149,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 3395c170c..0f081176e 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1170,6 +1170,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 65c67607b..e65b5f52b 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1158,6 +1158,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index fc3d2945f..51b03fa7d 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1173,6 +1173,7 @@ #define TR_MENU_OTHER "Autres" #define TR_MENU_INVERT "Inverser" #define TR_JITTER_FILTER "Filtre ADC" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 900913578..1530edfb0 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1166,6 +1166,7 @@ #define TR_MENU_OTHER "Altro" #define TR_MENU_INVERT "Inverti" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 7aaf4d5ac..7fd696397 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1160,6 +1160,7 @@ TR_GYR_VSRCRAW #define TR_MENU_OTHER "Verdere" #define TR_MENU_INVERT "Inverteer" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 1922fa9b0..b342291a2 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1166,6 +1166,7 @@ #define TR_MENU_OTHER "Inny " #define TR_MENU_INVERT "Odwróć" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index cefcb53fd..bad49e96e 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1155,6 +1155,7 @@ #define TR_MENU_OTHER "Other" #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #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 3d60f986b..bfda7e796 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1166,6 +1166,7 @@ #define TR_MENU_OTHER "Annat" #define TR_MENU_INVERT "Invertera" #define TR_JITTER_FILTER "ADC Filter" +#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" From 4f614850c43adc6ace89b492fc04e1670bbfb135 Mon Sep 17 00:00:00 2001 From: Andre Bernet Date: Mon, 30 Sep 2019 17:56:12 +0200 Subject: [PATCH 098/257] Add "Act" switch to companion (fix #6851) (#6854) --- companion/src/datamodels/rawitemdatamodels.cpp | 2 ++ companion/src/firmwares/opentx/opentxeeprom.cpp | 4 ++++ companion/src/firmwares/rawswitch.cpp | 3 +++ companion/src/firmwares/rawswitch.h | 1 + 4 files changed, 10 insertions(+) diff --git a/companion/src/datamodels/rawitemdatamodels.cpp b/companion/src/datamodels/rawitemdatamodels.cpp index f1e613d4a..1cba1c180 100644 --- a/companion/src/datamodels/rawitemdatamodels.cpp +++ b/companion/src/datamodels/rawitemdatamodels.cpp @@ -85,6 +85,7 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett Firmware * fw = getCurrentFirmware(); // Descending switch direction: NOT (!) switches + addItems(SWITCH_TYPE_ACT, -1); addItems(SWITCH_TYPE_SENSOR, -CPN_MAX_SENSORS); addItems(SWITCH_TYPE_TELEMETRY, -1); addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes)); @@ -107,6 +108,7 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett addItems(SWITCH_TYPE_SENSOR, CPN_MAX_SENSORS); addItems(SWITCH_TYPE_ON, 1); addItems(SWITCH_TYPE_ONE, 1); + addItems(SWITCH_TYPE_ACT, 1); } void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 8332a7ff0..8e0c408db 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -217,6 +217,10 @@ class SwitchesConversionTable: public ConversionTable { addConversion(RawSwitch(SWITCH_TYPE_SENSOR, i), val++); } } + if (version >= 219) { + addConversion(RawSwitch(SWITCH_TYPE_ACT, -1), -val+offset); + addConversion(RawSwitch(SWITCH_TYPE_ACT, 1), val++); + } } diff --git a/companion/src/firmwares/rawswitch.cpp b/companion/src/firmwares/rawswitch.cpp index 6438d335e..1d91f242a 100644 --- a/companion/src/firmwares/rawswitch.cpp +++ b/companion/src/firmwares/rawswitch.cpp @@ -115,6 +115,9 @@ QString RawSwitch::toString(Board::Type board, const GeneralSettings * const gen case SWITCH_TYPE_ONE: return tr("One"); + case SWITCH_TYPE_ACT: + return tr("Act"); + case SWITCH_TYPE_FLIGHT_MODE: if (modelData) return modelData->flightModeData[index-1].nameToString(index - 1); diff --git a/companion/src/firmwares/rawswitch.h b/companion/src/firmwares/rawswitch.h index 6d0c93700..af49156c0 100644 --- a/companion/src/firmwares/rawswitch.h +++ b/companion/src/firmwares/rawswitch.h @@ -45,6 +45,7 @@ enum RawSwitchType { SWITCH_TYPE_TIMER_MODE, SWITCH_TYPE_TELEMETRY, SWITCH_TYPE_SENSOR, + SWITCH_TYPE_ACT, MAX_SWITCH_TYPE }; From 8685e6c0890eb8fa8c68517975e0c4aa2c0a28d4 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 1 Oct 2019 07:10:09 +0200 Subject: [PATCH 099/257] Temporary compile fix, feature is going to be reworked --- radio/src/gui/128x64/model_setup.cpp | 2 +- radio/src/gui/212x64/model_setup.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index a7d5e777e..0c9ab7654 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -844,7 +844,7 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_MULTI_PROTOCOLS, multi_rfProto, menuHorizontalPosition==1 ? attr : 0); } #endif - if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) { + if (attr && menuHorizontalPosition == 0) { if (s_editMode > 0) EXTERNAL_MODULE_OFF(); else diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index c10acaad3..749d54221 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -830,7 +830,7 @@ void menuModelSetup(event_t event) } } #endif - if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) { + if (attr && menuHorizontalPosition == 0) { if (s_editMode > 0) EXTERNAL_MODULE_OFF(); else From 8cf59887f7c30569b757356ea6fe356228f5a54d Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 1 Oct 2019 07:58:52 +0200 Subject: [PATCH 100/257] Compile fixes --- radio/src/gui/128x64/model_setup.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 0c9ab7654..e25d8364c 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -844,6 +844,7 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_MULTI_PROTOCOLS, multi_rfProto, menuHorizontalPosition==1 ? attr : 0); } #endif +#if defined(PCBTARANIS) if (attr && menuHorizontalPosition == 0) { if (s_editMode > 0) EXTERNAL_MODULE_OFF(); @@ -851,6 +852,7 @@ void menuModelSetup(event_t event) if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) EXTERNAL_MODULE_ON(); } +#endif if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { From e74f14cc480cd8c50aa9b1a90959c6370160db25 Mon Sep 17 00:00:00 2001 From: Andre Bernet Date: Tue, 1 Oct 2019 09:49:34 +0200 Subject: [PATCH 101/257] Fix shift in sources on X9DP pre-2019 and X-Lite and hardware page (fix #6860 fix#6856) * Fix shift in sources on X9DP pre-2019 * Probably better fix, but needs to be carried to Xlite if approved * Fix Xlite strings * Forgot to update conversions too --- radio/src/dataconstants.h | 2 +- radio/src/datastructs.h | 4 ++-- radio/src/storage/conversions/datastructs_218.h | 4 ++-- radio/src/targets/taranis/board.h | 9 +++++++-- radio/src/translations/untranslated.h | 10 ++-------- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 0052b0f6a..4586bcc05 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -793,7 +793,7 @@ static_assert(MIXSRC_FIRST_LOGICAL_SWITCH == MIXSRC_FIRST_SWITCH + STORAGE_NUM_S #define MIXSRC_FIRST (MIXSRC_NONE + 1) #define MIXSRC_LAST MIXSRC_LAST_CH -#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + NUM_SWITCHES - 1) +#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES - 1) #define INPUTSRC_FIRST MIXSRC_Rud #define INPUTSRC_LAST MIXSRC_LAST_TELEM diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 8a5952bfe..46950cf9d 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -690,7 +690,7 @@ PACK(struct TrainerData { swarnstate_t switchUnlockStates; \ swconfig_t switchConfig; \ char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME]; \ - char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME]; \ + char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME]; \ BLUETOOTH_FIELDS #elif defined(PCBSKY9X) #define EXTRA_GENERAL_FIELDS \ @@ -703,7 +703,7 @@ PACK(struct TrainerData { uint8_t sticksGain; \ uint8_t rotarySteps; \ char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME]; \ - char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME]; + char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME]; #else #define EXTRA_GENERAL_FIELDS #endif diff --git a/radio/src/storage/conversions/datastructs_218.h b/radio/src/storage/conversions/datastructs_218.h index d331b943e..578e7c1bf 100644 --- a/radio/src/storage/conversions/datastructs_218.h +++ b/radio/src/storage/conversions/datastructs_218.h @@ -504,7 +504,7 @@ PACK(struct ModelData_v218 { swarnstate218_t switchUnlockStates; \ swconfig218_t switchConfig; \ char switchNames[NUM_SWITCHES_218][LEN_SWITCH_NAME_218]; \ - char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME_218]; \ + char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME_218]; \ BLUETOOTH_FIELDS_218 #elif defined(PCBSKY9X) #define EXTRA_GENERAL_FIELDS_218 \ @@ -517,7 +517,7 @@ PACK(struct ModelData_v218 { uint8_t sticksGain; \ uint8_t rotarySteps; \ char switchNames[NUM_SWITCHES_218][LEN_SWITCH_NAME_218]; \ - char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME_218]; + char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME_218]; #else #define EXTRA_GENERAL_FIELDS_218 EXTRA_GENERAL_FIELDS_GENERAL_218 #endif diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index b7cfff1e4..7c4842d39 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -492,14 +492,19 @@ enum Analogs { #define NUM_SLIDERS 4 #define STORAGE_NUM_POTS 4 #define STORAGE_NUM_SLIDERS 4 -#else +#elif defined(PCBX9DP) #define NUM_POTS 3 #define NUM_SLIDERS 2 #define STORAGE_NUM_POTS 3 #define STORAGE_NUM_SLIDERS 2 +#else + #define NUM_POTS 2 + #define NUM_SLIDERS 2 + #define STORAGE_NUM_POTS 3 + #define STORAGE_NUM_SLIDERS 2 #endif -#define NUM_XPOTS NUM_POTS +#define NUM_XPOTS STORAGE_NUM_POTS #define NUM_TRIMS 4 #define NUM_MOUSE_ANALOGS 0 #define STORAGE_NUM_MOUSE_ANALOGS 0 diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 83ddc3095..480717772 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -38,12 +38,9 @@ #elif defined(PCBX9E) #define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0" -#elif defined(PCBXLITES) - #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0" - #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0" #elif defined(PCBXLITE) #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0" - #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0" + #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0" #elif defined(RADIO_X7) #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0""\312SI\0""\312SJ\0" @@ -53,12 +50,9 @@ #elif defined(PCBX9LITE) #define TR_POTS_VSRCRAW "\310S1\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0" -#elif defined(PCBX9DP) && PCBREV >= 2019 - #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0" - #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0" #elif defined(PCBTARANIS) #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0" - #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0" + #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0" #elif defined(PCBSKY9X) #define TR_POTS_VSRCRAW "P1\0 ""P2\0 ""P3\0 " #define TR_SW_VSRCRAW "3POS" "THR\0""RUD\0""ELE\0""AIL\0""GEA\0""TRN\0" From 44ae96d4f0faaa99ddc4e4afac1246e6f7775dde Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 1 Oct 2019 10:02:12 +0200 Subject: [PATCH 102/257] Fix bind on 9x nivigation (#6875) --- radio/src/gui/128x64/model_setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 0865f6f95..39ac6fe6f 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -1282,7 +1282,7 @@ void menuModelSetup(event_t event) if (isModuleR9MNonAccess(moduleIdx) || isModuleD16(moduleIdx)) { #if defined(PCBXLITE) if (EVT_KEY_MASK(event) == KEY_ENTER) { -#elif defined(PCBSKY9X) || defined(PCBAR9X) +#elif defined(NAVIGATION_9X) if (event == EVT_KEY_FIRST(KEY_ENTER)) { #else if (event == EVT_KEY_BREAK(KEY_ENTER)) { From 5a317d7ba8b7a9a128b4479de7466d64356978e6 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 1 Oct 2019 15:01:21 +0200 Subject: [PATCH 103/257] Prevent conflict with trainer on external module (#6846) Prevent conflict with trainer on external module --- radio/src/gui/gui_common.cpp | 11 ++++++++++- radio/src/gui/gui_common.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index e9a0f2077..a26d4eb15 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -536,6 +536,15 @@ bool isPxx2IsrmChannelsCountAllowed(int channels) } #endif +bool isTrainerUsingModuleBay() +{ +#if defined(PCBTARANIS) + if (TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE <= g_model.trainerData.mode && g_model.trainerData.mode <= TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) + return true; +#endif + return false; +} + bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType) { switch (moduleType) { @@ -647,7 +656,7 @@ bool isExternalModuleAvailable(int moduleType) #endif #if defined(HARDWARE_INTERNAL_MODULE) - if (isModuleUsingSport(EXTERNAL_MODULE, moduleType) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type)) + if ((isModuleUsingSport(EXTERNAL_MODULE, moduleType) || isTrainerUsingModuleBay()) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type)) return false; #endif diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 9f4d12894..7239aaaec 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -62,6 +62,7 @@ bool isSwitchAvailableInTimers(int swtch); bool isR9MModeAvailable(int mode); bool isPxx2IsrmChannelsCountAllowed(int channels); bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType); +bool isTrainerUsingModuleBay(); bool isExternalModuleAvailable(int moduleType); bool isInternalModuleAvailable(int moduleType); bool isRfProtocolAvailable(int protocol); From e3c4082da7a5c9a7e2c4b26360fc5dac427b6f7b Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 1 Oct 2019 15:32:40 +0200 Subject: [PATCH 104/257] Compilation --- radio/src/opentx.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 3bc6913ad..b7248c5f8 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -869,10 +869,13 @@ static void checkRTCBattery() void checkFailsafe() { for (int i=0; i Date: Tue, 1 Oct 2019 15:41:15 +0200 Subject: [PATCH 105/257] Travis compilation fix --- CMakeLists.txt | 5 +++++ companion/src/tests/conversions.cpp | 14 +++++++------- tools/commit-tests.sh | 29 +++++++++++++++-------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d9b3abb6..e60c35532 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,11 @@ endif() add_subdirectory(${RADIO_SRC_DIRECTORY}) +add_custom_target(tests-radio + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/gtests-radio + DEPENDS gtests-radio + ) + if(Qt5Core_FOUND AND NOT DISABLE_COMPANION) add_subdirectory(${COMPANION_SRC_DIRECTORY}) add_custom_target(gtests DEPENDS gtests-radio gtests-companion) diff --git a/companion/src/tests/conversions.cpp b/companion/src/tests/conversions.cpp index bee7b9520..611c2a3f1 100644 --- a/companion/src/tests/conversions.cpp +++ b/companion/src/tests/conversions.cpp @@ -42,7 +42,7 @@ TEST(Conversions, ConversionX9DPFrom22) EXPECT_STREQ("Thr", model.inputNames[0]); EXPECT_STREQ("Tes", model.sensorData[0].label); EXPECT_EQ(10, model.sensorData[0].id); - EXPECT_EQ(9, model.sensorData[0].instance); + EXPECT_EQ(10, model.sensorData[0].instance); EXPECT_EQ(RawSource(SOURCE_TYPE_TELEMETRY,0).toValue(), model.logicalSw[0].val1); } @@ -77,7 +77,7 @@ TEST(Conversions, ConversionX9DPFrom23) EXPECT_STREQ("Rud", model1.inputNames[0]); EXPECT_STREQ("Tes", model1.sensorData[0].label); EXPECT_EQ(10, model1.sensorData[0].id); - EXPECT_EQ(10, model1.sensorData[0].instance); + EXPECT_EQ(11, model1.sensorData[0].instance); EXPECT_EQ(RawSource(SOURCE_TYPE_TELEMETRY,0).toValue(), model1.logicalSw[0].val1); const ModelData & model2 = radioData.models[1]; @@ -96,7 +96,7 @@ TEST(Conversions, ConversionX9DPFrom23) EXPECT_STREQ("Rud", model2.inputNames[0]); EXPECT_STREQ("Tes", model2.sensorData[0].label); EXPECT_EQ(10, model2.sensorData[0].id); - EXPECT_EQ(10, model2.sensorData[0].instance); + EXPECT_EQ(11, model2.sensorData[0].instance); EXPECT_EQ(RawSource(SOURCE_TYPE_TELEMETRY,0).toValue(), model2.logicalSw[0].val1); } @@ -130,7 +130,7 @@ TEST(Conversions, ConversionX7From22) EXPECT_STREQ("Tes", model.sensorData[0].label); EXPECT_EQ(10, model.sensorData[0].id); - EXPECT_EQ(9, model.sensorData[0].instance); + EXPECT_EQ(10, model.sensorData[0].instance); EXPECT_EQ(900, model.limitData[0].max); // -100 EXPECT_EQ(10, model.flightModeData[0].gvars[0]); @@ -178,7 +178,7 @@ TEST(Conversions, ConversionXLiteFrom22) EXPECT_STREQ("Tes", model.sensorData[0].label); EXPECT_EQ(10, model.sensorData[0].id); - EXPECT_EQ(8, model.sensorData[0].instance); + EXPECT_EQ(9, model.sensorData[0].instance); EXPECT_EQ(900, model.limitData[0].max); // -100 EXPECT_EQ(LS_FN_VPOS, model.logicalSw[0].func); @@ -284,7 +284,7 @@ TEST(Conversions, ConversionX10From22) EXPECT_STREQ("Rud", model.inputNames[0]); EXPECT_STREQ("Tes", model.sensorData[0].label); EXPECT_EQ(10, model.sensorData[0].id); - EXPECT_EQ(9, model.sensorData[0].instance); + EXPECT_EQ(10, model.sensorData[0].instance); EXPECT_EQ(5 + 2 + 3, model.thrTraceSrc); // CH3 } @@ -360,6 +360,6 @@ TEST(Conversions, ConversionX12SFrom22) EXPECT_STREQ("Rud", model.inputNames[0]); EXPECT_STREQ("Tes", model.sensorData[0].label); EXPECT_EQ(10, model.sensorData[0].id); - EXPECT_EQ(9, model.sensorData[0].instance); + EXPECT_EQ(10, model.sensorData[0].instance); EXPECT_EQ(5 + 2 + 3, model.thrTraceSrc); // CH3 } diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 73c7a2775..edb1dedaa 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -64,7 +64,7 @@ if [[ " SKY9X ARM9X ALL " =~ " ${FLAVOR} " ]] ; then 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 + make -j${CORES} tests-radio fi if [[ " AR9X ARM9X ALL " =~ " ${FLAVOR} " ]] ; then @@ -73,7 +73,7 @@ if [[ " AR9X ARM9X ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=AR9X -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " 9XRPRO ARM9X ALL " =~ " ${FLAVOR} " ]] ; then @@ -82,7 +82,7 @@ if [[ " 9XRPRO ARM9X ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=9XRPRO -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X9LITE ALL " =~ " ${FLAVOR} " ]] ; then @@ -91,7 +91,7 @@ if [[ " X9LITE ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X9LITE -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X7 ALL " =~ " ${FLAVOR} " ]] ; then @@ -100,7 +100,7 @@ if [[ " X7 ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X7 -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " XLITE ALL " =~ " ${FLAVOR} " ]] ; then @@ -109,7 +109,7 @@ if [[ " XLITE ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=XLITE -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " XLITES ALL " =~ " ${FLAVOR} " ]] ; then @@ -118,7 +118,7 @@ if [[ " XLITES ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=XLITES -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X9D X9 ALL " =~ " ${FLAVOR} " ]] ; then @@ -127,7 +127,7 @@ if [[ " X9D X9 ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X9D -DHELI=YES -DLUA=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X9D+ X9 ALL " =~ " ${FLAVOR} " ]] ; then @@ -136,7 +136,7 @@ if [[ " X9D+ X9 ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X9D+ -DHELI=YES -DLUA=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X9D+2019 X9 ALL " =~ " ${FLAVOR} " ]] ; then @@ -145,7 +145,7 @@ if [[ " X9D+2019 X9 ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X9D+ -DPCBREV=2019 -DHELI=YES -DLUA=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X9E X9 ALL " =~ " ${FLAVOR} " ]] ; then @@ -154,7 +154,7 @@ if [[ " X9E X9 ALL " =~ " ${FLAVOR} " ]] ; then 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 - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X10 HORUS ALL " =~ " ${FLAVOR} " ]] ; then @@ -163,7 +163,7 @@ if [[ " X10 HORUS ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X10 -DHELI=YES -DLUA=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " X12S HORUS ALL " =~ " ${FLAVOR} " ]] ; then @@ -172,7 +172,7 @@ if [[ " X12S HORUS ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X12S -DHELI=YES -DLUA=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " T12 ALL " =~ " ${FLAVOR} " ]] ; then @@ -181,7 +181,7 @@ if [[ " T12 ALL " =~ " ${FLAVOR} " ]] ; then cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T12 -DHELI=YES -DGVARS=YES ${SRCDIR} make -j${CORES} ${FIRMARE_TARGET} make -j${CORES} libsimulator - make -j${CORES} tests + make -j${CORES} tests-radio fi if [[ " DEFAULT ALL " =~ " ${FLAVOR} " ]] ; then @@ -189,4 +189,5 @@ if [[ " DEFAULT ALL " =~ " ${FLAVOR} " ]] ; then rm -rf * cmake ${COMMON_OPTIONS} ${SRCDIR} make -j${CORES} + make -j${CORES} tests fi From 2a41bf086a3d68edeb00d8ec65b755bf99406832 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 1 Oct 2019 15:57:27 +0200 Subject: [PATCH 106/257] X12S RTC voltage fix --- radio/src/targets/horus/x12s_adc_driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/horus/x12s_adc_driver.cpp b/radio/src/targets/horus/x12s_adc_driver.cpp index 932f752a0..2833c4620 100644 --- a/radio/src/targets/horus/x12s_adc_driver.cpp +++ b/radio/src/targets/horus/x12s_adc_driver.cpp @@ -139,7 +139,7 @@ void adcInit() uint16_t getRTCBatteryVoltage() { - return (rtcBatteryVoltage * ADC_VREF_PREC2) / 2048; + return (rtcBatteryVoltage * 2 * ADC_VREF_PREC2) / 2048; } const uint16_t adcCommands[MOUSE1+2] = From 9dffcd3e26a0c59fb306d75615c11bc981ae1a55 Mon Sep 17 00:00:00 2001 From: Kilrah Date: Tue, 1 Oct 2019 17:33:01 +0200 Subject: [PATCH 107/257] French translations --- radio/src/translations/fr.h.txt | 144 ++++++++++++++++---------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 51b03fa7d..e27845efc 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -455,10 +455,10 @@ #endif #define TR_PROTO TR(INDENT "Proto.", INDENT "Protocole") #define TR_PPMFRAME INDENT "Trame PPM" -#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") -#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define TR_REFRESHRATE INDENT "Période" +#define STR_WARN_BATTVOLTAGE TR(INDENT "Signal est VBAT: ", INDENT "ATTENTION: signal est à VBAT: ") #define TR_MS "ms" -#define TR_FREQUENCY INDENT "Frequency" +#define TR_FREQUENCY INDENT "Fréquence" #define TR_SWITCH TR("Inter", "Interrupteur") #define TR_TRIMS "Trims" #define TR_FADEIN "Fondu ON" @@ -478,12 +478,12 @@ #define TR_SUBTYPE INDENT "Sous-type" #define TR_NOFREEEXPO "Max expos atteint!" #define TR_NOFREEMIXER "Max mixages atteint!" -#define TR_SOURCE "Source" +#define TR_SOURCE "Source" #define TR_WEIGHT "Ratio" #define TR_EXPO TR("Expo", "Exponentiel") #define TR_SIDE "Coté" #define TR_DIFFERENTIAL "Différentiel" -#define TR_OFFSET "Décalage" +#define TR_OFFSET "Décalage" #define TR_TRIM "Trim" #define TR_DREX "DRex" #define DREX_CHBOX_OFFSET 30 @@ -491,8 +491,8 @@ #define TR_FLMODE TR("Phase", "Phases") #define TR_MIXWARNING "Alerte" #define TR_OFF "OFF" -#define TR_ANTENNA "Antenna" -#define TR_NO_INFORMATION TR("No info", "No information") +#define TR_ANTENNA "Antenne" +#define TR_NO_INFORMATION TR("Pas d'info", "Pas d'information") #define TR_MULTPX "Opération" #define TR_DELAYDOWN "Retard bas" #define TR_DELAYUP "Retard haut" @@ -516,7 +516,7 @@ #define TR_HAPTIC_LABEL "Vibreur" #define TR_HAPTICSTRENGTH INDENT "Force" #define TR_GYRO_LABEL "Gyro" -#define TR_GYRO_OFFSET "Offset" +#define TR_GYRO_OFFSET "Décalage" #define TR_GYRO_MAX "Max" #define TR_CONTRAST "Contraste" #define TR_ALARMS_LABEL "Alarmes" @@ -540,8 +540,8 @@ #define TR_BLOFFBRIGHTNESS INDENT "Luminosité OFF" #define TR_BLCOLOR INDENT "Couleur" #define TR_SPLASHSCREEN "Logo d'accueil" -#define TR_PWR_ON_DELAY "Pwr On delay" -#define TR_PWR_OFF_DELAY "Pwr Off delay" +#define TR_PWR_ON_DELAY "Délai btn ON" +#define TR_PWR_OFF_DELAY "Délai btn OFF" #define TR_THROTTLEWARNING TR(INDENT "Alerte gaz", INDENT "Alerte gaz") #define TR_SWITCHWARNING TR(INDENT "Alerte int", INDENT "Pos. interrupteurs") #define TR_POTWARNINGSTATE TR(INDENT "Pot&Slid.", INDENT "Pots & sliders") @@ -579,11 +579,11 @@ #define OFS_RX 4 #define TR_ACCEL "Acc:" #define TR_NODATA CENTER "NO DATA" -#define TR_US "us" +#define TR_US "us" #define TR_TMR1LATMINUS "Tmr1Lat min\037\124us" - #define TR_TMIXMAXMS "Tmix max" - #define TR_FREE_STACK "Free stack" +#define TR_TMIXMAXMS "Tmix max" +#define TR_FREE_STACK "Free stack" #define TR_MENUTORESET TR_ENTER" pour reset" #define TR_PPM_TRAINER "TR" @@ -648,8 +648,8 @@ #define TR_MULTI_RFTUNE TR(INDENT "Ajust.fréq", INDENT "Ajustement fréq.") #define TR_MULTI_TELEMETRY "Télémétrie" #define TR_MULTI_VIDFREQ TR(INDENT "Fréq. vidéo", INDENT "Fréquence vidéo") -#define TR_RFPOWER TR(INDENT "Puiss. RF", INDENT "Puissance RF") -#define TR_MULTI_FIXEDID TR("FixedID", "Fixed ID") +#define TR_RFPOWER TR(INDENT "Puiss. RF", INDENT "Puissance RF") +#define TR_MULTI_FIXEDID "ID fixe" #define TR_MULTI_OPTION TR(INDENT "Option", INDENT "Option perso") #define TR_MULTI_AUTOBIND TR(INDENT "Bind auto", INDENT "Bind automatique") #define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodét.", INDENT "Autodétection") @@ -704,37 +704,37 @@ #define TR_CAT_NOT_EMPTY "Categorie non vide" #define TR_SDCARD_ERROR "Erreur carte SD" #define TR_NO_SDCARD "Carte SD indisponible" -#define TR_WAITING_FOR_RX "Waiting for RX..." -#define TR_WAITING_FOR_TX "Waiting for TX..." -#define TR_NO_TOOLS "No tools available" +#define TR_WAITING_FOR_RX "Attente du RX..." +#define TR_WAITING_FOR_TX "Attente du TX..." +#define TR_NO_TOOLS "Pas d'outils dispo" #define TR_NORMAL "Normal" -#define TR_NOT_INVERTED "Not inv" -#define TR_NOT_CONNECTED "!Connected" -#define TR_CONNECTED "Connected" +#define TR_NOT_INVERTED "Non inv" +#define TR_NOT_CONNECTED "!Connecté" +#define TR_CONNECTED "Connecté" #define TR_FLEX_915 "Flex 915MHz" #define TR_FLEX_868 "Flex 868MHz" -#define TR_16CH_WITHOUT_TELEMETRY TR("16CH without telem.", "16CH without telemetry") -#define TR_16CH_WITH_TELEMETRY TR("16CH with telem.", "16CH with telemetry") -#define TR_8CH_WITH_TELEMETRY TR("8CH with telem.", "8CH with telemetry") -#define TR_EXT_ANTENNA "Ext. antenna" +#define TR_16CH_WITHOUT_TELEMETRY TR("16CH sans télém.", "16CH sans télémétrie") +#define TR_16CH_WITH_TELEMETRY TR("16CH avec télém.", "16CH avec télémétrie") +#define TR_8CH_WITH_TELEMETRY TR("8CH avec télém.", "8CH avec télémétrie") +#define TR_EXT_ANTENNA "Antenne externe" #define TR_PIN "Pin" -#define TR_UPDATE_RX_OPTIONS "Update RX options?" -#define TR_UPDATE_TX_OPTIONS "Update TX options?" -#define TR_MODULES_RX_VERSION "Modules / RX version" -#define TR_MENU_MODULES_RX_VERSION "MODULES / RX VERSION" -#define TR_MENU_FIRM_OPTIONS "FIRMWARE OPTIONS" +#define TR_UPDATE_RX_OPTIONS "Sauver options RX?" +#define TR_UPDATE_TX_OPTIONS "Sauver options TX?" +#define TR_MODULES_RX_VERSION "Versions modules / RX" +#define TR_MENU_MODULES_RX_VERSION "VERSIONS MODULES / RX " +#define TR_MENU_FIRM_OPTIONS "OPTIONS FIRMWARE" #define TR_GYRO "Gyro" -#define TR_STICKS_POTS_SLIDERS "Sticks/Pots/Sliders" -#define TR_PWM_STICKS_POTS_SLIDERS "PWM Sticks/Pots/Sliders" -#define TR_RF_PROTOCOL "RF Protocol" -#define TR_MODULE_OPTIONS "Module options" -#define TR_POWER "Power" -#define TR_NO_TX_OPTIONS "No TX options" -#define TR_RTC_BATT "RTC Batt" -#define TR_POWER_METER_EXT "Power Meter (EXT)" -#define TR_POWER_METER_INT "Power Meter (INT)" -#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" -#define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" +#define TR_STICKS_POTS_SLIDERS "Manches/Pots/leviers" +#define TR_PWM_STICKS_POTS_SLIDERS "Manches PWM/Pots/leviers" +#define TR_RF_PROTOCOL "Protocole RF" +#define TR_MODULE_OPTIONS "Options module" +#define TR_POWER "Puissance" +#define TR_NO_TX_OPTIONS "Pas d'options TX" +#define TR_RTC_BATT "Pile RTC" +#define TR_POWER_METER_EXT "Puissancemètre (EXT)" +#define TR_POWER_METER_INT "Puissancemètre (INT)" +#define TR_SPECTRUM_ANALYSER_EXT TR("Spectre (EXT)", "Analyseur spectre (EXT)") +#define TR_SPECTRUM_ANALYSER_INT TR("Spectre (INT)", "Analyseur spectre (INT)") #define TR_SDCARD_FULL "Carte SD pleine" #define TR_INCOMPATIBLE "Incompatible" #define TR_WARNING "ALERTE" @@ -748,9 +748,9 @@ #define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD") #define TR_NIGHTLY_NOTSAFE "Version de test uniq." #define TR_WRONG_SDCARDVERSION "Version requise: " -#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low power mode" -#define TR_BATTERY "BATTERY" +#define TR_WARN_RTC_BATTERY_LOW "Batterie RTC faible" +#define TR_WARN_MULTI_LOWPOWER "Mode basse puis." +#define TR_BATTERY "BATTERIE" #define TR_WRONG_PCBREV "PCB incorrect détecté" #define TR_EMERGENCY_MODE "MODE SECOURS" #define TR_PCBREV_ERROR "Erreur PCB" @@ -799,11 +799,11 @@ #define TR_TIME "Heure" #define TR_MAXBAUDRATE "Max bauds" #define TR_BLUETOOTH "Bluetooth" -#define TR_BLUETOOTH_DISC "Discover" +#define TR_BLUETOOTH_DISC "Découvrir" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" -#define TR_BLUETOOTH_PIN_CODE "PIN code" +#define TR_BLUETOOTH_DIST_ADDR INDENT "Addr dist." +#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Addr locale" +#define TR_BLUETOOTH_PIN_CODE "Code PIN" #define TR_BAUDRATE "Baudrate BT" #define LEN_BLUETOOTH_MODES "\012" #if defined(PCBX9E) @@ -831,9 +831,9 @@ #define TR_VIEW_TEXT "Voir texte" #define TR_FLASH_BOOTLOADER "Flasher BootLoader" #define TR_FLASH_EXTERNAL_DEVICE TR("Flasher S.Port", "Flasher S.Port externe") -#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") -#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" +#define TR_FLASH_RECEIVER_OTA "Flasher RX OTA" +#define TR_FLASH_BLUETOOTH_MODULE TR("Flash module BT", "Flash module Bluetooth") +#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flasher pwr mngt unit" #define TR_CURRENT_VERSION "Version courante :" #define TR_FLASH_INTERNAL_MODULE TR("Flasher module int.", "Flasher module interne") #define TR_FLASH_EXTERNAL_MODULE TR("Flasher module ext.", "Flasher module externe") @@ -842,16 +842,16 @@ #define TR_WRITING TR("\14Ecriture...", "\032Ecriture...") #define TR_CONFIRM_FORMAT "Confirmer Formatage?" #define TR_INTERNALRF "HF interne" -#define TR_INTERNAL_MODULE TR("Int. module","Internal module") -#define TR_EXTERNAL_MODULE TR("Ext. module","External module") -#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required" -#define TR_TELEMETRY_DISABLED "Telem. disabled" -#define TR_MORE_OPTIONS_AVAILABLE "More options available" -#define TR_NO_MODULE_INFORMATION "No module information" +#define TR_INTERNAL_MODULE TR("Module int.","Module interne") +#define TR_EXTERNAL_MODULE TR("Module ext.","Module externe") +#define TR_OPENTX_UPGRADE_REQUIRED "Màj OpenTX nécessaire" +#define TR_TELEMETRY_DISABLED "Télém. désactivée" +#define TR_MORE_OPTIONS_AVAILABLE "Autres options disponibles" +#define TR_NO_MODULE_INFORMATION "Pas d'info module" #define TR_EXTERNALRF "HF externe" #define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Type failsafe") #define TR_FAILSAFESET "REGLAGES FAILSAFE" -#define TR_REG_ID TR("ID Enr.", "ID Enregisrement") +#define TR_REG_ID TR("ID Enr.", "ID Enregistr.") #define TR_OWNER_ID "ID Radio" #define TR_PINMAPSET "PINMAP" #define TR_HOLD "Hold" @@ -905,7 +905,7 @@ #define TR_PXX2_SELECT_RX "Sélect RX..." #define TR_PXX2_DEFAULT "" #define TR_BT_SELECT_DEVICE "Sélect appareil..." -#define TR_DISCOVER "Découvrir" +#define TR_DISCOVER "Découvrir" #define TR_BUTTON_INIT BUTTON("Init") #define TR_WAITING "Attente..." #define TR_RECEIVER_DELETE "Suppr récept.?" @@ -914,8 +914,8 @@ #define TR_BIND "Bind" #define TR_REGISTER TR("Enr", "Enregistr.") #define TR_MODULE_RANGE BUTTON(TR("Prt", "Port.")) -#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS") -#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete")) +#define TR_RECEIVER_OPTIONS TR("OPTIONS REC.", "OPTIONS RECEPTEUR") +#define TR_DEL_BUTTON BUTTON(TR("Eff", "Effacer")) #define TR_RESET_BTN BUTTON("RAZ") #define TR_DEBUG "Debug" #define TR_KEYS_BTN BUTTON(TR("Btns","Inters")) @@ -937,18 +937,18 @@ #define TR_ANTENNACONFIRM1 "Vraiment changer?" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\021" -#define TR_ANTENNA_MODES "Interne\0 ""Ask\0 ""Par modèle\0 ""Interne + Externe" +#define TR_ANTENNA_MODES "Interne\0 ""Demander\0 ""Par modèle\0 ""Interne + Externe" #else -#define LEN_ANTENNA_MODES "\011" -#define TR_ANTENNA_MODES "Internal\0""Ask\0 ""Per model""External" +#define LEN_ANTENNA_MODES "\012" +#define TR_ANTENNA_MODES "Interne\0 ""Demander\0 ""Par modèle""Externe\0 " #endif -#define TR_USE_INTERNAL_ANTENNA TR("Use int. antenna", "Use internal antenna") -#define TR_USE_EXTERNAL_ANTENNA TR("Use ext. antenna", "Use external antenna") +#define TR_USE_INTERNAL_ANTENNA TR("Util antenne int", "Utiliser antenne interne") +#define TR_USE_EXTERNAL_ANTENNA TR("Util antenne ext", "Utiliser antenne externe") #define TR_ANTENNACONFIRM2 TR("Vérif antenne", "Installer l'antenne d'abord!") -#define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Nécessite firm." -#define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Requires FCC" -#define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Requires EU" -#define TR_MODULE_PROTOCOL_WARN_LINE2 "R9M non certifié" +#define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Nécessite firm." +#define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Nécessite FCC" +#define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Nécessite EU" +#define TR_MODULE_PROTOCOL_WARN_LINE2 "R9M non certifié" #define TR_LOWALARM INDENT "Alarme basse" #define TR_CRITICALALARM INDENT "Alarme critique" #define TR_RSSIALARM_WARN TR("RSSI", "TELEMETRIE") @@ -979,7 +979,7 @@ #define TR_PREFLIGHT "Vérifications avant vol" #define TR_CHECKLIST TR(INDENT "Notes", INDENT "Afficher notes") #define TR_FAS_OFFSET TR(INDENT "Corr FAS", INDENT "Correction FAS") -#define TR_AUX_SERIAL_MODE "Port série" +#define TR_AUX_SERIAL_MODE "Port série" #define TR_SCRIPT "Script" #define TR_INPUTS "Entrées" #define TR_OUTPUTS "Sorties" @@ -1173,7 +1173,7 @@ #define TR_MENU_OTHER "Autres" #define TR_MENU_INVERT "Inverser" #define TR_JITTER_FILTER "Filtre ADC" -#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_RTC_CHECK TR("Vérif. RTC", "Vérification pile RTC") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" From 7a0a6a93410df9b0fdccc34c34b69909a5f16e32 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 1 Oct 2019 18:58:07 +0200 Subject: [PATCH 108/257] Fixes #6873 --- radio/src/switches.cpp | 1 - radio/src/targets/taranis/keys_driver.cpp | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 1a405fb05..eb950cd0a 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -33,7 +33,6 @@ #define SWITCH_WARNING_LIST_Y 4*FH+4 #endif - enum LogicalSwitchContextState { SWITCH_START, SWITCH_DELAY, diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp index 144d7e97e..907372900 100644 --- a/radio/src/targets/taranis/keys_driver.cpp +++ b/radio/src/targets/taranis/keys_driver.cpp @@ -194,6 +194,8 @@ uint32_t switchState(uint8_t index) ADD_3POS_CASE(D, 3); ADD_2POS_CASE(F); ADD_2POS_CASE(H); + ADD_2POS_CASE(I); + ADD_2POS_CASE(J); #else ADD_3POS_CASE(D, 3); ADD_3POS_CASE(E, 4); From f8c9382972f09da8f956c303d3b40e7adc1acf81 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 1 Oct 2019 18:59:34 +0200 Subject: [PATCH 109/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index f4378c9d0..45a95ec7a 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1575,3 +1575,4 @@ He Liu Andrias Thomsen Alain Azais Alan Stuart +Fernando Rimoldi From ab385d1bdbc736c818e2a585b8cea6f4462f72f0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 1 Oct 2019 15:01:21 +0200 Subject: [PATCH 110/257] Prevent conflict with trainer on external module (#6846) Prevent conflict with trainer on external module --- radio/src/gui/gui_common.cpp | 11 ++++++++++- radio/src/gui/gui_common.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index db46986bb..cee207093 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -536,6 +536,15 @@ bool isPxx2IsrmChannelsCountAllowed(int channels) } #endif +bool isTrainerUsingModuleBay() +{ +#if defined(PCBTARANIS) + if (TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE <= g_model.trainerData.mode && g_model.trainerData.mode <= TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) + return true; +#endif + return false; +} + bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType) { switch (moduleType) { @@ -644,7 +653,7 @@ bool isExternalModuleAvailable(int moduleType) #endif #if defined(HARDWARE_INTERNAL_MODULE) - if (isModuleUsingSport(EXTERNAL_MODULE, moduleType) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type)) + if ((isModuleUsingSport(EXTERNAL_MODULE, moduleType) || isTrainerUsingModuleBay()) && isModuleUsingSport(INTERNAL_MODULE, g_model.moduleData[INTERNAL_MODULE].type)) return false; #endif diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index b941d2ec9..16f5ac397 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -62,6 +62,7 @@ bool isSwitchAvailableInTimers(int swtch); bool isR9MModeAvailable(int mode); bool isPxx2IsrmChannelsCountAllowed(int channels); bool isModuleUsingSport(uint8_t moduleBay, uint8_t moduleType); +bool isTrainerUsingModuleBay(); bool isExternalModuleAvailable(int moduleType); bool isInternalModuleAvailable(int moduleType); bool isRfProtocolAvailable(int protocol); From 3b6a7b752354a2597c6dad9c8cedfa9d994d8a90 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 2 Oct 2019 07:49:24 +0200 Subject: [PATCH 111/257] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 45a95ec7a..b6aedbc4b 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1576,3 +1576,5 @@ Andrias Thomsen Alain Azais Alan Stuart Fernando Rimoldi +James Snodgrass + From db53255d7b8713411d140d9fab16008228ee02fb Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 2 Oct 2019 08:18:38 +0200 Subject: [PATCH 112/257] Update CREDITS.txt --- CREDITS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CREDITS.txt b/CREDITS.txt index b6aedbc4b..80fb4e8f8 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1577,4 +1577,4 @@ Alain Azais Alan Stuart Fernando Rimoldi James Snodgrass - +Diego Mendoza Gonzalez From 85a2b138f7b122cd50ccfcb7f7eff4f2fa34bc7c Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 2 Oct 2019 12:52:20 +0200 Subject: [PATCH 113/257] Fix X7 SJ using wrong pin --- radio/src/gui/128x64/radio_diagkeys.cpp | 2 +- radio/src/targets/taranis/hal.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp index bd8668c82..a5840754a 100644 --- a/radio/src/gui/128x64/radio_diagkeys.cpp +++ b/radio/src/gui/128x64/radio_diagkeys.cpp @@ -64,7 +64,7 @@ void menuRadioDiagKeys(event_t event) #else if (i < NUM_SWITCHES) { if (SWITCH_EXISTS(i)) { - y = MENU_HEADER_HEIGHT + 1 + FH*i; + y = (NUM_SWITCHES > 6 ? 0 : MENU_HEADER_HEIGHT) + FH*i; getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i); getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3)); drawSwitch(8*FW+4, y, sw, 0); diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 99acd429b..20904fb1c 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -521,8 +521,8 @@ #define HARDWARE_SWITCH_J #define SWITCHES_GPIO_REG_I GPIOC->IDR #define SWITCHES_GPIO_PIN_I GPIO_Pin_13 // PC.13 - #define SWITCHES_GPIO_REG_J GPIOC->IDR - #define SWITCHES_GPIO_PIN_J GPIO_Pin_10 // PC.10 + #define SWITCHES_GPIO_REG_J GPIOD->IDR + #define SWITCHES_GPIO_PIN_J GPIO_Pin_10 // PD.10 #endif #if defined(PCBX9E) @@ -632,8 +632,8 @@ #elif defined(RADIO_X7) #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) #define KEYS_GPIOA_PINS GPIO_Pin_5 - #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_10 | GPIO_Pin_13) - #define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15) + #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_13) + #define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15) #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15) #elif defined(PCBX9LITE) #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) From d1485166efa2c364a49f1c6a243dba131211e6e8 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 2 Oct 2019 14:56:47 +0200 Subject: [PATCH 114/257] Rework VIRTUAL EVENTS (#6878) Virtual events --- radio/src/lua/api_general.cpp | 85 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 75f1a36d8..04b0f814a 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -54,10 +54,10 @@ #define FIND_FIELD_DESC 0x01 #define KEY_EVENTS(xxx, yyy) \ - { "EVT_"#xxx"_FIRST", EVT_KEY_FIRST(yyy) }, \ - { "EVT_"#xxx"_BREAK", EVT_KEY_BREAK(yyy) }, \ - { "EVT_"#xxx"_LONG", EVT_KEY_LONG(yyy) }, \ - { "EVT_"#xxx"_REPT", EVT_KEY_REPT(yyy) } + { "EVT_"#xxx"_FIRST", EVT_KEY_FIRST(yyy) }, \ + { "EVT_"#xxx"_BREAK", EVT_KEY_BREAK(yyy) }, \ + { "EVT_"#xxx"_LONG", EVT_KEY_LONG(yyy) }, \ + { "EVT_"#xxx"_REPT", EVT_KEY_REPT(yyy) } /*luadoc @function getVersion() @@ -1379,7 +1379,7 @@ static int luaChdir(lua_State * L) @function loadScript(file [, mode], [,env]) Load a Lua script file. This is similar to Lua's own [loadfile()](https://www.lua.org/manual/5.2/manual.html#pdf-loadfile) -API method, but it uses OpenTx's optional pre-compilation feature to save memory and time during load. +API method, but it uses OpenTx's optional pre-compilation feature to save memory and time during load. Return values are same as from Lua API loadfile() method: If the script was loaded w/out errors then the loaded script (or "chunk") is returned as a function. Otherwise, returns nil plus the error message. @@ -1675,53 +1675,48 @@ const luaR_value_entry opentxConstants[] = { { "FIXEDWIDTH", FIXEDWIDTH }, #endif -// Virtual Page Next/Previous -#if defined(KEYS_GPIO_REG_PGUP) && defined(KEYS_GPIO_REG_PGDN) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_FIRST(KEY_PGUP) }, - { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_FIRST(KEY_PGDN) }, -#elif defined(KEYS_GPIO_REG_PGDN) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_PGDN) }, - { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PGDN) }, -#elif defined(KEYS_GPIO_REG_UP) && defined(KEYS_GPIO_REG_DOWN) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_UP) }, - { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_LONG(KEY_DOWN) }, -#elif defined(KEYS_GPIO_REG_PAGE) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_PAGE) }, - { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PAGE) }, +// Virtual events +#if defined(ROTARY_ENCODER_NAVIGATION) + { "EVT_VIRTUAL_PREVIOUS", EVT_ROTARY_LEFT }, + { "EVT_VIRTUAL_PREVIOUS_REPT", EVT_ROTARY_LEFT }, + { "EVT_VIRTUAL_NEXT", EVT_ROTARY_RIGHT }, + { "EVT_VIRTUAL_NEXT_REPT", EVT_ROTARY_RIGHT }, +#else + { "EVT_VIRTUAL_PREVIOUS", EVT_KEY_FIRST(KEY_LEFT) }, + { "EVT_VIRTUAL_PREVIOUS_REPT", EVT_KEY_REPT(KEY_LEFT) }, + { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_RIGHT) }, + { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_RIGHT) }, #endif -// Virtual exit - { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, - -// Virtual enter -#if defined(KEYS_GPIO_REG_ENTER) +#if defined(NAVIGATION_9X) || defined(NAVIGATION_XLITE) + { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_UP) }, + { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_UP) }, + { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_DOWN) }, + { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_DOWN) }, { "EVT_VIRTUAL_ENTER", EVT_KEY_BREAK(KEY_ENTER) }, { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, -#endif - -// Virtual menu -#if defined(KEYS_GPIO_REG_MENU) + { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, +#elif defined(NAVIGATION_X7) || defined(NAVIGATION_X9D) + { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_PAGE) }, + { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PAGE) }, { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_MENU) }, { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_MENU) }, -#elif defined(KEYS_GPIO_REG_SHIFT) - { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_SHIFT) }, - { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_SHIFT) }, + { "EVT_VIRTUAL_ENTER", EVT_KEY_BREAK(KEY_ENTER) }, + { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, + { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, +#elif defined(NAVIGATION_HORUS) +#if defined(KEYS_GPIO_REG_PGUP) + { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_BREAK(KEY_PGUP) }, + { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PGDN) }, +#else + { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_PGDN) }, + { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PGDN) }, #endif - -// Virtual generic plus-next-right minus-previous-left -#if defined(ROTARY_ENCODER_NAVIGATION) - { "EVT_VIRTUAL_NEXT", EVT_ROTARY_RIGHT}, - { "EVT_VIRTUAL_PREVIOUS", EVT_ROTARY_LEFT }, -#elif defined(KEYS_GPIO_REG_RIGHT) && defined(KEYS_GPIO_REG_LEFT) - { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_RIGHT) }, - { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_RIGHT) }, - { "EVT_VIRTUAL_PREVIOUS", EVT_KEY_FIRST(KEY_LEFT) }, - { "EVT_VIRTUAL_PREVIOUS_REPT", EVT_KEY_REPT(KEY_LEFT) }, -#elif defined(KEYS_GPIO_REG_PLUS) && defined(KEYS_GPIO_REG_MINUS) - { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_PLUS) }, - { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_PLUS) }, - { "EVT_VIRTUAL_PREVIOUS", EVT_KEY_FIRST(KEY_MINUS) }, - { "EVT_VIRTUAL_PREVIOUS_REPT", EVT_KEY_REPT(KEY_MINUS) }, + { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_MODEL) }, + { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_MODEL) }, + { "EVT_VIRTUAL_ENTER", EVT_KEY_BREAK(KEY_ENTER) }, + { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, + { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, #endif #if defined(KEYS_GPIO_REG_EXIT) From 3c7bb1640e76a6510f5fb73be458ce3573d9d609 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 2 Oct 2019 19:35:43 +0200 Subject: [PATCH 115/257] Add old event check too --- radio/util/lua/lua_old_event_check.lua | 73 ++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 radio/util/lua/lua_old_event_check.lua diff --git a/radio/util/lua/lua_old_event_check.lua b/radio/util/lua/lua_old_event_check.lua new file mode 100755 index 000000000..6a02f4329 --- /dev/null +++ b/radio/util/lua/lua_old_event_check.lua @@ -0,0 +1,73 @@ +local toolName = "TNS|LUA event tests|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 virtual_next = 0 +local virtual_previous = 0 +local virtual_next_rept = 0 +local virtual_previous_rept = 0 +local virtual_page_next = 0 +local virtual_page_previous = 0 +local virtual_enter = 0 +local virtual_enter_long = 0 +local virtual_menu = 0 +local virtual_menu_long = 0 + +-- Init +local function init() + +end + +-- Main +local function run(event) + if event == nil then + error("Cannot be run as a model script!") + return 2 + elseif event == EVT_VIRTUAL_EXIT then + return 2 + elseif event == EVT_PLUS_FIRST then + virtual_next = virtual_next + 1 + elseif event == EVT_MINUS_FIRST then + virtual_previous = virtual_previous + 1 + elseif event == EVT_PLUS_REPT then + virtual_next_rept = virtual_next_rept + 1 + elseif event == EVT_MINUS_REPT then + virtual_previous_rept = virtual_previous_rept + 1 + elseif event == EVT_PAGE_BREAK then + virtual_page_next = virtual_page_next +1 + elseif event == EVT_PAGE_LONG then + virtual_page_previous = virtual_page_previous + 1 + elseif event == EVT_ENTER_BREAK then + virtual_enter = virtual_enter + 1 + elseif event == EVT_MENU_BREAK then + virtual_menu = virtual_menu + 1 + end + + lcd.clear() + lcd.drawScreenTitle("LUA EVENT TEST", 0, 0) + lcd.drawText(1, 10, "PLUS: "..virtual_next) + lcd.drawText(1, 20, "MINUS: "..virtual_previous) + lcd.drawText(1, 40, "PLUS_REPT: "..virtual_next_rept) + lcd.drawText(1, 50, "MINUS_REPT: "..virtual_previous_rept) + lcd.drawText(LCD_W/2, 10, "ENTER: "..virtual_enter) + lcd.drawText(LCD_W/2, 20, "MENU: "..virtual_menu) + lcd.drawText(LCD_W/2, 40, "NEXT_PAGE: "..virtual_page_next) + lcd.drawText(LCD_W/2, 50, "PREVIOUS_PAGE: "..virtual_page_previous) + return 0 +end + +return { init=init, run=run } From 6c610ce40dcb21ffd2969c57e5af26c420e55c2c Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 2 Oct 2019 19:43:47 +0200 Subject: [PATCH 116/257] Improve checks --- radio/util/lua/lua_event_test.lua | 1 + radio/util/lua/lua_old_event_check.lua | 1 + 2 files changed, 2 insertions(+) diff --git a/radio/util/lua/lua_event_test.lua b/radio/util/lua/lua_event_test.lua index 13d46bcdc..588c0fa76 100644 --- a/radio/util/lua/lua_event_test.lua +++ b/radio/util/lua/lua_event_test.lua @@ -56,6 +56,7 @@ local function run(event) elseif event == EVT_VIRTUAL_MENU then virtual_menu = virtual_menu + 1 end + killEvents(event); lcd.clear() lcd.drawScreenTitle("LUA EVENT TEST", 0, 0) diff --git a/radio/util/lua/lua_old_event_check.lua b/radio/util/lua/lua_old_event_check.lua index 6a02f4329..6a74a3c0f 100755 --- a/radio/util/lua/lua_old_event_check.lua +++ b/radio/util/lua/lua_old_event_check.lua @@ -51,6 +51,7 @@ local function run(event) virtual_page_next = virtual_page_next +1 elseif event == EVT_PAGE_LONG then virtual_page_previous = virtual_page_previous + 1 + killEvents(event); elseif event == EVT_ENTER_BREAK then virtual_enter = virtual_enter + 1 elseif event == EVT_MENU_BREAK then From c243242f706b10b76877915fc5fd6f41a14ad25d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 2 Oct 2019 23:17:59 +0200 Subject: [PATCH 117/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 80fb4e8f8..ccfd70fec 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1578,3 +1578,4 @@ Alan Stuart Fernando Rimoldi James Snodgrass Diego Mendoza Gonzalez +Dale Wheeler From 2af34ce03b0465aec67375e3d1d6eff8b215f85c Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 2 Oct 2019 23:18:29 +0200 Subject: [PATCH 118/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index ccfd70fec..738d01313 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1579,3 +1579,4 @@ Fernando Rimoldi James Snodgrass Diego Mendoza Gonzalez Dale Wheeler +Nico Wagner From 3943a0581db5bc1d87cc780e1cf16ca7ae5218d1 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 3 Oct 2019 07:51:04 +0200 Subject: [PATCH 119/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 738d01313..6fcbf589e 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1580,3 +1580,4 @@ James Snodgrass Diego Mendoza Gonzalez Dale Wheeler Nico Wagner +James A Davey From b4e603bc86aaaec44589335ade720aa90a2286ee Mon Sep 17 00:00:00 2001 From: Kilrah Date: Thu, 3 Oct 2019 08:30:43 +0200 Subject: [PATCH 120/257] French translation --- radio/src/translations/fr.h.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index e27845efc..69c599265 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1173,7 +1173,7 @@ #define TR_MENU_OTHER "Autres" #define TR_MENU_INVERT "Inverser" #define TR_JITTER_FILTER "Filtre ADC" -#define TR_RTC_CHECK TR("Vérif. RTC", "Vérification pile RTC") +#define TR_RTC_CHECK TR("Vérif. RTC", "Vérif. pile RTC") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" From a2709e067680449666d28942bcda41dc4ff7223f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 3 Oct 2019 09:26:49 +0200 Subject: [PATCH 121/257] Completely removes the macro MOVE_CURSOR_FROM_HERE() which was for AVR (#6880) --- radio/src/dataconstants.h | 8 +-- radio/src/gui/128x64/gui.h | 2 - radio/src/gui/128x64/model_display.cpp | 60 ++++++++++++------- radio/src/gui/128x64/radio_setup.cpp | 1 - radio/src/gui/212x64/gui.h | 1 - radio/src/gui/212x64/model_display.cpp | 53 ++++++++++------ .../conversions/conversions_216_218.cpp | 2 +- .../conversions/conversions_218_219.cpp | 2 +- 8 files changed, 79 insertions(+), 50 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 4586bcc05..2f88ed826 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -334,17 +334,17 @@ enum TelemetryUnit { enum TelemetryScreenType { TELEMETRY_SCREEN_TYPE_NONE, TELEMETRY_SCREEN_TYPE_VALUES, - TELEMETRY_SCREEN_TYPE_GAUGES, -#if defined(LUA) + TELEMETRY_SCREEN_TYPE_BARS, TELEMETRY_SCREEN_TYPE_SCRIPT, +#if defined(LUA) TELEMETRY_SCREEN_TYPE_MAX = TELEMETRY_SCREEN_TYPE_SCRIPT #else - TELEMETRY_SCREEN_TYPE_MAX = TELEMETRY_SCREEN_TYPE_GAUGES + TELEMETRY_SCREEN_TYPE_MAX = TELEMETRY_SCREEN_TYPE_BARS #endif }; #define MAX_TELEMETRY_SCREENS 4 #define TELEMETRY_SCREEN_TYPE(screenIndex) TelemetryScreenType((g_model.screensType >> (2*(screenIndex))) & 0x03) -#define IS_BARS_SCREEN(screenIndex) (TELEMETRY_SCREEN_TYPE(screenIndex) == TELEMETRY_SCREEN_TYPE_GAUGES) +#define IS_BARS_SCREEN(screenIndex) (TELEMETRY_SCREEN_TYPE(screenIndex) == TELEMETRY_SCREEN_TYPE_BARS) constexpr int16_t FAILSAFE_CHANNEL_HOLD = 2000; constexpr int16_t FAILSAFE_CHANNEL_NOPULSE = 2001; diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h index 6a720068a..329a9c3a4 100644 --- a/radio/src/gui/128x64/gui.h +++ b/radio/src/gui/128x64/gui.h @@ -246,7 +246,6 @@ void readModelNotes(); #define IS_ROTARY_EVENT(evt) (EVT_KEY_MASK(evt) >= 0x0e) void repeatLastCursorMove(event_t event); #define REPEAT_LAST_CURSOR_MOVE() { if (EVT_KEY_MASK(event) >= 0x0e) putEvent(event); else repeatLastCursorMove(event); } - #define MOVE_CURSOR_FROM_HERE() if (menuHorizontalPosition > 0) REPEAT_LAST_CURSOR_MOVE() #else #define IS_ROTARY_LEFT(evt) (0) #define IS_ROTARY_RIGHT(evt) (0) @@ -255,7 +254,6 @@ void readModelNotes(); #define IS_ROTARY_EVENT(evt) (0) void repeatLastCursorMove(event_t event); #define REPEAT_LAST_CURSOR_MOVE() repeatLastCursorMove(event) - #define MOVE_CURSOR_FROM_HERE() if (menuHorizontalPosition > 0) REPEAT_LAST_CURSOR_MOVE() #endif // TODO enum diff --git a/radio/src/gui/128x64/model_display.cpp b/radio/src/gui/128x64/model_display.cpp index b9fe1b662..f138593e0 100644 --- a/radio/src/gui/128x64/model_display.cpp +++ b/radio/src/gui/128x64/model_display.cpp @@ -52,21 +52,44 @@ enum MenuModelDisplayItems { #endif #define DISPLAY_COL3 (17*FW+2) -#if defined(LUA) - #define SCREEN_TYPE_ROWS 1 - #define DISPLAY_LINE_ROWS(x) ((TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE || TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_SCRIPT) ? HIDDEN_ROW : (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_GAUGES ? (uint8_t)2 : (uint8_t)1)) -#else - #define SCREEN_TYPE_ROWS 0 - #define DISPLAY_LINE_ROWS(x) (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE ? HIDDEN_ROW : (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_GAUGES ? (uint8_t)2 : (uint8_t)1)) -#endif - -#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, DISPLAY_LINE_ROWS(x), DISPLAY_LINE_ROWS(x), DISPLAY_LINE_ROWS(x), DISPLAY_LINE_ROWS(x) -#define TELEMETRY_CURRENT_SCREEN(k) (k < ITEM_DISPLAY_SCREEN_LABEL2 ? 0 : (k < ITEM_DISPLAY_SCREEN_LABEL3 ? 1 : (k < ITEM_DISPLAY_SCREEN_LABEL4 ? 2 : 3))) - -#if defined(LUA) -void onTelemetryScriptFileSelectionMenu(const char *result) +inline uint8_t SCREEN_TYPE_COLUMNS(uint8_t screenIndex) { - int screenIndex = TELEMETRY_CURRENT_SCREEN(menuVerticalPosition - HEADER_LINE); + if (TELEMETRY_SCREEN_TYPE(screenIndex) == TELEMETRY_SCREEN_TYPE_SCRIPT) + return 1; + else + return 0; +} + +inline uint8_t SCREEN_LINE_COLUMNS(uint8_t screenIndex, uint8_t lineIndex) +{ + switch (TELEMETRY_SCREEN_TYPE(screenIndex)) { + case TELEMETRY_SCREEN_TYPE_VALUES: + return 1; + case TELEMETRY_SCREEN_TYPE_BARS: + return g_model.screens[screenIndex].bars[lineIndex].source ? 2 : 0; + default: + return HIDDEN_ROW; + } +} + +#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_COLUMNS(x), SCREEN_LINE_COLUMNS(x, 0), SCREEN_LINE_COLUMNS(x, 1), SCREEN_LINE_COLUMNS(x, 2), SCREEN_LINE_COLUMNS(x, 3) + +inline uint8_t DISPLAY_CURRENT_SCREEN(uint8_t line) +{ + if (line < ITEM_DISPLAY_SCREEN_LABEL2) + return 0; + else if (line < ITEM_DISPLAY_SCREEN_LABEL3) + return 1; + else if (line < ITEM_DISPLAY_SCREEN_LABEL4) + return 2; + else + return 3; +} + +#if defined(LUA) +void onTelemetryScriptFileSelectionMenu(const char * result) +{ + int screenIndex = DISPLAY_CURRENT_SCREEN(menuVerticalPosition - HEADER_LINE); if (result == STR_UPDATE_LIST) { if (!sdListFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.screens[screenIndex].script.file), NULL)) { @@ -82,7 +105,6 @@ void onTelemetryScriptFileSelectionMenu(const char *result) } #endif - int skipHiddenLines(int noRows, const uint8_t * mstate_tab, int row) { for(int i=0; i0) { switch (menuHorizontalPosition) { case 0: diff --git a/radio/src/gui/128x64/radio_setup.cpp b/radio/src/gui/128x64/radio_setup.cpp index 6c85607dc..e3fd06bb3 100644 --- a/radio/src/gui/128x64/radio_setup.cpp +++ b/radio/src/gui/128x64/radio_setup.cpp @@ -643,7 +643,6 @@ void menuRadioSetup(event_t event) resumePulses(); waitKeysReleased(); } - MOVE_CURSOR_FROM_HERE(); break; } } diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h index 7013ede4b..b4d7fbae2 100644 --- a/radio/src/gui/212x64/gui.h +++ b/radio/src/gui/212x64/gui.h @@ -280,7 +280,6 @@ void menuChannelsView(event_t event); #endif #define REPEAT_LAST_CURSOR_MOVE() { if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) putEvent(event); else menuHorizontalPosition = 0; } -#define MOVE_CURSOR_FROM_HERE() if (menuHorizontalPosition > 0) REPEAT_LAST_CURSOR_MOVE() #define MENU_FIRST_LINE_EDIT (menuTab ? (MAXCOL((uint16_t)0) >= HIDDEN_ROW ? (MAXCOL((uint16_t)1) >= HIDDEN_ROW ? 2 : 1) : 0) : 0) #define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0) diff --git a/radio/src/gui/212x64/model_display.cpp b/radio/src/gui/212x64/model_display.cpp index 857f9a7de..0e1da16d5 100644 --- a/radio/src/gui/212x64/model_display.cpp +++ b/radio/src/gui/212x64/model_display.cpp @@ -51,21 +51,44 @@ enum MenuModelDisplayItems { #define DISPLAY_COL2 (16*FW) #define DISPLAY_COL3 (28*FW+2) -#if defined(LUA) - #define SCREEN_TYPE_ROWS 1 - #define DISPLAY_LINE_ROWS(x) ((TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE || TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_SCRIPT) ? HIDDEN_ROW : (uint8_t)2) -#else - #define SCREEN_TYPE_ROWS 0 - #define DISPLAY_LINE_ROWS(x) (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE ? HIDDEN_ROW : (uint8_t)2) -#endif -#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, DISPLAY_LINE_ROWS(x), DISPLAY_LINE_ROWS(x), DISPLAY_LINE_ROWS(x), DISPLAY_LINE_ROWS(x) +inline uint8_t SCREEN_TYPE_COLUMNS(uint8_t screenIndex) +{ + if (TELEMETRY_SCREEN_TYPE(screenIndex) == TELEMETRY_SCREEN_TYPE_SCRIPT) + return 1; + else + return 0; +} -#define TELEMETRY_CURRENT_SCREEN(k) (k < ITEM_DISPLAY_SCREEN_LABEL2 ? 0 : (k < ITEM_DISPLAY_SCREEN_LABEL3 ? 1 : (k < ITEM_DISPLAY_SCREEN_LABEL4 ? 2 : 3))) +inline uint8_t SCREEN_LINE_COLUMNS(uint8_t screenIndex, uint8_t lineIndex) +{ + switch (TELEMETRY_SCREEN_TYPE(screenIndex)) { + case TELEMETRY_SCREEN_TYPE_VALUES: + return 2; + case TELEMETRY_SCREEN_TYPE_BARS: + return g_model.screens[screenIndex].bars[lineIndex].source ? 2 : 0; + default: + return HIDDEN_ROW; + } +} + +#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_COLUMNS(x), SCREEN_LINE_COLUMNS(x, 0), SCREEN_LINE_COLUMNS(x, 1), SCREEN_LINE_COLUMNS(x, 2), SCREEN_LINE_COLUMNS(x, 3) + +inline uint8_t DISPLAY_CURRENT_SCREEN(uint8_t line) +{ + if (line < ITEM_DISPLAY_SCREEN_LABEL2) + return 0; + else if (line < ITEM_DISPLAY_SCREEN_LABEL3) + return 1; + else if (line < ITEM_DISPLAY_SCREEN_LABEL4) + return 2; + else + return 3; +} #if defined(LUA) void onTelemetryScriptFileSelectionMenu(const char *result) { - int screenIndex = TELEMETRY_CURRENT_SCREEN(menuVerticalPosition); + int screenIndex = DISPLAY_CURRENT_SCREEN(menuVerticalPosition); if (result == STR_UPDATE_LIST) { if (!sdListFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.screens[screenIndex].script.file), NULL)) { @@ -122,7 +145,7 @@ void menuModelDisplay(event_t event) case ITEM_DISPLAY_SCREEN_LABEL3: case ITEM_DISPLAY_SCREEN_LABEL4: { - uint8_t screenIndex = TELEMETRY_CURRENT_SCREEN(k); + uint8_t screenIndex = DISPLAY_CURRENT_SCREEN(k); drawStringWithIndex(0*FW, y, STR_SCREEN, screenIndex+1); TelemetryScreenType oldScreenType = TELEMETRY_SCREEN_TYPE(screenIndex); TelemetryScreenType newScreenType = (TelemetryScreenType)editChoice(DISPLAY_COL2, y, "", STR_VTELEMSCREENTYPE, oldScreenType, 0, TELEMETRY_SCREEN_TYPE_MAX, (menuHorizontalPosition==0 ? attr : 0), event); @@ -151,9 +174,6 @@ void menuModelDisplay(event_t event) } } } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } #endif break; } @@ -195,7 +215,7 @@ void menuModelDisplay(event_t event) if (IS_BARS_SCREEN(screenIndex)) { FrSkyBarData & bar = g_model.screens[screenIndex].bars[lineIndex]; - drawSource(DISPLAY_COL1, y, bar.source, menuHorizontalPosition==0 ? attr : 0); + drawSource(DISPLAY_COL1, y, bar.source, menuHorizontalPosition == 0 ? attr : 0); int16_t barMax, barMin; LcdFlags lf = LEFT; getMixSrcRange(bar.source, barMin, barMax, &lf); @@ -209,9 +229,6 @@ void menuModelDisplay(event_t event) drawSourceCustomValue(DISPLAY_COL3, y, bar.source, bar.barMax, (menuHorizontalPosition==2 ? attr : 0) | lf); } } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } if (attr && s_editMode>0) { switch (menuHorizontalPosition) { case 0: diff --git a/radio/src/storage/conversions/conversions_216_218.cpp b/radio/src/storage/conversions/conversions_216_218.cpp index ed1590026..6d9012e03 100644 --- a/radio/src/storage/conversions/conversions_216_218.cpp +++ b/radio/src/storage/conversions/conversions_216_218.cpp @@ -1226,7 +1226,7 @@ void convertModelData_217_to_218(ModelData &model) } } } - else if (((oldModel.frsky.screensType >> (2*i)) & 0x03) == TELEMETRY_SCREEN_TYPE_GAUGES) { + else if (((oldModel.frsky.screensType >> (2*i)) & 0x03) == TELEMETRY_SCREEN_TYPE_BARS) { for (int j = 0; j < 4; j++) { newModel.frsky.screens[i].bars[j].source = convertSource_217_to_218(oldModel.frsky.screens[i].bars[j].source); } diff --git a/radio/src/storage/conversions/conversions_218_219.cpp b/radio/src/storage/conversions/conversions_218_219.cpp index f6076917d..2352a7036 100644 --- a/radio/src/storage/conversions/conversions_218_219.cpp +++ b/radio/src/storage/conversions/conversions_218_219.cpp @@ -353,7 +353,7 @@ void convertModelData_218_to_219(ModelData &model) } } } - else if (screenType == TELEMETRY_SCREEN_TYPE_GAUGES) { + else if (screenType == TELEMETRY_SCREEN_TYPE_BARS) { for (int j = 0; j < 4; j++) { newModel.screens[i].bars[j].source = convertSource_218_to_219(oldModel.frsky.screens[i].bars[j].source); } From 4b3a77c538c57edd6f187a762a9c3a0ae3c36b47 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 3 Oct 2019 09:29:42 +0200 Subject: [PATCH 122/257] Add missing modules (#6879) --- companion/src/firmwares/moduledata.cpp | 8 ++++---- companion/src/firmwares/opentx/opentxinterface.cpp | 6 ++++-- companion/src/modeledit/setup.cpp | 5 +---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index 50310c5d0..e09724b48 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -127,12 +127,12 @@ QString ModuleData::protocolToString(unsigned protocol) "FrSky XJT (D16)", "FrSky XJT (D8)", "FrSky XJT (LR12)", "FrSky DJT", "TBS Crossfire", "DIY Multiprotocol Module", - "FrSky PXX R9M", - "FrSky PXX R9M Lite", - "FrSky PXX R9M Lite Pro", + "FrSky R9M", + "FrSky R9M Lite", + "FrSky R9M Lite Pro", "SBUS output at VBat", "FrSky ACCESS ISRM", "FrSky ACCST ISRM D16", - "FrSky ACCESS R9M", + "FrSky ACCESS R9M 2019", "FrSky ACCESS R9M Lite", "FrSky ACCESS R9M Lite Pro", "FrSky XJT lite (D16)", "FrSky XJT lite (D8)", "FrSky XJT lite (LR12)" diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 3ba4f2a7a..d832d77dd 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -797,13 +797,15 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) case PULSES_MULTIMODULE: case PULSES_CROSSFIRE: return true; + case PULSES_ACCESS_R9M: + return IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_HORUS(board) && id.contains("internalaccess")); + case PULSES_PXX_R9M_LITE: case PULSES_ACCESS_R9M_LITE: case PULSES_ACCESS_R9M_LITE_PRO: - return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board)); case PULSES_XJT_LITE_X16: case PULSES_XJT_LITE_D8: case PULSES_XJT_LITE_LR12: - return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board)); + return (IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board)); default: return false; } diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 4b12115fe..7aa27fad2 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -217,10 +217,7 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul // The protocols available on this board for (unsigned int i=0; iisAvailable((PulsesProtocol) i, moduleIdx)) { - if (IS_TARANIS_XLITE(firmware->getBoard()) && i == PULSES_PXX_R9M) //TODO remove when mini are handled as a different module type - ui->protocol->addItem("FrSky R9M Mini", (QVariant) i); - else - ui->protocol->addItem(ModuleData::protocolToString(i), i); + ui->protocol->addItem(ModuleData::protocolToString(i), i); if (i == module.protocol) ui->protocol->setCurrentIndex(ui->protocol->count()-1); } From bba5dbe01433cd8a6b30072cb68bb664b8fb11a2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 3 Oct 2019 09:30:23 +0200 Subject: [PATCH 123/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 6fcbf589e..588d8d6ad 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1581,3 +1581,4 @@ Diego Mendoza Gonzalez Dale Wheeler Nico Wagner James A Davey +Peter Glassey From 13fdb1b791a520122cd9e1e4107978882fa76eea Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 3 Oct 2019 09:37:47 +0200 Subject: [PATCH 124/257] Update credits --- CREDITS.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 6d16a5ca1..9b01442bb 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1558,3 +1558,27 @@ Daniel Dubovski Hans-Georg Böhm Tiberiu Atudorei Alessandro Apostoli (Yaapu!) +Kenneth Bonerigo +Frits van Voorst +Steven Dodge +Christian Buchinger +Patrick Blanc +Darrell Carew +Philippe Faure +Marco Lange +Aaron Tygart +Frantisek Vajbar +Mike Perkins +Knut Einar Kristensen +Georgios Papadopoulos +He Liu +Andrias Thomsen +Alain Azais +Alan Stuart +Fernando Rimoldi +James Snodgrass +Diego Mendoza Gonzalez +Dale Wheeler +Nico Wagner +James A Davey +Peter Glassey \ No newline at end of file From 8bf7350ae71eb414f2636707c6f7d77facab8688 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 3 Oct 2019 10:19:17 +0200 Subject: [PATCH 125/257] Fix eeprom too big issue (#6882) --- companion/src/firmwares/opentx/opentxeeprom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 8e0c408db..ca698adc0 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -1918,7 +1918,7 @@ class SensorField: public TransformedField { if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) { _id = sensor.id; _subid = sensor.subid; - _instance = ((sensor.instance - 1) & 0x1F) | (sensor.rxIdx << 5) | (sensor.moduleIdx << 7); + _instance = sensor.instance == 0 ? 0 : ((sensor.instance - 1) & 0x1F) | (sensor.rxIdx << 5) | (sensor.moduleIdx << 7); _ratio = sensor.ratio; _offset = sensor.offset; } From f562d7a7576c52c67f66988ece687b80a12c7c55 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 3 Oct 2019 18:10:20 +0200 Subject: [PATCH 126/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 588d8d6ad..a38d4590d 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1582,3 +1582,4 @@ Dale Wheeler Nico Wagner James A Davey Peter Glassey +Jeff Dillingham From 1b57c24685dd46f4c240f57c39cd0154f546dfc4 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 3 Oct 2019 18:10:42 +0200 Subject: [PATCH 127/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index a38d4590d..686a9cbeb 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1583,3 +1583,4 @@ Nico Wagner James A Davey Peter Glassey Jeff Dillingham +Don Crowe From 8ef57e2267e3ac3ca707b3fe5c5cb85ae8dd7e6b Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 3 Oct 2019 19:21:11 +0200 Subject: [PATCH 128/257] Fix telemetryBaudrate handling (#6887) This fixes #6886 --- companion/src/firmwares/generalsettings.h | 1 + companion/src/firmwares/opentx/opentxeeprom.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/companion/src/firmwares/generalsettings.h b/companion/src/firmwares/generalsettings.h index 5325119b4..a111cac1e 100644 --- a/companion/src/firmwares/generalsettings.h +++ b/companion/src/firmwares/generalsettings.h @@ -109,6 +109,7 @@ class GeneralSettings { bool adjustRTC; bool optrexDisplay; unsigned int inactivityTimer; + unsigned int telemetryBaudrate; bool minuteBeep; bool preBeep; bool flashBeep; diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index ca698adc0..0fe94ab70 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2607,7 +2607,7 @@ OpenTxGeneralData::OpenTxGeneralData(GeneralSettings & generalData, Board::Type } internalField.Append(new UnsignedField<8>(this, generalData.inactivityTimer)); - internalField.Append(new SpareBitsField<3>(this)); // telemetryBaudrate + internalField.Append(new UnsignedField<3>(this, generalData.telemetryBaudrate)); if (IS_HORUS(board)) internalField.Append(new SpareBitsField<3>(this)); else if (IS_TARANIS(board)) From f1bd371bc5170ee3159c7bf06752e31a0158da7d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 4 Oct 2019 07:53:30 +0200 Subject: [PATCH 129/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 686a9cbeb..d48a30532 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1584,3 +1584,4 @@ James A Davey Peter Glassey Jeff Dillingham Don Crowe +Nicola Claudio Rossi From 2b59541c5c492148ed43f2b912a90066c63c7292 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 4 Oct 2019 07:54:01 +0200 Subject: [PATCH 130/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index d48a30532..f309c9b0c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1585,3 +1585,4 @@ Peter Glassey Jeff Dillingham Don Crowe Nicola Claudio Rossi +Fabien Leroy From 959ea9a9f0b33c5d7a545d0741ba60ae30557a86 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 4 Oct 2019 07:54:15 +0200 Subject: [PATCH 131/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index f309c9b0c..550da74db 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1586,3 +1586,4 @@ Jeff Dillingham Don Crowe Nicola Claudio Rossi Fabien Leroy +Tyler Nelson From d9a035db11db102d831bb0a5d2c17694bd4af556 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 4 Oct 2019 08:39:31 +0200 Subject: [PATCH 132/257] Differentiate between inc/dec and prev/next because of x9d(+) (#6890) * Review virtual event to differentiate between prev/next and inc/dec * Review scripts * Replace VIRTUAL_PREVIOUS by VIRTUAL_PREV --- .../SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua | 2 +- .../horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua | 6 ++-- .../horus/SCRIPTS/TOOLS/FrSky GaSuite.lua | 8 ++--- .../sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua | 6 ++-- .../sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua | 8 ++--- .../SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua | 2 +- .../SCRIPTS/TOOLS/CROSSFIRE/device.lua | 4 +-- .../SCRIPTS/TOOLS/FrSky GaSuite.lua | 8 ++--- .../taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua | 6 ++-- .../taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua | 8 ++--- .../SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua | 2 +- .../SCRIPTS/TOOLS/CROSSFIRE/device.lua | 6 ++-- .../SCRIPTS/TOOLS/FrSky GaSuite.lua | 8 ++--- .../taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua | 6 ++-- .../taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua | 8 ++--- radio/src/lua/api_general.cpp | 31 +++++++++++++------ 16 files changed, 66 insertions(+), 53 deletions(-) diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua index c4d71f1b9..a34621b77 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua @@ -91,7 +91,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT then selectDevice(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectDevice(-1) end diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua index e8d8be6db..50a8c7dde 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/CROSSFIRE/device.lua @@ -455,15 +455,15 @@ local function runDevicePage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT then + if event == EVT_VIRTUAL_INC then incrField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_DEC then incrField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky GaSuite.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky GaSuite.lua index df7fce8ce..8ef4def42 100755 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky GaSuite.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky GaSuite.lua @@ -332,15 +332,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end @@ -500,7 +500,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT_PAGE then selectPage(1) - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + elseif event == EVT_VIRTUAL_PREV_PAGE then killEvents(event); selectPage(-1) end diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua index 1b82bc47f..73d2b88e2 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SBEC.lua @@ -221,15 +221,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua index c49b78f52..6753e18df 100755 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/FrSky SxR.lua @@ -268,15 +268,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end @@ -348,7 +348,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT_PAGE then selectPage(1) - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + elseif event == EVT_VIRTUAL_PREV_PAGE then killEvents(event); selectPage(-1) end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua index f68c4db3d..70c125b69 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua @@ -90,7 +90,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT then selectDevice(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectDevice(-1) end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua index 289df386b..8ccdbf285 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/CROSSFIRE/device.lua @@ -452,13 +452,13 @@ local function runDevicePage(event) elseif edit then if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then incrField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REPT then incrField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky GaSuite.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky GaSuite.lua index df7fce8ce..8ef4def42 100755 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky GaSuite.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky GaSuite.lua @@ -332,15 +332,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end @@ -500,7 +500,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT_PAGE then selectPage(1) - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + elseif event == EVT_VIRTUAL_PREV_PAGE then killEvents(event); selectPage(-1) end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua index 1b82bc47f..73d2b88e2 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SBEC.lua @@ -221,15 +221,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua index c49b78f52..6753e18df 100755 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/FrSky SxR.lua @@ -268,15 +268,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end @@ -348,7 +348,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT_PAGE then selectPage(1) - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + elseif event == EVT_VIRTUAL_PREV_PAGE then killEvents(event); selectPage(-1) end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua index f68c4db3d..70c125b69 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/crossfire.lua @@ -90,7 +90,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT then selectDevice(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectDevice(-1) end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua index 6f733469a..58416af36 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/CROSSFIRE/device.lua @@ -450,15 +450,15 @@ local function runDevicePage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then incrField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then incrField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky GaSuite.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky GaSuite.lua index df7fce8ce..8ef4def42 100755 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky GaSuite.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky GaSuite.lua @@ -332,15 +332,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end @@ -500,7 +500,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT_PAGE then selectPage(1) - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + elseif event == EVT_VIRTUAL_PREV_PAGE then killEvents(event); selectPage(-1) end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua index 1b82bc47f..73d2b88e2 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SBEC.lua @@ -221,15 +221,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua index c49b78f52..6753e18df 100755 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/FrSky SxR.lua @@ -268,15 +268,15 @@ local function runFieldsPage(event) end end elseif edit then - if event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + if event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then addField(1) - elseif event == EVT_VIRTUAL_PREVIOUS or event == EVT_VIRTUAL_PREVIOUS_REPT then + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then addField(-1) end else if event == EVT_VIRTUAL_NEXT then selectField(1) - elseif event == EVT_VIRTUAL_PREVIOUS then + elseif event == EVT_VIRTUAL_PREV then selectField(-1) end end @@ -348,7 +348,7 @@ local function run(event) return 2 elseif event == EVT_VIRTUAL_NEXT_PAGE then selectPage(1) - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then + elseif event == EVT_VIRTUAL_PREV_PAGE then killEvents(event); selectPage(-1) end diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 04b0f814a..93f688d0d 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1677,19 +1677,32 @@ const luaR_value_entry opentxConstants[] = { // Virtual events #if defined(ROTARY_ENCODER_NAVIGATION) - { "EVT_VIRTUAL_PREVIOUS", EVT_ROTARY_LEFT }, - { "EVT_VIRTUAL_PREVIOUS_REPT", EVT_ROTARY_LEFT }, + { "EVT_VIRTUAL_PREV", EVT_ROTARY_LEFT }, { "EVT_VIRTUAL_NEXT", EVT_ROTARY_RIGHT }, - { "EVT_VIRTUAL_NEXT_REPT", EVT_ROTARY_RIGHT }, + { "EVT_VIRTUAL_DEC", EVT_ROTARY_LEFT }, + { "EVT_VIRTUAL_INC", EVT_ROTARY_RIGHT }, +#elif defined(PCBX9D) || defined(PCBX9DP) // key reverted between field nav and value change + { "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_PLUS) }, + { "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_PLUS) }, + { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_MINUS) }, + { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_MINUS) }, + { "EVT_VIRTUAL_DEC", EVT_KEY_FIRST(KEY_MINUS) }, + { "EVT_VIRTUAL_DEC_REPT", EVT_KEY_REPT(KEY_MINUS) }, + { "EVT_VIRTUAL_INC", EVT_KEY_FIRST(KEY_PLUS) }, + { "EVT_VIRTUAL_INC_REPT", EVT_KEY_REPT(KEY_PLUS) }, #else - { "EVT_VIRTUAL_PREVIOUS", EVT_KEY_FIRST(KEY_LEFT) }, - { "EVT_VIRTUAL_PREVIOUS_REPT", EVT_KEY_REPT(KEY_LEFT) }, + { "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_LEFT) }, + { "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_LEFT) }, { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_RIGHT) }, { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_RIGHT) }, + { "EVT_VIRTUAL_DEC", EVT_KEY_FIRST(KEY_LEFT) }, + { "EVT_VIRTUAL_DEC_REPT", EVT_KEY_REPT(KEY_LEFT) }, + { "EVT_VIRTUAL_INC", EVT_KEY_FIRST(KEY_RIGHT) }, + { "EVT_VIRTUAL_INC_REPT", EVT_KEY_REPT(KEY_RIGHT) }, #endif #if defined(NAVIGATION_9X) || defined(NAVIGATION_XLITE) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_UP) }, + { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_UP) }, { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_UP) }, { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_DOWN) }, { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_DOWN) }, @@ -1697,7 +1710,7 @@ const luaR_value_entry opentxConstants[] = { { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, #elif defined(NAVIGATION_X7) || defined(NAVIGATION_X9D) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_PAGE) }, + { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_PAGE) }, { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PAGE) }, { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_MENU) }, { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_MENU) }, @@ -1706,10 +1719,10 @@ const luaR_value_entry opentxConstants[] = { { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, #elif defined(NAVIGATION_HORUS) #if defined(KEYS_GPIO_REG_PGUP) - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_BREAK(KEY_PGUP) }, + { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_BREAK(KEY_PGUP) }, { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PGDN) }, #else - { "EVT_VIRTUAL_PREVIOUS_PAGE", EVT_KEY_LONG(KEY_PGDN) }, + { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_PGDN) }, { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PGDN) }, #endif { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_MODEL) }, From eca62ed13ee3e9ecb5a0a050ea37f3db521cff08 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 4 Oct 2019 08:58:13 +0200 Subject: [PATCH 133/257] Allow setup of new switches on X7 --- radio/src/gui/128x64/model_setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 39ac6fe6f..ab99628b6 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -617,7 +617,7 @@ void menuModelSetup(event_t event) } int current = 0; - for (int i = 0; i < switchWarningsCount; i++) { + for (int i = 0; i < NUM_SWITCHES; i++) { if (SWITCH_WARNING_ALLOWED(i)) { div_t qr = div(current, MAX_SWITCH_PER_LINE); if (!READ_ONLY() && event==EVT_KEY_BREAK(KEY_ENTER) && attr && l_posHorz == current && old_posHorz >= 0) { From 179156f5a4ad1babd3db697c011871867e406d24 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 4 Oct 2019 09:38:23 +0200 Subject: [PATCH 134/257] Increment SD version following virtual event changes --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e60c35532..15d83b917 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(VERSION_REVISION "1") 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 "0021") +set(SDCARD_REVISION "0022") set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION}) cmake_minimum_required(VERSION 2.8) From 1e9d6225d7e84f513924498fc7943254ab798113 Mon Sep 17 00:00:00 2001 From: Kilrah Date: Fri, 4 Oct 2019 10:29:07 +0200 Subject: [PATCH 135/257] Fix inability to flash receivers from .frsk files with external module pins for radios without SPORT connector (#6892) --- radio/src/gui/common/stdlcd/radio_sdmanager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp index 797717314..b57ec798b 100644 --- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp +++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp @@ -385,8 +385,12 @@ void menuRadioSdManager(event_t _event) POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE); if (information.productFamily == FIRMWARE_FAMILY_EXTERNAL_MODULE) POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE); - if (HAS_SPORT_UPDATE_CONNECTOR() && (information.productFamily == FIRMWARE_FAMILY_RECEIVER || information.productFamily == FIRMWARE_FAMILY_SENSOR)) - POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE); + if (information.productFamily == FIRMWARE_FAMILY_RECEIVER || information.productFamily == FIRMWARE_FAMILY_SENSOR) { + if (HAS_SPORT_UPDATE_CONNECTOR()) + POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE); + else + POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_MODULE); + } #if defined(PXX2) if (information.productFamily == FIRMWARE_FAMILY_RECEIVER) POPUP_MENU_ADD_ITEM(STR_FLASH_RECEIVER_OTA); From 268c4d4ecefb691f45ef1604c66828239f383fd2 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 4 Oct 2019 11:48:51 +0200 Subject: [PATCH 136/257] Compile fixes --- radio/src/targets/taranis/intmodule_pulses_driver.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index 8e16f19d7..e71768eac 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "pulses/pulses.h" void intmoduleStop() { From 99f45e47322d218c858eac3e9335d506079a8934 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 5 Oct 2019 14:37:59 +0200 Subject: [PATCH 137/257] Post 2.3.1 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15d83b917..e2178a5f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(OpenTX) set(VERSION_MAJOR "2") set(VERSION_MINOR "3") -set(VERSION_REVISION "1") +set(VERSION_REVISION "2") set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) From 40565c89d746db5e28e4f8bfd32cb276346a9b86 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 5 Oct 2019 22:18:33 +0200 Subject: [PATCH 138/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 550da74db..b9df7886f 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1587,3 +1587,4 @@ Don Crowe Nicola Claudio Rossi Fabien Leroy Tyler Nelson +Stuart Olson From e8a0ab3d356406f03cdf495856c5796b2963b02d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 5 Oct 2019 22:19:02 +0200 Subject: [PATCH 139/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index b9df7886f..e495cd511 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1588,3 +1588,4 @@ Nicola Claudio Rossi Fabien Leroy Tyler Nelson Stuart Olson +Reinhard Plietsch From 7d90497e8445cb2418b131b7b3061a799efe4f37 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 5 Oct 2019 22:19:24 +0200 Subject: [PATCH 140/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index e495cd511..445e0e3b1 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1589,3 +1589,4 @@ Fabien Leroy Tyler Nelson Stuart Olson Reinhard Plietsch +Manuel Spoerri From 7c30d150888b256441bb9483abc5e77e6a684848 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 6 Oct 2019 10:03:20 +0200 Subject: [PATCH 141/257] Improve lua virtual event check script --- radio/util/lua/lua_event_test.lua | 65 +++++++++++++++++++------------ 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/radio/util/lua/lua_event_test.lua b/radio/util/lua/lua_event_test.lua index 588c0fa76..3a883b7cb 100644 --- a/radio/util/lua/lua_event_test.lua +++ b/radio/util/lua/lua_event_test.lua @@ -17,11 +17,13 @@ local toolName = "TNS|LUA event tests|TNE" ---- ######################################################################### local virtual_next = 0 -local virtual_previous = 0 +local virtual_prev = 0 +local virtual_inc = 0 +local virtual_dec = 0 local virtual_next_rept = 0 -local virtual_previous_rept = 0 +local virtual_prev_rept = 0 local virtual_page_next = 0 -local virtual_page_previous = 0 +local virtual_page_prev = 0 local virtual_enter = 0 local virtual_enter_long = 0 local virtual_menu = 0 @@ -37,37 +39,52 @@ local function run(event) if event == nil then error("Cannot be run as a model script!") return 2 - elseif event == EVT_VIRTUAL_EXIT then + end + if event == EVT_VIRTUAL_EXIT then return 2 - elseif event == EVT_VIRTUAL_NEXT then + end + if event == EVT_VIRTUAL_NEXT then virtual_next = virtual_next + 1 - elseif event == EVT_VIRTUAL_PREVIOUS then - virtual_previous = virtual_previous + 1 - elseif event == EVT_VIRTUAL_NEXT_REPT then + end + if event == EVT_VIRTUAL_PREV then + virtual_prev = virtual_prev + 1 + end + if event == EVT_VIRTUAL_INC then + virtual_inc = virtual_inc + 1 + end + if event == EVT_VIRTUAL_DEC then + virtual_dec = virtual_dec + 1 + end + if event == EVT_VIRTUAL_NEXT_REPT then virtual_next_rept = virtual_next_rept + 1 - elseif event == EVT_VIRTUAL_PREVIOUS_REPT then - virtual_previous_rept = virtual_previous_rept + 1 - elseif event == EVT_VIRTUAL_NEXT_PAGE then + end + if event == EVT_VIRTUAL_PREV_REPT then + virtual_prev_rept = virtual_prev_rept + 1 + end + if event == EVT_VIRTUAL_NEXT_PAGE then virtual_page_next = virtual_page_next +1 - elseif event == EVT_VIRTUAL_PREVIOUS_PAGE then - virtual_page_previous = virtual_page_previous + 1 - elseif event == EVT_VIRTUAL_ENTER then + end + if event == EVT_VIRTUAL_PREV_PAGE then + virtual_page_prev = virtual_page_prev + 1 + killEvents(event); + end + if event == EVT_VIRTUAL_ENTER then virtual_enter = virtual_enter + 1 - elseif event == EVT_VIRTUAL_MENU then + end + if event == EVT_VIRTUAL_MENU then virtual_menu = virtual_menu + 1 end - killEvents(event); lcd.clear() lcd.drawScreenTitle("LUA EVENT TEST", 0, 0) - lcd.drawText(1, 10, "NEXT: "..virtual_next) - lcd.drawText(1, 20, "PREVIOUS: "..virtual_previous) - lcd.drawText(1, 40, "NEXT_REPT: "..virtual_next_rept) - lcd.drawText(1, 50, "PREVIOUS_REPT: "..virtual_previous_rept) - lcd.drawText(LCD_W/2, 10, "ENTER: "..virtual_enter) - lcd.drawText(LCD_W/2, 20, "MENU: "..virtual_menu) - lcd.drawText(LCD_W/2, 40, "NEXT_PAGE: "..virtual_page_next) - lcd.drawText(LCD_W/2, 50, "PREVIOUS_PAGE: "..virtual_page_previous) + lcd.drawText(1, 10, "PREV:"..virtual_prev) + lcd.drawText(LCD_W/2, 10, "NEXT: "..virtual_next) + lcd.drawText(1, 20, "DEC:"..virtual_dec) + lcd.drawText(LCD_W/2, 20, "INC:"..virtual_inc) + lcd.drawText(1, 30, "NXT PAGE: "..virtual_page_next) + lcd.drawText(LCD_W/2, 30, "PRV PAGE: "..virtual_page_prev) + lcd.drawText(1, 50, "ENTER: "..virtual_enter) + lcd.drawText(LCD_W/2, 50, "MENU: "..virtual_menu) return 0 end From f78dbafa17f9dd69e10d95cdaa4d87b2a4616393 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 12:40:11 +0200 Subject: [PATCH 142/257] [X9D] P3 fix --- radio/src/dataconstants.h | 5 +++++ radio/src/gui/212x64/view_main.cpp | 12 ++++++++---- radio/src/mixer.cpp | 4 ++-- radio/src/simu.cpp | 11 ++++++----- radio/src/targets/common/arm/stm32/adc_driver.cpp | 4 ++-- radio/src/targets/taranis/board.h | 7 ++++++- radio/src/translations/untranslated.h | 3 +++ 7 files changed, 32 insertions(+), 14 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 2f88ed826..4e21d419b 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -632,8 +632,13 @@ enum MixSources { #elif defined(PCBTARANIS) MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1") MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2") +#if defined(PCBX9D) + MIXSRC_POT3 = MIXSRC_NONE, + MIXSRC_FIRST_SLIDER = MIXSRC_POT2 + 1, +#else MIXSRC_POT3, LUA_EXPORT("s3", "Potentiometer 3") MIXSRC_FIRST_SLIDER, +#endif MIXSRC_SLIDER1 = MIXSRC_FIRST_SLIDER, LUA_EXPORT("ls", "Left slider") MIXSRC_SLIDER2, LUA_EXPORT("rs", "Right slider") MIXSRC_LAST_POT = MIXSRC_SLIDER2, diff --git a/radio/src/gui/212x64/view_main.cpp b/radio/src/gui/212x64/view_main.cpp index 46b56716d..8008507b8 100644 --- a/radio/src/gui/212x64/view_main.cpp +++ b/radio/src/gui/212x64/view_main.cpp @@ -165,19 +165,23 @@ void displayTrims(uint8_t phase) void drawSliders() { - for (uint8_t i=NUM_STICKS; i=SLIDER1 ? LCD_H/2+1 : 1); #endif lcdDrawSolidVerticalLine(x, y, LCD_H/2-2); lcdDrawSolidVerticalLine(x+1, y, LCD_H/2-2); - y += LCD_H/2-4; + y += LCD_H / 2 - 4; y -= ((calibratedAnalogs[i]+RESX)*(LCD_H/2-4)/(RESX*2)); // calculate once per loop lcdDrawSolidVerticalLine(x-1, y, 2); lcdDrawSolidVerticalLine(x+2, y, 2); diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index ee4406201..43c2629ee 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -311,7 +311,7 @@ getvalue_t getValue(mixsrc_t i) } #endif - else if (i <= MIXSRC_LAST_POT+NUM_MOUSE_ANALOGS) { + else if (i <= MIXSRC_LAST_POT + NUM_MOUSE_ANALOGS) { return calibratedAnalogs[i - MIXSRC_Rud]; } @@ -420,7 +420,7 @@ void evalInputs(uint8_t mode) { BeepANACenter anaCenter = 0; - for (uint8_t i=0; i [-1024..1024] uint8_t ch = (i < NUM_STICKS ? CONVERT_MODE(i) : i); int16_t v = anaIn(i); diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index b92e16dab..cfe2516a6 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -113,7 +113,7 @@ OpenTxSim::OpenTxSim(FXApp* a): sliders[i]->setValue(0); } - for(int i=0; isetValue(0); @@ -125,6 +125,7 @@ OpenTxSim::OpenTxSim(FXApp* a): continue; } #endif + knobs[i]->setRange(-1024, 1024); } @@ -152,7 +153,7 @@ OpenTxSim::~OpenTxSim() delete sliders[2]; delete sliders[3]; - for(int i=0; isliders[chan]->getValue(); - else if (chanknobs[chan-NUM_STICKS]->getValue(); + else if (chan < NUM_STICKS + NUM_POTS + NUM_SLIDERS) + return opentxSim->knobs[chan - NUM_STICKS]->getValue(); #if defined(PCBTARANIS) else if (chan == TX_RTC_VOLTAGE) return 800; // 2.34V diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/adc_driver.cpp index 36d0e5a60..c24f4a5c8 100644 --- a/radio/src/targets/common/arm/stm32/adc_driver.cpp +++ b/radio/src/targets/common/arm/stm32/adc_driver.cpp @@ -36,14 +36,14 @@ 9 /*TX_VOLTAGE*/, 10 /*TX_VBAT*/ }; #elif defined(PCBX9DP) const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1, 1}; +#elif defined(PCBX9D) + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1, 1,1, 1, 1}; #elif defined(PCBX7) const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1, 1}; #elif defined(PCBX9LITE) const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1}; #elif defined(PCBXLITE) const int8_t adcDirection[NUM_ANALOGS] = {1,-1,-1,1, -1,1, 1, 1}; -#else - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,0, 1,1, 1, 1}; #endif #if NUM_PWMSTICKS > 0 diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 7c4842d39..28f293de3 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -465,6 +465,11 @@ enum Analogs { SLIDER2, SLIDER3, SLIDER4, +#elif defined(PCBX9D) + POT2, + POT_LAST = POT2, + SLIDER1, + SLIDER2, #else POT2, POT3, @@ -556,7 +561,7 @@ enum CalibratedAnalogs { CALIBRATED_STICK3, CALIBRATED_STICK4, CALIBRATED_POT_FIRST, - CALIBRATED_POT_LAST = CALIBRATED_POT_FIRST + NUM_POTS - 1, + CALIBRATED_POT_LAST = CALIBRATED_POT_FIRST + STORAGE_NUM_POTS - 1, CALIBRATED_SLIDER_FIRST, CALIBRATED_SLIDER_LAST = CALIBRATED_SLIDER_FIRST + NUM_SLIDERS - 1, NUM_CALIBRATED_ANALOGS diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 480717772..810b70eed 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -50,6 +50,9 @@ #elif defined(PCBX9LITE) #define TR_POTS_VSRCRAW "\310S1\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0" +#elif defined(PCBX9D) + #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\311LS\0""\311RS\0" + #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0" #elif defined(PCBTARANIS) #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0" From a08c391f933e60026375c47d468fcc60c4dd9e75 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 14:28:00 +0200 Subject: [PATCH 143/257] [X9D] Different fix --- radio/src/dataconstants.h | 5 ----- radio/src/gui/212x64/view_main.cpp | 2 -- radio/src/gui/common/stdlcd/radio_hardware.cpp | 6 ++++-- radio/src/targets/common/arm/stm32/adc_driver.cpp | 2 +- radio/src/targets/taranis/board.h | 9 ++------- radio/src/translations/untranslated.h | 3 --- 6 files changed, 7 insertions(+), 20 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 4e21d419b..2f88ed826 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -632,13 +632,8 @@ enum MixSources { #elif defined(PCBTARANIS) MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1") MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2") -#if defined(PCBX9D) - MIXSRC_POT3 = MIXSRC_NONE, - MIXSRC_FIRST_SLIDER = MIXSRC_POT2 + 1, -#else MIXSRC_POT3, LUA_EXPORT("s3", "Potentiometer 3") MIXSRC_FIRST_SLIDER, -#endif MIXSRC_SLIDER1 = MIXSRC_FIRST_SLIDER, LUA_EXPORT("ls", "Left slider") MIXSRC_SLIDER2, LUA_EXPORT("rs", "Right slider") MIXSRC_LAST_POT = MIXSRC_SLIDER2, diff --git a/radio/src/gui/212x64/view_main.cpp b/radio/src/gui/212x64/view_main.cpp index 8008507b8..eee71f097 100644 --- a/radio/src/gui/212x64/view_main.cpp +++ b/radio/src/gui/212x64/view_main.cpp @@ -172,10 +172,8 @@ void drawSliders() coord_t x = ((i==SLIDER1 || i==SLIDER3) ? 3 : LCD_W-5); int8_t y = (i=SLIDER1 ? LCD_H/2+1 : 1); #endif diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 4f8156453..6b21a0f0f 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -99,7 +99,7 @@ enum { #if defined(HARDWARE_POT2) ITEM_RADIO_HARDWARE_POT2, #endif -#if defined(HARDWARE_POT3) +#if defined(HARDWARE_POT3) || defined(PCBX9D) // TODO #if defined(STORAGE_POT3) ITEM_RADIO_HARDWARE_POT3, #endif #if defined(HARDWARE_POT4) @@ -194,6 +194,8 @@ enum { #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 #elif (NUM_POTS + NUM_SLIDERS) == 3 #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 +#elif defined(PCBX9D) // TODO defined(STORAGE_POT3) && !defined(STORAGE_POT3) + #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, HIDDEN_ROW, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 #elif (NUM_POTS + NUM_SLIDERS) == 4 #define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 #elif (NUM_POTS + NUM_SLIDERS) == 5 @@ -472,7 +474,7 @@ void menuRadioHardware(event_t event) { int index = k - ITEM_RADIO_HARDWARE_SA; int config = SWITCH_CONFIG(index); - lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, MIXSRC_FIRST_SWITCH-MIXSRC_Rud+index+1, menuHorizontalPosition < 0 ? attr : 0); + lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, MIXSRC_FIRST_SWITCH - MIXSRC_Rud + index + 1, menuHorizontalPosition < 0 ? attr : 0); if (ZEXIST(g_eeGeneral.switchNames[index]) || (attr && s_editMode > 0 && menuHorizontalPosition == 0)) editName(HW_SETTINGS_COLUMN1, y, g_eeGeneral.switchNames[index], LEN_SWITCH_NAME, event, menuHorizontalPosition == 0 ? attr : 0); else diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/adc_driver.cpp index c24f4a5c8..ac4cc4024 100644 --- a/radio/src/targets/common/arm/stm32/adc_driver.cpp +++ b/radio/src/targets/common/arm/stm32/adc_driver.cpp @@ -37,7 +37,7 @@ #elif defined(PCBX9DP) const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1, 1}; #elif defined(PCBX9D) - const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1, 1,1, 1, 1}; + const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1,0, 1,1, 1, 1}; #elif defined(PCBX7) const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1, 1}; #elif defined(PCBX9LITE) diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 28f293de3..eb9ccde57 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -465,11 +465,6 @@ enum Analogs { SLIDER2, SLIDER3, SLIDER4, -#elif defined(PCBX9D) - POT2, - POT_LAST = POT2, - SLIDER1, - SLIDER2, #else POT2, POT3, @@ -503,7 +498,7 @@ enum Analogs { #define STORAGE_NUM_POTS 3 #define STORAGE_NUM_SLIDERS 2 #else - #define NUM_POTS 2 + #define NUM_POTS 3 // TODO X9D has only 2 pots #define NUM_SLIDERS 2 #define STORAGE_NUM_POTS 3 #define STORAGE_NUM_SLIDERS 2 @@ -561,7 +556,7 @@ enum CalibratedAnalogs { CALIBRATED_STICK3, CALIBRATED_STICK4, CALIBRATED_POT_FIRST, - CALIBRATED_POT_LAST = CALIBRATED_POT_FIRST + STORAGE_NUM_POTS - 1, + CALIBRATED_POT_LAST = CALIBRATED_POT_FIRST + NUM_POTS - 1, CALIBRATED_SLIDER_FIRST, CALIBRATED_SLIDER_LAST = CALIBRATED_SLIDER_FIRST + NUM_SLIDERS - 1, NUM_CALIBRATED_ANALOGS diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 810b70eed..480717772 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -50,9 +50,6 @@ #elif defined(PCBX9LITE) #define TR_POTS_VSRCRAW "\310S1\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0" -#elif defined(PCBX9D) - #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\311LS\0""\311RS\0" - #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0" #elif defined(PCBTARANIS) #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0" #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0" From 8718dff3a4d0ba3bd3df15f8098688584e8921f4 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 17:31:06 +0200 Subject: [PATCH 144/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 445e0e3b1..4fc5343e0 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1590,3 +1590,4 @@ Tyler Nelson Stuart Olson Reinhard Plietsch Manuel Spoerri +Paul Pearson From cbbb016a265dd1324ab333a1b2ff64846566dcbd Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 17:31:40 +0200 Subject: [PATCH 145/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 4fc5343e0..ba61c5005 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1591,3 +1591,4 @@ Stuart Olson Reinhard Plietsch Manuel Spoerri Paul Pearson +Thierry Laligand From 00786bfa40ac56b808ce26810f251340e39f554d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 17:32:09 +0200 Subject: [PATCH 146/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index ba61c5005..5d9f96461 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1592,3 +1592,4 @@ Reinhard Plietsch Manuel Spoerri Paul Pearson Thierry Laligand +Bruno Mexique From d3210ac873b69169301e163e4d5fb20b6e16d27f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 17:32:30 +0200 Subject: [PATCH 147/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 5d9f96461..9c220abc0 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1593,3 +1593,4 @@ Manuel Spoerri Paul Pearson Thierry Laligand Bruno Mexique +Uwe Jordt From 570dd0ce9c21553ba9a4a7814c12e111a838877b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 18:24:46 +0200 Subject: [PATCH 148/257] [DE] Translations fixes --- radio/src/translations/de.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 15a8773f9..99d5d4d9c 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -490,7 +490,7 @@ #define TR_ALARM TR(INDENT "Alarme ", INDENT "Aufleuchten bei Alarm") //9XR-Pro #define TR_USRDATA "Daten berechnen aus" #define TR_BLADES TR(INDENT "Prop", INDENT "Prop-Blätter") //9XR-Pro -#define TR_SCREEN "TelmBild " +#define TR_SCREEN "Seite: " #define TR_SOUND_LABEL "Töne" #define TR_LENGTH INDENT "Dauer" #define TR_BEEP_LENGTH INDENT "Beep-Länge" @@ -1148,7 +1148,7 @@ #define TR_MENU_CHANNELS "\320Kanäle" #define TR_MENU_GVARS "\311Glob. Vars" #define TR_MENU_TELEMETRY "\321Telemetrie" -#define TR_MENU_DISPLAY "DISPLAY" +#define TR_MENU_DISPLAY "TELM-SEITEN" #define TR_MENU_OTHER "Weitere" #define TR_MENU_INVERT "Invertieren" #define TR_JITTER_FILTER "ADC Filter" From fe396a85cfb75aace66d8d360624bff6e1c4d186 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 22:22:45 +0200 Subject: [PATCH 149/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 9c220abc0..719f4ed7b 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1594,3 +1594,4 @@ Paul Pearson Thierry Laligand Bruno Mexique Uwe Jordt +Markus Goelzner From 81aa1cb211ae635c9a4308fb3817451e39d2c31b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 7 Oct 2019 22:23:20 +0200 Subject: [PATCH 150/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 719f4ed7b..9d2abef08 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1595,3 +1595,4 @@ Thierry Laligand Bruno Mexique Uwe Jordt Markus Goelzner +Jean-Claude Etiemble From b3a64d3b2c8a098a8c00ad664bb2898a27cb7d5c Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 8 Oct 2019 16:06:55 +0200 Subject: [PATCH 151/257] T16 doesn't have SPORT connector --- radio/src/targets/horus/hal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 18acb1602..0df645d4b 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -304,7 +304,7 @@ // S.Port update connector #define SPORT_MAX_BAUDRATE 250000 // < 400000 -#if defined(PCBX10) +#if defined(PCBX10) && !defined(RADIO_T16) #define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOH #define SPORT_UPDATE_PWR_GPIO GPIOH #define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_13 // PH.13 From 7a9cffb12ae5176f84fec9675ba62b7e42801380 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 9 Oct 2019 09:07:23 +0200 Subject: [PATCH 152/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 9d2abef08..71f28baff 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1596,3 +1596,4 @@ Bruno Mexique Uwe Jordt Markus Goelzner Jean-Claude Etiemble +Wojciech Winiarski From c4759aebae9d06bd31f474ec8553ab441f88fdc9 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 9 Oct 2019 17:47:34 +0200 Subject: [PATCH 153/257] Use vertical axis for field/value changes and horizontal for Nav (#6916) * Use vertical axis for field/value changes and horizontal for Nav * INc with up, NEXT with down --- radio/src/lua/api_general.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index aa0bd28bb..14cc82187 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1695,21 +1695,21 @@ const luaR_value_entry opentxConstants[] = { { "EVT_VIRTUAL_INC", EVT_KEY_FIRST(KEY_PLUS) }, { "EVT_VIRTUAL_INC_REPT", EVT_KEY_REPT(KEY_PLUS) }, #else - { "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_LEFT) }, - { "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_LEFT) }, - { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_RIGHT) }, - { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_RIGHT) }, - { "EVT_VIRTUAL_DEC", EVT_KEY_FIRST(KEY_LEFT) }, - { "EVT_VIRTUAL_DEC_REPT", EVT_KEY_REPT(KEY_LEFT) }, - { "EVT_VIRTUAL_INC", EVT_KEY_FIRST(KEY_RIGHT) }, - { "EVT_VIRTUAL_INC_REPT", EVT_KEY_REPT(KEY_RIGHT) }, + { "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_UP) }, + { "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_UP) }, + { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_DOWN) }, + { "EVT_VIRTUAL_NEXT_REPT", EVT_KEY_REPT(KEY_DOWN) }, + { "EVT_VIRTUAL_DEC", EVT_KEY_FIRST(KEY_DOWN) }, + { "EVT_VIRTUAL_DEC_REPT", EVT_KEY_REPT(KEY_DOWN) }, + { "EVT_VIRTUAL_INC", EVT_KEY_FIRST(KEY_UP) }, + { "EVT_VIRTUAL_INC_REPT", EVT_KEY_REPT(KEY_UP) }, #endif #if defined(NAVIGATION_9X) || defined(NAVIGATION_XLITE) - { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_UP) }, - { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_UP) }, - { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_DOWN) }, - { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_DOWN) }, + { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_LONG(KEY_LEFT) }, + { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_LEFT) }, + { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_RIGHT) }, + { "EVT_VIRTUAL_MENU_LONG", EVT_KEY_LONG(KEY_RIGHT) }, { "EVT_VIRTUAL_ENTER", EVT_KEY_BREAK(KEY_ENTER) }, { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, From 0bc7135e4081106e360e9e0f65125395b83da68b Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 9 Oct 2019 18:22:23 +0200 Subject: [PATCH 154/257] Disable trainer signal based input when trainer signal is lost (#6905) * Disable trainer signal based input when trainer signal is lost * Cosmetics --- radio/src/mixer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 2dd0c535e..655438d4c 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -157,6 +157,8 @@ void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx, int16_t ovwrValue continue; if (ed->flightModes & (1<srcRaw >= MIXSRC_FIRST_TRAINER && ed->srcRaw <= MIXSRC_LAST_TRAINER && !IS_TRAINER_INPUT_VALID()) + continue; if (getSwitch(ed->swtch)) { int32_t v; if (ed->srcRaw == ovwrIdx) { From a6d79494ce34f16ad55439ee4ee33515347da485 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 10 Oct 2019 08:01:10 +0200 Subject: [PATCH 155/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 71f28baff..ce815fc70 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1597,3 +1597,4 @@ Uwe Jordt Markus Goelzner Jean-Claude Etiemble Wojciech Winiarski +Michael Fleming From 200d2f33576e739c27db69ed0ea615647b6f485d Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 11:01:48 +0200 Subject: [PATCH 156/257] X9D 2019 support images too, this fixes #6924 --- companion/src/firmwares/opentx/opentxinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index d7adfb817..995654af2 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -449,7 +449,7 @@ int OpenTxFirmware::getCapability(::Capability capability) else return id.contains("imperial") ? 1 : 0; case ModelImage: - return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || IS_HORUS(board)); + return (board == BOARD_TARANIS_X9D || IS_TARANIS_PLUS(board) || board == BOARD_TARANIS_X9DP_2019 || IS_HORUS(board)); case HasBeeper: return (!IS_ARM(board)); case HasPxxCountry: From aee77ed9e9b33229c77c346c86abd9e1c24ea7b4 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 10 Oct 2019 14:03:49 +0200 Subject: [PATCH 157/257] Navigation code shared and improved (#6923) --- radio/src/gui/212x64/gui.h | 2 -- radio/src/gui/480x272/menus.h | 2 -- radio/src/gui/gui_common.h | 15 +++++++++++++++ radio/src/gui/navigation/navigation_horus.cpp | 10 +++++----- radio/src/gui/navigation/navigation_x7.cpp | 9 ++++----- radio/src/gui/navigation/navigation_x9d.cpp | 8 ++++---- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h index b4d7fbae2..3883a2e86 100644 --- a/radio/src/gui/212x64/gui.h +++ b/radio/src/gui/212x64/gui.h @@ -280,8 +280,6 @@ void menuChannelsView(event_t event); #endif #define REPEAT_LAST_CURSOR_MOVE() { if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) putEvent(event); else menuHorizontalPosition = 0; } - -#define MENU_FIRST_LINE_EDIT (menuTab ? (MAXCOL((uint16_t)0) >= HIDDEN_ROW ? (MAXCOL((uint16_t)1) >= HIDDEN_ROW ? 2 : 1) : 0) : 0) #define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0) #define EDIT_MODE_INIT 0 // TODO enum diff --git a/radio/src/gui/480x272/menus.h b/radio/src/gui/480x272/menus.h index afe790f3f..2145c067b 100644 --- a/radio/src/gui/480x272/menus.h +++ b/radio/src/gui/480x272/menus.h @@ -605,8 +605,6 @@ void readModelNotes(); #define CURSOR_MOVED_LEFT(event) (event==EVT_ROTARY_LEFT || EVT_KEY_MASK(event) == KEY_LEFT) #define CURSOR_MOVED_RIGHT(event) (event==EVT_ROTARY_RIGHT || EVT_KEY_MASK(event) == KEY_RIGHT) #define REPEAT_LAST_CURSOR_MOVE(last, refresh) { if (CURSOR_MOVED_RIGHT(event)) menuHorizontalPosition = (menuHorizontalPosition >= (last) ? 0 : menuHorizontalPosition + 1); else menuHorizontalPosition = (menuHorizontalPosition <= (0) ? last : menuHorizontalPosition - 1); if (refresh) putEvent(EVT_REFRESH); } - -#define MENU_FIRST_LINE_EDIT (MAXCOL((uint16_t)0) >= HIDDEN_ROW ? (MAXCOL((uint16_t)1) >= HIDDEN_ROW ? 2 : 1) : 0) #define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0) #define EDIT_MODE_INIT 0 // TODO enum diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 7239aaaec..2654584ce 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -38,6 +38,21 @@ #define CASE_EVT_ROTARY_RIGHT #endif +#if defined(NAVIGATION_X7) || defined(NAVIGATION_X9D) || defined(NAVIGATION_HORUS) +inline uint8_t MENU_FIRST_LINE_EDIT(const uint8_t * horTab, uint8_t horTabMax) +{ + if (horTab) { + uint8_t result = 0; + while (result < horTabMax && horTab[result] >= HIDDEN_ROW) + ++result; + return result; + } + else { + return 0; + } +} +#endif + typedef bool (*IsValueAvailable)(int); int circularIncDec(int current, int inc, int min, int max, IsValueAvailable isValueAvailable=nullptr); diff --git a/radio/src/gui/navigation/navigation_horus.cpp b/radio/src/gui/navigation/navigation_horus.cpp index 494f1ee49..b8729c8a3 100644 --- a/radio/src/gui/navigation/navigation_horus.cpp +++ b/radio/src/gui/navigation/navigation_horus.cpp @@ -353,7 +353,7 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t switch (event) { case EVT_ENTRY: s_editMode = EDIT_MODE_INIT; - menuVerticalPosition = MENU_FIRST_LINE_EDIT; + menuVerticalPosition = MENU_FIRST_LINE_EDIT(horTab, horTabMax); menuHorizontalPosition = POS_HORZ_INIT(menuVerticalPosition); break; @@ -390,7 +390,7 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t AUDIO_KEY_PRESS(); } else { - uint8_t posVertInit = MENU_FIRST_LINE_EDIT; + uint8_t posVertInit = MENU_FIRST_LINE_EDIT(horTab, horTabMax); if (menuVerticalOffset != 0 || menuVerticalPosition != posVertInit) { menuVerticalOffset = 0; menuVerticalPosition = posVertInit; @@ -435,7 +435,7 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t break; } do { - INC(menuVerticalPosition, MENU_FIRST_LINE_EDIT, rowcount-1); + INC(menuVerticalPosition, MENU_FIRST_LINE_EDIT(horTab, horTabMax), rowcount-1); } while (CURSOR_NOT_ALLOWED_IN_ROW(menuVerticalPosition)); menuHorizontalPosition = POS_HORZ_INIT(menuVerticalPosition); break; @@ -454,7 +454,7 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t break; } do { - DEC(menuVerticalPosition, MENU_FIRST_LINE_EDIT, rowcount-1); + DEC(menuVerticalPosition, MENU_FIRST_LINE_EDIT(horTab, horTabMax), rowcount-1); } while (CURSOR_NOT_ALLOWED_IN_ROW(menuVerticalPosition)); if (COLATTR(menuVerticalPosition) & NAVIGATION_LINE_BY_LINE) menuHorizontalPosition = -1; @@ -465,7 +465,7 @@ bool check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t linesCount = rowcount; - if (menuVerticalPosition <= MENU_FIRST_LINE_EDIT) { + if (menuVerticalPosition <= MENU_FIRST_LINE_EDIT(horTab, horTabMax)) { menuVerticalOffset = 0; if (horTab) { linesCount = 0; diff --git a/radio/src/gui/navigation/navigation_x7.cpp b/radio/src/gui/navigation/navigation_x7.cpp index d4b2b1f1b..bc835a375 100644 --- a/radio/src/gui/navigation/navigation_x7.cpp +++ b/radio/src/gui/navigation/navigation_x7.cpp @@ -205,7 +205,6 @@ tmr10ms_t menuEntryTime; #define MAXCOL_RAW(row) (horTab ? *(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) #define MAXCOL(row) (MAXCOL_RAW(row) >= HIDDEN_ROW ? MAXCOL_RAW(row) : (const uint8_t)(MAXCOL_RAW(row) & (~NAVIGATION_LINE_BY_LINE))) #define COLATTR(row) (MAXCOL_RAW(row) == (uint8_t)-1 ? (const uint8_t)0 : (const uint8_t)(MAXCOL_RAW(row) & NAVIGATION_LINE_BY_LINE)) -#define MENU_FIRST_LINE_EDIT (menuTab ? (MAXCOL((uint16_t)0) >= HIDDEN_ROW ? (MAXCOL((uint16_t)1) >= HIDDEN_ROW ? 2 : 1) : 0) : 0) #define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0) void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t menuTabSize, const uint8_t * horTab, uint8_t horTabMax, vertpos_t rowcount) @@ -251,7 +250,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t case EVT_ENTRY: menuEntryTime = get_tmr10ms(); s_editMode = EDIT_MODE_INIT; - l_posVert = MENU_FIRST_LINE_EDIT; + l_posVert = MENU_FIRST_LINE_EDIT(horTab, horTabMax); l_posHorz = POS_HORZ_INIT(l_posVert); break; @@ -291,7 +290,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t AUDIO_KEY_PRESS(); } else { - uint8_t posVertInit = MENU_FIRST_LINE_EDIT; + uint8_t posVertInit = MENU_FIRST_LINE_EDIT(horTab, horTabMax); if (menuVerticalOffset != 0 || l_posVert != posVertInit) { menuVerticalOffset = 0; l_posVert = posVertInit; @@ -327,7 +326,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t } do { - INC(l_posVert, MENU_FIRST_LINE_EDIT, rowcount-1); + INC(l_posVert, MENU_FIRST_LINE_EDIT(horTab, horTabMax), rowcount-1); } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); s_editMode = 0; // if we go down, we must be in this mode @@ -356,7 +355,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t } do { - DEC(l_posVert, MENU_FIRST_LINE_EDIT, rowcount-1); + DEC(l_posVert, MENU_FIRST_LINE_EDIT(horTab, horTabMax), rowcount-1); } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); s_editMode = 0; // if we go up, we must be in this mode diff --git a/radio/src/gui/navigation/navigation_x9d.cpp b/radio/src/gui/navigation/navigation_x9d.cpp index 0018ad063..911455211 100644 --- a/radio/src/gui/navigation/navigation_x9d.cpp +++ b/radio/src/gui/navigation/navigation_x9d.cpp @@ -360,7 +360,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t case EVT_ENTRY: menuEntryTime = get_tmr10ms(); s_editMode = EDIT_MODE_INIT; - l_posVert = MENU_FIRST_LINE_EDIT; + l_posVert = MENU_FIRST_LINE_EDIT(horTab, horTabMax); l_posHorz = POS_HORZ_INIT(l_posVert); SET_SCROLLBAR_X(LCD_W-1); break; @@ -402,7 +402,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t AUDIO_KEY_PRESS(); } else { - uint8_t posVertInit = MENU_FIRST_LINE_EDIT; + uint8_t posVertInit = MENU_FIRST_LINE_EDIT(horTab, horTabMax); if (menuVerticalOffset != 0 || l_posVert != posVertInit) { menuVerticalOffset = 0; l_posVert = posVertInit; @@ -438,7 +438,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t } do { - INC(l_posVert, MENU_FIRST_LINE_EDIT, rowcount-1); + INC(l_posVert, MENU_FIRST_LINE_EDIT(horTab, horTabMax), rowcount-1); } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); s_editMode = 0; // if we go down, we must be in this mode @@ -467,7 +467,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t } do { - DEC(l_posVert, MENU_FIRST_LINE_EDIT, rowcount-1); + DEC(l_posVert, MENU_FIRST_LINE_EDIT(horTab, horTabMax), rowcount-1); } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); s_editMode = 0; // if we go up, we must be in this mode From 39189a1652368d81f6c496779f804588371be7c0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 15:11:57 +0200 Subject: [PATCH 158/257] Fix debug compile --- radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt index 64cd31c76..946c638b2 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -121,7 +121,6 @@ else() ${BOOTLOADER_SRC} ../../../../../${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c ../../../../../serial.cpp - ../aux_serial_driver.cpp ) endif() endif() From c3db736e33156be698f3856894b93c3ca240e899 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 15:27:48 +0200 Subject: [PATCH 159/257] Companion internal module rework (#6925) Companion internal module rework --- companion/src/firmwares/boards.h | 6 ++++++ companion/src/firmwares/opentx/opentxinterface.cpp | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index b7af393b6..845f181e8 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -319,4 +319,10 @@ inline bool HAS_EXTERNAL_ANTENNA(Board::Type board) return (board == Board::BOARD_X10 || board == Board::BOARD_HORUS_X12S || (IS_TARANIS_XLITE(board) && !IS_TARANIS_XLITES(board))); } +inline bool IS_ACCESS_RADIO(Board::Type board, QString &id) +{ + return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == Board::BOARD_TARANIS_X9DP_2019 || board == Board::BOARD_X10_EXPRESS || + (IS_HORUS(board) && id.contains("internalaccess")); +} + #endif // _BOARDS_H_ diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 995654af2..16ce23b07 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -772,14 +772,14 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) return true; case PULSES_PXX_XJT_X16: case PULSES_PXX_XJT_LR12: - return !(IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_T16(board)); + return !IS_ACCESS_RADIO(board, id); case PULSES_PXX_XJT_D8: - return !(IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || IS_JUMPER_T16(board) || id.contains("eu")); + return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")); case PULSES_PPM: return id.contains("internalppm"); case PULSES_ACCESS_ISRM: case PULSES_ACCST_ISRM_D16: - return IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == BOARD_TARANIS_X9DP_2019 || board == BOARD_X10_EXPRESS || (IS_HORUS(board) && id.contains("internalaccess")); + return IS_ACCESS_RADIO(board, id); case PULSES_MULTIMODULE: return id.contains("internalmulti"); default: From 54bb04f049986e7f82867dafea75acbff3cf3dec Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 10 Oct 2019 15:29:39 +0200 Subject: [PATCH 160/257] New multi protocols (#6920) * New Multi protocols Scanner FrSkyX RX Flyskys AFHDS2A RX * Skip Multi/Scanner protocol * added new protocols in companion --- companion/src/firmwares/moduledata.h | 5 ++++- companion/src/firmwares/multiprotocols.cpp | 4 +++- companion/src/modeledit/setup.cpp | 9 ++++++--- radio/src/gui/128x64/model_setup.cpp | 2 +- radio/src/gui/212x64/model_setup.cpp | 2 +- radio/src/gui/480x272/model_setup.cpp | 2 +- radio/src/gui/gui_common.cpp | 2 ++ radio/src/gui/gui_common.h | 6 ++++++ radio/src/pulses/modules_constants.h | 5 ++++- radio/src/translations/untranslated.h | 2 +- 10 files changed, 29 insertions(+), 10 deletions(-) diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index 5d86c2876..4e05e2120 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -114,7 +114,10 @@ enum MultiModuleRFProtocols { MODULE_SUBTYPE_MULTI_POTENSIC, MODULE_SUBTYPE_MULTI_ZSX, MODULE_SUBTYPE_MULTI_FLYZONE, - MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_FLYZONE + MODULE_SUBTYPE_MULTI_SCANNER, + MODULE_SUBTYPE_MULTI_FRSKYX_RX, + MODULE_SUBTYPE_MULTI_AFHDS2A_RX, + MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_AFHDS2A_RX }; enum TrainerProtocol { diff --git a/companion/src/firmwares/multiprotocols.cpp b/companion/src/firmwares/multiprotocols.cpp index 4ad8ba68a..73f9ea69f 100644 --- a/companion/src/firmwares/multiprotocols.cpp +++ b/companion/src/firmwares/multiprotocols.cpp @@ -71,6 +71,7 @@ static const QStringList STR_SUBTYPE_REDPINE {"Fast", "Slow"}; static const QStringList STR_SUBTYPE_POTENSIC {"A20 Firefly"}; static const QStringList STR_SUBTYPE_ZSX {"JJRC ZSX-280"}; static const QStringList STR_SUBTYPE_FLYZONE {"FZ-410 TX"}; +static const QStringList STR_SUBTYPE_FRSKYX_RX {"D16 FCC", "D16 LBT"}; static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT}; @@ -116,6 +117,7 @@ const Multiprotocols multiProtocols { {MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr}, {MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr}, {MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr}, + {MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE}, {MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION}, // Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff) @@ -158,7 +160,7 @@ QString Multiprotocols::protocolToString(int protocol, bool custom) "Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "J6 PRO","FQ777","Assan","Hontai","Open LRS", "FlySky AFHDS2A", "Q2x2", "Walkera", "Q303", "GW008", "DM002", "Cabell", "ESky 150", "H8 3D", "Corona", "CFlie", "Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761", - "KFPlan KF606", "Redpine", "Potensic", "ZXS", "FlyZone" + "KFPlan KF606", "Redpine", "Potensic", "ZXS", "FlyZone", "Scanner", "FrSky RX", "FlySky AFHDS2A RX" }); if (protocol == MM_RF_CUSTOM_SELECTED || custom) diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 7aa27fad2..e0fbbf606 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -223,6 +223,8 @@ ModulePanel::ModulePanel(QWidget * parent, ModelData & model, ModuleData & modul } } for (int i=0; i<=MODULE_SUBTYPE_MULTI_LAST; i++) { + if (i == MODULE_SUBTYPE_MULTI_SCANNER) + continue; ui->multiProtocol->addItem(Multiprotocols::protocolToString(i), i); } @@ -543,7 +545,7 @@ void ModulePanel::update() ui->lowPower->setVisible(mask & MASK_MULTIMODULE); if (mask & MASK_MULTIMODULE) { - ui->multiProtocol->setCurrentIndex(module.multi.rfProtocol); + ui->multiProtocol->setCurrentIndex(ui->multiProtocol->findData(module.multi.rfProtocol)); ui->autoBind->setChecked(module.multi.autoBindMode); ui->lowPower->setChecked(module.multi.lowPowerMode); } @@ -714,9 +716,10 @@ void ModulePanel::on_failsafeMode_currentIndexChanged(int value) void ModulePanel::onMultiProtocolChanged(int index) { - if (!lock && module.multi.rfProtocol != (unsigned)index) { + int rfProtocol = ui->multiProtocol->itemData(index).toInt(); + if (!lock && module.multi.rfProtocol != (unsigned)rfProtocol) { lock=true; - module.multi.rfProtocol = (unsigned int) index; + module.multi.rfProtocol = (unsigned int)rfProtocol; unsigned int maxSubTypes = multiProtocols.getProtocol(index).numSubTypes(); if (module.multi.customProto) maxSubTypes=8; diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index fbfd8ed53..4abf89a28 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -886,7 +886,7 @@ void menuModelSetup(event_t event) #if defined(MULTIMODULE) else if (isModuleMultimodule(EXTERNAL_MODULE)) { int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].multi.customProto == 1 ? MODULE_SUBTYPE_MULTI_CUSTOM : g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false); - CHECK_INCDEC_MODELVAR(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST); + CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST, isMultiProtocolSelectable); if (checkIncDec_Ret) { g_model.moduleData[EXTERNAL_MODULE].multi.customProto = (multiRfProto == MODULE_SUBTYPE_MULTI_CUSTOM); if (!g_model.moduleData[EXTERNAL_MODULE].multi.customProto) diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 749d54221..c137c9d29 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -856,7 +856,7 @@ void menuModelSetup(event_t event) #if defined(MULTIMODULE) else if (isModuleMultimodule(EXTERNAL_MODULE)) { int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].multi.customProto == 1 ? MODULE_SUBTYPE_MULTI_CUSTOM : g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false); - CHECK_INCDEC_MODELVAR(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST); + CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST, isMultiProtocolSelectable); if (checkIncDec_Ret) { g_model.moduleData[EXTERNAL_MODULE].multi.customProto = (multiRfProto == MODULE_SUBTYPE_MULTI_CUSTOM); if (!g_model.moduleData[EXTERNAL_MODULE].multi.customProto) diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index c49f8fab1..078f15d40 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -1082,7 +1082,7 @@ bool menuModelSetup(event_t event) #if defined(MULTIMODULE) else if (isModuleMultimodule(moduleIdx)) { int multiRfProto = g_model.moduleData[moduleIdx].multi.customProto == 1 ? MODULE_SUBTYPE_MULTI_CUSTOM : g_model.moduleData[moduleIdx].getMultiProtocol(false); - CHECK_INCDEC_MODELVAR(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST); + CHECK_INCDEC_MODELVAR_CHECK(event, multiRfProto, MODULE_SUBTYPE_MULTI_FIRST, MODULE_SUBTYPE_MULTI_LAST, isMultiProtocolSelectable); if (checkIncDec_Ret) { g_model.moduleData[moduleIdx].multi.customProto = (multiRfProto == MODULE_SUBTYPE_MULTI_CUSTOM); if (!g_model.moduleData[moduleIdx].multi.customProto) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index a2f9b4090..daee811e6 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -827,6 +827,7 @@ const char STR_SUBTYPE_REDPINE[] = "\004""Fast""Slow"; const char STR_SUBTYPE_POTENSIC[] = "\003""A20"; const char STR_SUBTYPE_ZSX[] = "\007""280JJRC"; const char STR_SUBTYPE_FLYZONE[] = "\005""FZ410"; +const char STR_SUBTYPE_FRSKYX_RX[] = "\003""FCC""LBT"; const mm_protocol_definition multi_protocols[] = { @@ -868,6 +869,7 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_POTENSIC, 0, false, STR_SUBTYPE_POTENSIC, nullptr}, {MODULE_SUBTYPE_MULTI_ZSX, 0, false, STR_SUBTYPE_ZSX, nullptr}, {MODULE_SUBTYPE_MULTI_FLYZONE, 0, false, STR_SUBTYPE_FLYZONE, nullptr}, + {MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE}, {MM_RF_CUSTOM_SELECTED, 7, true, NO_SUBTYPE, STR_MULTI_OPTION}, // Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff) diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 2654584ce..43dc8df80 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -174,6 +174,12 @@ const mm_protocol_definition *getMultiProtocolDefinition (uint8_t protocol); #define MULTIMODULE_STATUS_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, (isModuleMultimodule(moduleIdx) && getMultiSyncStatus(moduleIdx).isValid()) ? TITLE_ROW : HIDDEN_ROW, #define MULTIMODULE_MODULE_ROWS(moduleIdx) isModuleMultimodule(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, #define MULTIMODULE_MODE_ROWS(moduleIdx) (g_model.moduleData[moduleIdx].multi.customProto) ? (uint8_t) 3 :MULTIMODULE_HAS_SUBTYPE(g_model.moduleData[moduleIdx].getMultiProtocol(true)) ? (uint8_t)2 : (uint8_t)1 + +inline bool isMultiProtocolSelectable(int protocol) +{ + return protocol != MODULE_SUBTYPE_MULTI_SCANNER; +} + inline bool MULTIMODULE_HAS_SUBTYPE(uint8_t moduleIdx) { return getMultiProtocolDefinition(moduleIdx)->maxSubtype > 0; diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h index 948ee60df..34c1c2fb8 100644 --- a/radio/src/pulses/modules_constants.h +++ b/radio/src/pulses/modules_constants.h @@ -153,7 +153,10 @@ enum ModuleSubtypeMulti { MODULE_SUBTYPE_MULTI_POTENSIC, MODULE_SUBTYPE_MULTI_ZSX, MODULE_SUBTYPE_MULTI_FLYZONE, - MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_FLYZONE + MODULE_SUBTYPE_MULTI_SCANNER, + MODULE_SUBTYPE_MULTI_FRSKYX_RX, + MODULE_SUBTYPE_MULTI_AFHDS2A_RX, + MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_AFHDS2A_RX }; enum MMDSM2Subtypes { diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 5943fcda3..dc72f9f58 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -127,4 +127,4 @@ #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 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FSky 2A""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 ""FlyZone" +#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 ""SFHSS\0 ""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FSky 2A""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 ""FlyZone""Scanner""FrSkyRX""FS2A_RX" From a5e7279c57184fc7329e2a623e28ef3e9a326c5e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 10 Oct 2019 15:33:48 +0200 Subject: [PATCH 161/257] Fixed module data type export (#6919) Fixed module data type export --- .../src/firmwares/opentx/opentxeeprom.cpp | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 0fe94ab70..9e95b63b5 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2052,7 +2052,6 @@ class ModuleUnionField: public UnionField { void beforeExport() override { - module.rfProtocol = module.multi.rfProtocol & 0xf; rfProtExtra = (module.multi.rfProtocol >> 4) & 0x03; } @@ -2091,13 +2090,6 @@ class ModuleUnionField: public UnionField { attr==PULSES_PXX_R9M_LITE; } - void beforeExport() override - { - if (module.protocol >= PULSES_PXX_XJT_X16 && module.protocol <= PULSES_PXX_XJT_LR12) { - module.subType = module.protocol - PULSES_PXX_XJT_X16; - } - } - void afterImport() override { if (module.protocol == PULSES_PXX_XJT_X16) { @@ -2136,9 +2128,6 @@ class ModuleUnionField: public UnionField { void beforeExport() override { - if (module.protocol == PULSES_ACCST_ISRM_D16 || module.protocol == PULSES_ACCESS_ISRM) { - module.subType = module.protocol - PULSES_ACCESS_ISRM; - } for (int i=0; i= PULSES_LP45 && module.protocol <= PULSES_DSMX) { module.rfProtocol = module.protocol - PULSES_LP45; } + else if (module.protocol == PULSES_ACCST_ISRM_D16 || module.protocol == PULSES_ACCESS_ISRM) { + module.subType = module.protocol - PULSES_ACCESS_ISRM; + } + else if (module.protocol >= PULSES_PXX_XJT_X16 && module.protocol <= PULSES_PXX_XJT_LR12) { + module.subType = module.protocol - PULSES_PXX_XJT_X16; + } + else if (module.protocol == PULSES_MULTIMODULE) { + module.rfProtocol = module.multi.rfProtocol & 0xf; + } } void afterImport() override From 7094a744d65320eca75549f6bc314b4a4e3b28eb Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 15:37:17 +0200 Subject: [PATCH 162/257] Turn off external module while changing type (#6902) Turn off ext module while changing types --- radio/src/gui/128x64/model_setup.cpp | 29 +++++++++--------- radio/src/gui/212x64/model_setup.cpp | 27 +++++++++-------- radio/src/gui/480x272/model_setup.cpp | 42 +++++++++++++++++---------- radio/src/opentx.h | 2 ++ 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 4abf89a28..4587bcded 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -369,6 +369,8 @@ void menuModelSetup(event_t event) if (event == EVT_ENTRY || event == EVT_ENTRY_UP) { memclear(&reusableBuffer.moduleSetup, sizeof(reusableBuffer.moduleSetup)); reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power; + reusableBuffer.moduleSetup.previousType = g_model.moduleData[EXTERNAL_MODULE].type; + reusableBuffer.moduleSetup.newType = g_model.moduleData[EXTERNAL_MODULE].type; #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode; #endif @@ -828,7 +830,7 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE: lcdDrawTextAlignedLeft(y, INDENT TR_MODE); - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, reusableBuffer.moduleSetup.newType, menuHorizontalPosition==0 ? attr : 0); if (isModuleXJT(EXTERNAL_MODULE)) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_XJT_ACCST_RF_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==1 ? attr : 0); else if (isModuleDSM2(EXTERNAL_MODULE)) @@ -846,24 +848,25 @@ void menuModelSetup(event_t event) #endif #if defined(PCBTARANIS) if (attr && menuHorizontalPosition == 0) { - if (s_editMode > 0) - EXTERNAL_MODULE_OFF(); - else - if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) - EXTERNAL_MODULE_ON(); + if (s_editMode > 0) { + g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_NONE; + } + else if (reusableBuffer.moduleSetup.newType != reusableBuffer.moduleSetup.previousType) { + g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; + reusableBuffer.moduleSetup.previousType = reusableBuffer.moduleSetup.newType; + setModuleType(EXTERNAL_MODULE, g_model.moduleData[EXTERNAL_MODULE].type); + } + else if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE) { + g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; + } } #endif if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { case 0: - { - uint8_t moduleType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, isExternalModuleAvailable); - if (checkIncDec_Ret) { - setModuleType(EXTERNAL_MODULE, moduleType); - } - } - break; + reusableBuffer.moduleSetup.newType = checkIncDec(event, reusableBuffer.moduleSetup.newType, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, isExternalModuleAvailable); + break; case 1: if (isModuleDSM2(EXTERNAL_MODULE)) { diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index c137c9d29..9fd9183b8 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -385,6 +385,8 @@ void menuModelSetup(event_t event) if (event == EVT_ENTRY || event == EVT_ENTRY_UP) { memclear(&reusableBuffer.moduleSetup, sizeof(reusableBuffer.moduleSetup)); reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power; + reusableBuffer.moduleSetup.previousType = g_model.moduleData[EXTERNAL_MODULE].type; + reusableBuffer.moduleSetup.newType = g_model.moduleData[EXTERNAL_MODULE].type; } #if (defined(DSM2) || defined(PXX)) @@ -804,7 +806,7 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE: lcdDrawTextAlignedLeft(y, INDENT TR_MODE); - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, reusableBuffer.moduleSetup.newType, menuHorizontalPosition==0 ? attr : 0); if (isModuleXJT(EXTERNAL_MODULE)) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_XJT_ACCST_RF_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].subType, menuHorizontalPosition==1 ? attr : 0); else if (isModuleDSM2(EXTERNAL_MODULE)) @@ -831,23 +833,24 @@ void menuModelSetup(event_t event) } #endif if (attr && menuHorizontalPosition == 0) { - if (s_editMode > 0) - EXTERNAL_MODULE_OFF(); - else - if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) - EXTERNAL_MODULE_ON(); + if (s_editMode > 0) { + g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_NONE; + } + else if (reusableBuffer.moduleSetup.newType != reusableBuffer.moduleSetup.previousType) { + g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; + reusableBuffer.moduleSetup.previousType = reusableBuffer.moduleSetup.newType; + setModuleType(EXTERNAL_MODULE, g_model.moduleData[EXTERNAL_MODULE].type); + } + else if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE) { + g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; + } } if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { case 0: - { - uint8_t moduleType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, isExternalModuleAvailable); - if (checkIncDec_Ret) { - setModuleType(EXTERNAL_MODULE, moduleType); - } + reusableBuffer.moduleSetup.newType = checkIncDec(event, reusableBuffer.moduleSetup.newType, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, isExternalModuleAvailable); break; - } case 1: if (isModuleDSM2(EXTERNAL_MODULE)) { diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 078f15d40..7f78ec5a2 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -618,6 +618,8 @@ bool menuModelSetup(event_t event) if (event == EVT_ENTRY || event == EVT_ENTRY_UP) { memclear(&reusableBuffer.moduleSetup, sizeof(reusableBuffer.moduleSetup)); reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power; + reusableBuffer.moduleSetup.previousType = g_model.moduleData[EXTERNAL_MODULE].type; + reusableBuffer.moduleSetup.newType = g_model.moduleData[EXTERNAL_MODULE].type; #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) reusableBuffer.moduleSetup.antennaMode = g_model.moduleData[INTERNAL_MODULE].pxx.antennaMode; #endif @@ -1030,7 +1032,7 @@ bool menuModelSetup(event_t event) #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE: lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_MODE); - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, g_model.moduleData[moduleIdx].type, menuHorizontalPosition==0 ? attr : 0); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, moduleIdx == EXTERNAL_MODULE ? reusableBuffer.moduleSetup.newType : g_model.moduleData[INTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); if (isModuleXJT(moduleIdx)) lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_XJT_ACCST_RF_PROTOCOLS, 1+g_model.moduleData[moduleIdx].subType, (menuHorizontalPosition==1 ? attr : 0)); else if (isModuleDSM2(moduleIdx)) @@ -1054,28 +1056,36 @@ bool menuModelSetup(event_t event) } #endif if (attr && menuHorizontalPosition == 0 && moduleIdx == EXTERNAL_MODULE) { - if (s_editMode > 0) - EXTERNAL_MODULE_OFF(); - else - if(g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE) - EXTERNAL_MODULE_ON(); + if (s_editMode > 0) { + g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_NONE; + } + else if (reusableBuffer.moduleSetup.newType != reusableBuffer.moduleSetup.previousType) { + g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; + reusableBuffer.moduleSetup.previousType = reusableBuffer.moduleSetup.newType; + setModuleType(EXTERNAL_MODULE, g_model.moduleData[EXTERNAL_MODULE].type); + } + else if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE) { + g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; + } } if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { - case 0: - { + case 0: { #if defined(HARDWARE_INTERNAL_MODULE) - IsValueAvailable checkFun = moduleIdx == 0 ? isInternalModuleAvailable : isExternalModuleAvailable; -#else - IsValueAvailable checkFun = isExternalModuleAvailable; -#endif - uint8_t moduleType = checkIncDec(event, g_model.moduleData[moduleIdx].type, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, checkFun); - if (checkIncDec_Ret) { - setModuleType(moduleIdx, moduleType); + if (moduleIdx == INTERNAL_MODULE) { + uint8_t moduleType = checkIncDec(event, g_model.moduleData[moduleIdx].type, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, + isInternalModuleAvailable); + if (checkIncDec_Ret) { + setModuleType(moduleIdx, moduleType); + } } - break; + else +#endif + reusableBuffer.moduleSetup.newType = checkIncDec(event, reusableBuffer.moduleSetup.newType, MODULE_TYPE_NONE, MODULE_TYPE_MAX, EE_MODEL, + isExternalModuleAvailable); } + break; case 1: if (isModuleDSM2(moduleIdx)) CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX); diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 5d2266202..7a7ec1974 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1109,6 +1109,8 @@ union ReusableBuffer char msg[64]; uint8_t r9mPower; int8_t antennaMode; + uint8_t previousType; + uint8_t newType; BindInformation bindInformation; struct { union { From 891c13e98df49e3e8579d162c782f7f4e23e121f Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 15:42:35 +0200 Subject: [PATCH 163/257] Spectrum analyser reworked (#6836) * Spectrum analyser reworked * Fix typo * Cosmetics * Cosmetics * yet another overall look update * T16 compilations fixes * Various Taranis compile fixes * Cosmetics * Cosmetics * Cosmetics * Cosmetics fixes --- radio/src/gui/128x64/menus.h | 2 +- .../gui/480x272/radio_spectrum_analyser.cpp | 137 +++++++++++------- radio/src/gui/480x272/radio_tools.cpp | 18 ++- radio/src/gui/common/stdlcd/CMakeLists.txt | 10 +- .../common/stdlcd/radio_spectrum_analyser.cpp | 73 +++++++--- radio/src/gui/common/stdlcd/radio_tools.cpp | 18 ++- radio/src/gui/navigation/navigation_x9d.cpp | 3 +- radio/src/opentx.h | 3 +- radio/src/pulses/multi.cpp | 11 +- radio/src/pulses/pulses.cpp | 2 +- radio/src/pulses/pulses.h | 47 +++--- radio/src/targets/horus/CMakeLists.txt | 13 +- radio/src/targets/horus/board.cpp | 4 +- radio/src/targets/horus/board.h | 2 +- radio/src/telemetry/multi.cpp | 65 ++++++++- radio/src/telemetry/multi.h | 7 + 16 files changed, 284 insertions(+), 131 deletions(-) diff --git a/radio/src/gui/128x64/menus.h b/radio/src/gui/128x64/menus.h index 4f1428a6f..a8e47db57 100644 --- a/radio/src/gui/128x64/menus.h +++ b/radio/src/gui/128x64/menus.h @@ -52,7 +52,7 @@ enum MenuRadioIndexes { MENU_RADIO_SETUP, CASE_SDCARD(MENU_RADIO_SD_MANAGER) -#if defined(LUA) || defined(PXX2) +#if defined(LUA) || defined(PXX2) || defined(MULTIMODULE) MENU_RADIO_TOOLS, #endif MENU_RADIO_SPECIAL_FUNCTIONS, diff --git a/radio/src/gui/480x272/radio_spectrum_analyser.cpp b/radio/src/gui/480x272/radio_spectrum_analyser.cpp index 260fbc767..88f4529c8 100644 --- a/radio/src/gui/480x272/radio_spectrum_analyser.cpp +++ b/radio/src/gui/480x272/radio_spectrum_analyser.cpp @@ -22,20 +22,41 @@ extern uint8_t g_moduleIdx; -enum SpectrumFields { +enum SpectrumFields +{ SPECTRUM_FREQUENCY, SPECTRUM_SPAN, + SPECTRUM_TRACK, SPECTRUM_FIELDS_MAX }; +coord_t getAverage(uint8_t number, uint8_t * value) +{ + uint16_t sum = 0; + for (uint8_t i = 0; i < number; i++) { + sum += value[i]; + } + return sum / number; +} + +#define SPECTRUM_ROW (isModuleMultimodule(g_moduleIdx) ? READONLY_ROW : (uint8_t)0) +constexpr uint8_t GREYBAR_HEIGHT = 12; + bool menuRadioSpectrumAnalyser(event_t event) { - SUBMENU(STR_MENU_SPECTRUM_ANALYSER, ICON_RADIO_SPECTRUM_ANALYSER, 1, {1}); + SUBMENU(STR_MENU_SPECTRUM_ANALYSER, ICON_RADIO_SPECTRUM_ANALYSER, SPECTRUM_FIELDS_MAX, { + SPECTRUM_ROW, //Freq + SPECTRUM_ROW, //Span + 0 //Track + }); if (menuEvent) { - lcdDrawCenteredText(LCD_H/2, STR_STOPPING); + lcdDrawCenteredText(LCD_H / 2, STR_STOPPING); lcdRefresh(); - moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); + if (isModulePXX2(g_moduleIdx)) + moduleState[g_moduleIdx].readModuleInformation(&reusableBuffer.moduleSetup.pxx2.moduleInformation, PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); + else if (isModuleMultimodule((g_moduleIdx))) + moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL; /* wait 1s to resume normal operation before leaving */ watchdogSuspend(1000); RTOS_WAIT_MS(1000); @@ -44,7 +65,7 @@ bool menuRadioSpectrumAnalyser(event_t event) if (moduleState[g_moduleIdx].mode != MODULE_MODE_SPECTRUM_ANALYSER) { if (TELEMETRY_STREAMING()) { - lcdDrawCenteredText(LCD_H/2, STR_TURN_OFF_RECEIVER); + POPUP_WARNING(STR_TURN_OFF_RECEIVER); if (event == EVT_KEY_FIRST(KEY_EXIT)) { killEvents(event); popMenu(); @@ -62,7 +83,10 @@ bool menuRadioSpectrumAnalyser(event_t event) reusableBuffer.spectrumAnalyser.freqMax = 930; } else { - reusableBuffer.spectrumAnalyser.spanDefault = 40; // 40MHz + if (isModuleMultimodule(g_moduleIdx)) + reusableBuffer.spectrumAnalyser.spanDefault = 80; // 80MHz + else + reusableBuffer.spectrumAnalyser.spanDefault = 40; // 40MHz reusableBuffer.spectrumAnalyser.spanMax = 80; reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz reusableBuffer.spectrumAnalyser.freqMin = 2400; @@ -71,13 +95,14 @@ bool menuRadioSpectrumAnalyser(event_t event) reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000; reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000; + reusableBuffer.spectrumAnalyser.track = reusableBuffer.spectrumAnalyser.freq; reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W; reusableBuffer.spectrumAnalyser.dirty = true; moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER; } - for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); + for (uint8_t i = 0; i < SPECTRUM_FIELDS_MAX; i++) { + LcdFlags attr = (menuVerticalPosition == i ? (s_editMode > 0 ? INVERS | BLINK : INVERS) : 0); switch (i) { case SPECTRUM_FREQUENCY: { @@ -94,10 +119,10 @@ bool menuRadioSpectrumAnalyser(event_t event) break; } - case SPECTRUM_SPAN: + case SPECTRUM_SPAN: { uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000; lcdDrawText(MENUS_MARGIN_LEFT + 100, MENU_FOOTER_TOP, "S:", TEXT_INVERTED_COLOR); - lcdDrawNumber(lcdNextPos + 2, MENU_FOOTER_TOP, reusableBuffer.spectrumAnalyser.span/1000000, attr | TEXT_INVERTED_COLOR); + lcdDrawNumber(lcdNextPos + 2, MENU_FOOTER_TOP, reusableBuffer.spectrumAnalyser.span / 1000000, attr | TEXT_INVERTED_COLOR); lcdDrawText(lcdNextPos + 2, MENU_FOOTER_TOP, "MHz", TEXT_INVERTED_COLOR); if (attr) { reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, reusableBuffer.spectrumAnalyser.spanMax, 0) * 1000000; @@ -107,70 +132,72 @@ bool menuRadioSpectrumAnalyser(event_t event) } } break; + } + + case SPECTRUM_TRACK: { + uint16_t track = reusableBuffer.spectrumAnalyser.track / 1000000; + lcdDrawText(lcdNextPos + 10, MENU_FOOTER_TOP, "T:", TEXT_INVERTED_COLOR); + lcdDrawNumber(lcdNextPos + 2, MENU_FOOTER_TOP, reusableBuffer.spectrumAnalyser.track / 1000000, attr | TEXT_INVERTED_COLOR); + lcdDrawText(lcdNextPos + 2, MENU_FOOTER_TOP, "MHz", TEXT_INVERTED_COLOR); + if (attr) { + reusableBuffer.spectrumAnalyser.track = uint32_t( + checkIncDec(event, track, (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 1000000, + (reusableBuffer.spectrumAnalyser.freq + reusableBuffer.spectrumAnalyser.span / 2) / 1000000, 0)) * 1000000; + if (checkIncDec_Ret) { + reusableBuffer.spectrumAnalyser.dirty = true; + } + } + break; + } } } - + // Draw fixed part (scale,..) + lcdDrawFilledRect(0, MENU_FOOTER_TOP - GREYBAR_HEIGHT, LCD_W, GREYBAR_HEIGHT, SOLID, CURVE_AXIS_COLOR); for (uint32_t frequency = ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 10000000) * 10000000 + 10000000; ; frequency += 10000000) { int offset = frequency - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2); int x = offset / reusableBuffer.spectrumAnalyser.step; if (x >= LCD_W - 1) break; lcdDrawVerticalLine(x, MENU_HEADER_HEIGHT, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT, STASHED, CURVE_AXIS_COLOR); + + if ((frequency / 1000000) % 2 == 0) { + lcdDrawNumber(x, MENU_FOOTER_TOP - GREYBAR_HEIGHT - 1, frequency / 1000000, TINSIZE | TEXT_COLOR | CENTERED); + } } - for (uint8_t power = 20; ; power += 20) { + for (uint8_t power = 20;; power += 20) { int y = MENU_FOOTER_TOP - 1 - limit(0, power << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT); if (y <= MENU_HEADER_HEIGHT) break; lcdDrawHorizontalLine(0, y, LCD_W, STASHED, CURVE_AXIS_COLOR); } - coord_t peak_y = LCD_H; - coord_t peak_x = 0; + // Draw Tracker + int offset = reusableBuffer.spectrumAnalyser.track - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2); + int x = offset / reusableBuffer.spectrumAnalyser.step; + lcdDrawVerticalLine(x, MENU_HEADER_HEIGHT, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT - GREYBAR_HEIGHT, SOLID, TEXT_COLOR); - coord_t prev_yv = (coord_t)-1; - for (coord_t xv=0; xv(0, reusableBuffer.spectrumAnalyser.bars[xv] << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT); - if (prev_yv != (coord_t)-1) { - if (yv < peak_y) { - peak_x = xv; - peak_y = yv; - } - if (prev_yv < yv) { - for (int y=prev_yv; y<=yv; y+=1) { - lcdDrawPoint(xv, y, TEXT_COLOR); - } - } - else { - for (int y=yv; y<=prev_yv; y+=1) { - lcdDrawPoint(xv, y, TEXT_COLOR); - } + // Draw spectrum data + constexpr uint8_t step = 4; + + for (coord_t xv = 0; xv <= LCD_W - step; xv += 4) { + coord_t yv = MENU_FOOTER_TOP - 1 - limit(0, getAverage(step, &reusableBuffer.spectrumAnalyser.bars[xv]) << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT); + coord_t max_yv = MENU_FOOTER_TOP - 1 - limit(0, getAverage(step, &reusableBuffer.spectrumAnalyser.max[xv]) << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT); + + // Signal bar + lcdDrawSolidFilledRect(xv, yv, step - 1, LCD_H - yv - MENU_FOOTER_HEIGHT - GREYBAR_HEIGHT, TEXT_INVERTED_BGCOLOR); + lcdDrawRect(xv, yv, step - 1, LCD_H - yv - MENU_FOOTER_HEIGHT - GREYBAR_HEIGHT); + + // Signal max + lcdDrawLine(xv, max_yv, xv + step, max_yv); + + // Decay max values + if (max_yv < yv) { // Those value are INVERTED (MENU_FOOTER_TOP - value) + for (uint8_t i = 0; i < step; i++) { + reusableBuffer.spectrumAnalyser.max[xv + i] -= 1; } } - prev_yv = yv; } - prev_yv = (coord_t)-1; - for (coord_t xv=0; xv(0, reusableBuffer.spectrumAnalyser.max[xv] << 1, LCD_H - MENU_HEADER_HEIGHT - MENU_FOOTER_HEIGHT); - if (prev_yv != (coord_t)-1) { - if (prev_yv < yv) { - for (int y=prev_yv; y<=yv; y+=1) { - lcdDrawPoint(xv, y, TEXT_INVERTED_BGCOLOR); - } - } - else { - for (int y=yv; y<=prev_yv; y+=1) { - lcdDrawPoint(xv, y, TEXT_INVERTED_BGCOLOR); - } - } - } - prev_yv = yv; - } - - coord_t y = max(MENU_HEADER_HEIGHT + 1, peak_y - FH); - lcdDrawNumber(limit(20, peak_x, LCD_W - 20), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / LCD_W)) / 1000000, TINSIZE | CENTERED); - lcdDrawText(lcdNextPos, y, "M", TINSIZE); - return true; -} +} \ No newline at end of file diff --git a/radio/src/gui/480x272/radio_tools.cpp b/radio/src/gui/480x272/radio_tools.cpp index cf560fd71..a11ba0103 100644 --- a/radio/src/gui/480x272/radio_tools.cpp +++ b/radio/src/gui/480x272/radio_tools.cpp @@ -85,17 +85,21 @@ bool menuRadioTools(event_t event) uint8_t index = 0; -#if defined(PXX2) - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) +#if defined(INTERNAL_MODULE_PXX2) + if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) + if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE); - - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) +#elif defined(INTERNAL_MODULE_MULTI) + addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); +#endif +#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); - - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) +#endif +#if defined(PXX2) + if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE); #endif diff --git a/radio/src/gui/common/stdlcd/CMakeLists.txt b/radio/src/gui/common/stdlcd/CMakeLists.txt index 2da32d37a..0d3f726b3 100644 --- a/radio/src/gui/common/stdlcd/CMakeLists.txt +++ b/radio/src/gui/common/stdlcd/CMakeLists.txt @@ -18,7 +18,7 @@ set(GUI_SRC model_curve_edit.cpp ) -if(PXX2 OR LUA) +if(PXX2 OR LUA OR MULTIMODULE) set(GUI_SRC ${GUI_SRC} ../common/stdlcd/radio_tools.cpp) endif() @@ -36,8 +36,14 @@ endif() if(PXX2) set(GUI_SRC ${GUI_SRC} - ../common/stdlcd/radio_spectrum_analyser.cpp ../common/stdlcd/radio_power_meter.cpp ) endif() +if(PXX2 OR MULTIMODULE) + set(GUI_SRC + ${GUI_SRC} + ../common/stdlcd/radio_spectrum_analyser.cpp + ) +endif() + diff --git a/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp b/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp index a122dd7ba..ab96c52d5 100644 --- a/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp +++ b/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp @@ -25,12 +25,19 @@ extern uint8_t g_moduleIdx; enum SpectrumFields { SPECTRUM_FREQUENCY, SPECTRUM_SPAN, + SPECTRUM_TRACK, SPECTRUM_FIELDS_MAX }; +#define SPECTRUM_ROW (isModuleMultimodule(g_moduleIdx) ? READONLY_ROW : (uint8_t)0) + void menuRadioSpectrumAnalyser(event_t event) { - SUBMENU(STR_MENU_SPECTRUM_ANALYSER, 1, {1}); + SUBMENU(STR_MENU_SPECTRUM_ANALYSER, SPECTRUM_FIELDS_MAX, { + SPECTRUM_ROW, //Freq + SPECTRUM_ROW, //Span + 0 //Tracker + }); if (menuEvent) { lcdDrawCenteredText(LCD_H/2, STR_STOPPING); @@ -62,7 +69,10 @@ void menuRadioSpectrumAnalyser(event_t event) reusableBuffer.spectrumAnalyser.freqMax = 930; } else { - reusableBuffer.spectrumAnalyser.spanDefault = 40; // 40MHz + if (isModuleMultimodule(g_moduleIdx)) + reusableBuffer.spectrumAnalyser.spanDefault = 80; // 80MHz + else + reusableBuffer.spectrumAnalyser.spanDefault = 40; // 40MHz reusableBuffer.spectrumAnalyser.spanMax = 80; reusableBuffer.spectrumAnalyser.freqDefault = 2440; // 2440MHz reusableBuffer.spectrumAnalyser.freqMin = 2400; @@ -71,20 +81,22 @@ void menuRadioSpectrumAnalyser(event_t event) reusableBuffer.spectrumAnalyser.span = reusableBuffer.spectrumAnalyser.spanDefault * 1000000; reusableBuffer.spectrumAnalyser.freq = reusableBuffer.spectrumAnalyser.freqDefault * 1000000; + reusableBuffer.spectrumAnalyser.track = reusableBuffer.spectrumAnalyser.freq; reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W; reusableBuffer.spectrumAnalyser.dirty = true; moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER; } for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); + uint8_t sub = menuVerticalPosition; + LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0); switch (i) { case SPECTRUM_FREQUENCY: { uint16_t frequency = reusableBuffer.spectrumAnalyser.freq / 1000000; - lcdDrawText(1, 10, "F:", 0); - lcdDrawNumber(lcdLastRightPos + 2, 10, frequency, attr); - lcdDrawText(lcdLastRightPos + 2, 10, "MHz", 0); + lcdDrawText(1, 10, "F:", SMLSIZE); + lcdDrawNumber(lcdLastRightPos + 1, 10, frequency, attr|SMLSIZE); + lcdDrawText(lcdLastRightPos + 1, 10, "MHz", SMLSIZE); if (attr) { reusableBuffer.spectrumAnalyser.freq = uint32_t(checkIncDec(event, frequency, reusableBuffer.spectrumAnalyser.freqMin, reusableBuffer.spectrumAnalyser.freqMax, 0)) * 1000000; if (checkIncDec_Ret) { @@ -94,11 +106,11 @@ void menuRadioSpectrumAnalyser(event_t event) break; } - case SPECTRUM_SPAN: + case SPECTRUM_SPAN: { uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000; - lcdDrawText(lcdLastRightPos + 5, 10, "S:", 0); - lcdDrawNumber(lcdLastRightPos + 2, 10, reusableBuffer.spectrumAnalyser.span/1000000, attr); - lcdDrawText(lcdLastRightPos + 2, 10, "MHz", 0); + lcdDrawText(lcdLastRightPos + 2, 10, "S:", SMLSIZE); + lcdDrawNumber(lcdLastRightPos + 1, 10, reusableBuffer.spectrumAnalyser.span / 1000000, attr | SMLSIZE); + lcdDrawText(lcdLastRightPos + 1, 10, "MHz", SMLSIZE); if (attr) { reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, reusableBuffer.spectrumAnalyser.spanMax, 0) * 1000000; if (checkIncDec_Ret) { @@ -107,21 +119,42 @@ void menuRadioSpectrumAnalyser(event_t event) } } break; + } + + case SPECTRUM_TRACK: { + uint16_t track = reusableBuffer.spectrumAnalyser.track / 1000000; + lcdDrawText(lcdNextPos + 2, 10, "T:", SMLSIZE); + lcdDrawNumber(lcdNextPos + 1, 10, reusableBuffer.spectrumAnalyser.track / 1000000, attr | SMLSIZE); + lcdDrawText(lcdNextPos + 1, 10, "MHz", SMLSIZE); + if (attr) { + reusableBuffer.spectrumAnalyser.track = uint32_t( + checkIncDec(event, track, (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) / 1000000, + (reusableBuffer.spectrumAnalyser.freq + reusableBuffer.spectrumAnalyser.span / 2) / 1000000, 0)) * 1000000; + if (checkIncDec_Ret) { + reusableBuffer.spectrumAnalyser.dirty = true; + } + } + break; + } } } - uint8_t peak_y = 1; - uint8_t peak_x = 0; + // Signal bar for (uint8_t i=0; i(reusableBuffer.spectrumAnalyser.bars[i] >> 1, LCD_H); - if (h > peak_y) { - peak_x = i; - peak_y = h; - } lcdDrawSolidVerticalLine(i, LCD_H - h, h); } - int8_t y = max(FH, LCD_H - peak_y - FH); - lcdDrawNumber(min(100, peak_x), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / LCD_W)) / 1000000, TINSIZE); - lcdDrawText(lcdLastRightPos, y, "M", TINSIZE); -} + // Signal max + for (uint8_t i=0; i(reusableBuffer.spectrumAnalyser.max[i] >> 1, LCD_H); + lcdDrawPoint(i, LCD_H - h); + if (reusableBuffer.spectrumAnalyser.max[i] > 1) + reusableBuffer.spectrumAnalyser.max[i] -= 1; + } + + // Draw Tracker + int offset = reusableBuffer.spectrumAnalyser.track - (reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2); + int x = offset / reusableBuffer.spectrumAnalyser.step; + lcdDrawVerticalLine(x, 10+FH+1, LCD_H, SOLID); +} \ No newline at end of file diff --git a/radio/src/gui/common/stdlcd/radio_tools.cpp b/radio/src/gui/common/stdlcd/radio_tools.cpp index 1ac177c21..b2d13cba5 100644 --- a/radio/src/gui/common/stdlcd/radio_tools.cpp +++ b/radio/src/gui/common/stdlcd/radio_tools.cpp @@ -82,17 +82,21 @@ void menuRadioTools(event_t event) uint8_t index = 0; -#if defined(PXX2) - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) +#if defined(INTERNAL_MODULE_PXX2) + if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) + if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE); - - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) +#elif defined(INTERNAL_MODULE_MULTI) + addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); +#endif +#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); - - if (isPXX2ModuleOptionAvailable(reusableBuffer.radioTools.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) +#endif +#if defined(PXX2) + if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE); #endif diff --git a/radio/src/gui/navigation/navigation_x9d.cpp b/radio/src/gui/navigation/navigation_x9d.cpp index 911455211..a5d6fc332 100644 --- a/radio/src/gui/navigation/navigation_x9d.cpp +++ b/radio/src/gui/navigation/navigation_x9d.cpp @@ -373,7 +373,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t break; case EVT_KEY_BREAK(KEY_ENTER): - if (s_editMode > 1) + if (s_editMode > 1) break; if (menuHorizontalPosition < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) { l_posHorz = 0; @@ -545,4 +545,3 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuHorizontalPosition = l_posHorz; } - diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 7a7ec1974..34931dd44 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1187,12 +1187,11 @@ union ReusableBuffer struct { uint8_t bars[LCD_W]; -#if defined(COLORLCD) uint8_t max[LCD_W]; -#endif uint32_t freq; uint32_t span; uint32_t step; + uint32_t track; uint8_t spanDefault; uint8_t spanMax; uint16_t freqDefault; diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index 9ceb57886..7c686546f 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -37,7 +37,7 @@ void sendChannels(uint8_t moduleIdx); static void sendMulti(uint8_t moduleIdx, uint8_t b) { -#if defined(INTERNAL_MODULE_MULTI) +#if defined(HARDWARE_INTERNAL_MODULE) if (moduleIdx == INTERNAL_MODULE) { intmodulePulsesData.multi.sendByte(b); } @@ -171,6 +171,15 @@ void sendFrameProtocolHeader(uint8_t moduleIdx, bool failsafe) int8_t optionValue = g_model.moduleData[moduleIdx].multi.optionValue; uint8_t protoByte = 0; + + if (moduleState[moduleIdx].mode == MODULE_MODE_SPECTRUM_ANALYSER) { + sendMulti(moduleIdx, (uint8_t) 0x54); // Header byte + sendMulti(moduleIdx, (uint8_t) 54); // Spectrum custom protocol + sendMulti(moduleIdx, (uint8_t) 0); + sendMulti(moduleIdx, (uint8_t) 0); + return; + } + if (moduleState[moduleIdx].mode == MODULE_MODE_BIND) protoByte |= MULTI_SEND_BIND; else if (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK) diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index e771d4e90..6d869e484 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -287,7 +287,7 @@ void setupPulsesExternalModule(uint8_t protocol) } #if defined(HARDWARE_INTERNAL_MODULE) -void enablePulsesInternalModule(uint8_t protocol) +static void enablePulsesInternalModule(uint8_t protocol) { // start new protocol hardware here diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 9fa17a196..8dc12ee68 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -41,6 +41,12 @@ #define IS_DSM2_PROTOCOL(protocol) (0) #endif +#if defined(DSM2_SERIAL) + #define IS_DSM2_SERIAL_PROTOCOL(protocol) (IS_DSM2_PROTOCOL(protocol)) +#else + #define IS_DSM2_SERIAL_PROTOCOL(protocol) (0) +#endif + #if defined(MULTIMODULE) #define IS_MULTIMODULE_PROTOCOL(protocol) (protocol==PROTOCOL_CHANNELS_MULTIMODULE) #if !defined(DSM2) @@ -147,7 +153,8 @@ PACK(struct ModuleState { uint8_t paused:1; uint8_t spare:7; uint16_t counter; - union { + union + { ModuleInformation * moduleInformation; ModuleSettings * moduleSettings; ReceiverSettings * receiverSettings; @@ -165,12 +172,14 @@ PACK(struct ModuleState { moduleInformation->maximum = last; mode = MODULE_MODE_GET_HARDWARE_INFO; } + void readModuleSettings(ModuleSettings * destination) { moduleSettings = destination; moduleSettings->state = PXX2_SETTINGS_READ; mode = MODULE_MODE_MODULE_SETTINGS; } + void writeModuleSettings(ModuleSettings * source) { moduleSettings = source; @@ -178,12 +187,14 @@ PACK(struct ModuleState { moduleSettings->timeout = 0; mode = MODULE_MODE_MODULE_SETTINGS; } + void readReceiverSettings(ReceiverSettings * destination) { receiverSettings = destination; receiverSettings->state = PXX2_SETTINGS_READ; mode = MODULE_MODE_RECEIVER_SETTINGS; } + void writeReceiverSettings(ReceiverSettings * source) { receiverSettings = source; @@ -238,21 +249,21 @@ PACK(struct CrossfirePulsesData { union InternalModulePulsesData { #if defined(PXX1) - #if defined(INTMODULE_USART) - UartPxx1Pulses pxx_uart; - #else - PwmPxx1Pulses pxx; - #endif +#if defined(INTMODULE_USART) + UartPxx1Pulses pxx_uart; +#else + PwmPxx1Pulses pxx; +#endif #endif #if defined(PXX2) Pxx2Pulses pxx2; #endif -#if defined(INTERNAL_MODULE_MULTI) //&& defined(INTMODULE_USART) - UartMultiPulses multi; +#if defined(MULTIMODULE) //&& defined(INTMODULE_USART) + UartMultiPulses multi; #endif - + #if defined(INTERNAL_MODULE_PPM) PpmPulsesData ppm; #endif @@ -260,14 +271,14 @@ union InternalModulePulsesData { union ExternalModulePulsesData { #if defined(PXX1) - #if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) - UartPxx1Pulses pxx_uart; - #endif - #if defined(PPM_PIN_SERIAL) - SerialPxx1Pulses pxx; - #else - PwmPxx1Pulses pxx; - #endif +#if defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML) + UartPxx1Pulses pxx_uart; +#endif +#if defined(PPM_PIN_SERIAL) + SerialPxx1Pulses pxx; +#else + PwmPxx1Pulses pxx; +#endif #endif #if defined(PXX2) @@ -417,4 +428,4 @@ inline bool isModuleInBeepMode() return false; } -#endif // _PULSES_H_ +#endif // _PULSES_H_ \ No newline at end of file diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 14015b25e..bc16f5961 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -2,6 +2,7 @@ option(DISK_CACHE "Enable SD card disk cache" ON) option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON) option(PXX1 "PXX1 protocol support" ON) option(PXX2 "PXX2 protocol support" OFF) +option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON) set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)") set(CPU_TYPE STM32F4) @@ -146,16 +147,16 @@ set(GUI_SRC rle.cpp ) -if(PXX2 OR LUA) +if(PXX2 OR LUA OR MULTIMODULE) set(GUI_SRC ${GUI_SRC} radio_tools.cpp) endif() +if(PXX2 OR MULTIMODULE) + set(GUI_SRC ${GUI_SRC} radio_spectrum_analyser.cpp) +endif() + if(PXX2) - set(GUI_SRC - ${GUI_SRC} - radio_spectrum_analyser.cpp - radio_power_meter.cpp - ) + set(GUI_SRC ${GUI_SRC} radio_power_meter.cpp) endif() if(DISK_CACHE) diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 40900a099..0ec6e9746 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -49,7 +49,7 @@ void watchdogInit(unsigned int duration) extern "C" void initialise_monitor_handles(); #endif -#if defined(PCBX10) +#if defined(PCBX10) && !defined(RADIO_T16) void sportUpdateInit() { GPIO_InitTypeDef GPIO_InitStructure; @@ -171,7 +171,7 @@ void boardInit() DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM4_STOP|DBGMCU_TIM5_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM7_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM9_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM11_STOP|DBGMCU_TIM12_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE); #endif -#if defined(PCBX10) +#if defined(PCBX10) && !defined(RADIO_T16) ledInit(); sportUpdateInit(); #endif diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 3d891cb8a..c9d72c8ab 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -569,7 +569,7 @@ void telemetryClearFifo(); extern uint32_t telemetryErrors; // Sport update driver -#if defined(PCBX10) +#if defined(PCBX10) && !defined(RADIO_T16) void sportUpdatePowerOn(); void sportUpdatePowerOff(); #define SPORT_UPDATE_POWER_ON() sportUpdatePowerOn() diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 8225975e4..e7ff0487e 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -21,10 +21,12 @@ #include "telemetry.h" #include "multi.h" +extern uint8_t g_moduleIdx; + enum MultiPacketTypes : uint8_t { MultiStatus = 1, - FrSkySportTelemtry, + FrSkySmoduleIdxTelemtry, FrSkyHubTelemetry, SpektrumTelemetry, DSMBindPacket, @@ -138,7 +140,14 @@ void setMultiTelemetryBufferState(uint8_t, MultiBufferState state) static MultiBufferState guessProtocol(uint8_t module) { - if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_DSM2) + uint32_t moduleIdx = EXTERNAL_MODULE; +#if defined(INTERNAL_MODULE_MULTI) + if (isModuleMultimodule(INTERNAL_MODULE)) { + moduleIdx = INTERNAL_MODULE; + } +#endif + + if (g_model.moduleData[moduleIdx].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_DSM2) return SpektrumTelemetryFallback; else if (g_model.moduleData[module].getMultiProtocol(false) == MODULE_SUBTYPE_MULTI_FS_AFHDS2A) return FlyskyTelemetryFallback; @@ -146,6 +155,44 @@ static MultiBufferState guessProtocol(uint8_t module) return FrskyTelemetryFallback; } +static void processMultiScannerPacket(const uint8_t *data) +{ + uint8_t cur_channel = data[0]; + if (moduleState[g_moduleIdx].mode == MODULE_MODE_SPECTRUM_ANALYSER) { + for (uint8_t channel = 0; channel <5; channel++) { + uint8_t power = max(0,(data[channel+1] - 34) >> 1); // remove everything below -120dB + +#if LCD_W == 480 + coord_t x = cur_channel*2; + if (x < LCD_W) { + reusableBuffer.spectrumAnalyser.bars[x] = power; + reusableBuffer.spectrumAnalyser.bars[x+1] = power; + if (power > reusableBuffer.spectrumAnalyser.max[x]) { + reusableBuffer.spectrumAnalyser.max[x] = power; + reusableBuffer.spectrumAnalyser.max[x+1] = power; + } +#elif LCD_W == 212 + coord_t x = cur_channel; + if (x <= LCD_W) { + reusableBuffer.spectrumAnalyser.bars[x] = power; + if (power > reusableBuffer.spectrumAnalyser.max[x]) { + reusableBuffer.spectrumAnalyser.max[x] = power; + } +#else + coord_t x = cur_channel/2 + 1; + if (x <= LCD_W) { + reusableBuffer.spectrumAnalyser.bars[x] = power; + if (power > reusableBuffer.spectrumAnalyser.max[x]) { + reusableBuffer.spectrumAnalyser.max[x] = power; + } +#endif + } + if (++cur_channel > MULTI_SCANNER_MAX_CHANNEL) + cur_channel = 0; + } + } +} + static void processMultiStatusPacket(const uint8_t * data, uint8_t module) { MultiModuleStatus &status = getMultiModuleStatus(module); @@ -248,11 +295,11 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) TRACE("[MP] Received Frsky HUB telemetry len %d < 4", len); break; - case FrSkySportTelemtry: + case FrSkySmoduleIdxTelemtry: if (len >= 4) sportProcessTelemetryPacket(data); else - TRACE("[MP] Received sport telemetry len %d < 4", len); + TRACE("[MP] Received smoduleIdx telemetry len %d < 4", len); break; case InputSync: @@ -269,11 +316,17 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) #if defined(LUA) case FrskySportPolling: if (len >= 1 && outputTelemetryBuffer.destination == TELEMETRY_ENDPOINT_SPORT && data[0] == outputTelemetryBuffer.sport.physicalId) { - TRACE("MP Sending sport data out."); + TRACE("MP Sending smoduleIdx data out."); sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size); } break; #endif + case SpectrumScannerPacket: + if (len == 6) + processMultiScannerPacket(data); + else + TRACE("[MP] Received spectrum scanner len %d != 6", len); + break; default: TRACE("[MP] Unkown multi packet type 0x%02X, len %d", type, len); @@ -319,7 +372,7 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin return; } - // Caluclate how many samples went into the reported input Lag (*10) + // Caluclate how many samples went into the remoduleIdxed input Lag (*10) int numsamples = interval * 10000 / targetRefreshRate; // Convert lagDifference to ps diff --git a/radio/src/telemetry/multi.h b/radio/src/telemetry/multi.h index 1bfd1ded6..83f3de6fb 100644 --- a/radio/src/telemetry/multi.h +++ b/radio/src/telemetry/multi.h @@ -80,10 +80,17 @@ Type 0x06 Flysky AFHDS2 telemetry data data[0] = RSSI value data[1-28] telemetry data +Type 0x0B Spectrum Scanner telemetry data + length: 6 + data[0] = start channel (2400 + x*0.333 Mhz) + data[1-5] power levels + */ void processMultiTelemetryData(uint8_t data, uint8_t module); +#define MULTI_SCANNER_MAX_CHANNEL 249 + // This should be put into the Module definition if other modules gain this functionality struct MultiModuleSyncStatus { uint32_t adjustedRefreshRate; // in ps From 5976a6eda2d4913b0efb12b1a5db7b5de084c523 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 16:00:43 +0200 Subject: [PATCH 164/257] Compile fix --- companion/src/firmwares/boards.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index 845f181e8..c3cd3ff59 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -322,7 +322,7 @@ inline bool HAS_EXTERNAL_ANTENNA(Board::Type board) inline bool IS_ACCESS_RADIO(Board::Type board, QString &id) { return (IS_TARANIS_XLITES(board) || IS_TARANIS_X9LITE(board) || board == Board::BOARD_TARANIS_X9DP_2019 || board == Board::BOARD_X10_EXPRESS || - (IS_HORUS(board) && id.contains("internalaccess")); + (IS_HORUS(board) && id.contains("internalaccess"))); } #endif // _BOARDS_H_ From 99fa392c9ae27d55359d0fa8e854bd4adceb61d8 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 16:12:38 +0200 Subject: [PATCH 165/257] Temporary compile fix --- companion/src/firmwares/opentx/opentxeeprom.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 9e95b63b5..24e3779fc 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2090,6 +2090,10 @@ class ModuleUnionField: public UnionField { attr==PULSES_PXX_R9M_LITE; } + void beforeExport() override + { + } + void afterImport() override { if (module.protocol == PULSES_PXX_XJT_X16) { From 801d5bb2ca5082e955473fca405d20aeff312eab Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Oct 2019 17:35:47 +0200 Subject: [PATCH 166/257] Fix replace issue --- radio/src/telemetry/multi.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index e7ff0487e..268fb533c 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -26,7 +26,7 @@ extern uint8_t g_moduleIdx; enum MultiPacketTypes : uint8_t { MultiStatus = 1, - FrSkySmoduleIdxTelemtry, + FrSkySportTelemetry, FrSkyHubTelemetry, SpektrumTelemetry, DSMBindPacket, @@ -295,11 +295,11 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) TRACE("[MP] Received Frsky HUB telemetry len %d < 4", len); break; - case FrSkySmoduleIdxTelemtry: + case FrSkySportTelemetry: if (len >= 4) sportProcessTelemetryPacket(data); else - TRACE("[MP] Received smoduleIdx telemetry len %d < 4", len); + TRACE("[MP] Received sport telemetry len %d < 4", len); break; case InputSync: @@ -316,7 +316,7 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) #if defined(LUA) case FrskySportPolling: if (len >= 1 && outputTelemetryBuffer.destination == TELEMETRY_ENDPOINT_SPORT && data[0] == outputTelemetryBuffer.sport.physicalId) { - TRACE("MP Sending smoduleIdx data out."); + TRACE("MP Sending sport data out."); sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size); } break; @@ -372,7 +372,7 @@ void MultiModuleSyncStatus::calcAdjustedRefreshRate(uint16_t newRefreshRate, uin return; } - // Caluclate how many samples went into the remoduleIdxed input Lag (*10) + // Caluclate how many samples went into the reported input Lag (*10) int numsamples = interval * 10000 / targetRefreshRate; // Convert lagDifference to ps From 9bdccd47fee167f0408248640bb2b10a0ce24f2a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 10 Oct 2019 21:38:13 +0200 Subject: [PATCH 167/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index ce815fc70..cd3421cf4 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1598,3 +1598,4 @@ Markus Goelzner Jean-Claude Etiemble Wojciech Winiarski Michael Fleming +Russell G Shanks From 135133423a21d2721d62a5b6db5e4e29832c31e7 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 11 Oct 2019 08:09:59 +0200 Subject: [PATCH 168/257] Bsongis/issue 6910 x10 express bluetooth (#6931) [X10 Express] Bluetooth function added --- radio/src/bluetooth.cpp | 10 ++-- radio/src/gui/128x64/model_setup.cpp | 2 +- radio/src/gui/212x64/model_setup.cpp | 2 +- radio/src/gui/480x272/model_setup.cpp | 54 +++++++++++++------ radio/src/gui/480x272/radio_hardware.cpp | 18 +++++-- radio/src/gui/480x272/radio_sdmanager.cpp | 4 ++ .../src/gui/common/stdlcd/radio_hardware.cpp | 8 +-- radio/src/translations/cz.h.txt | 6 +-- radio/src/translations/de.h.txt | 6 +-- radio/src/translations/en.h.txt | 4 +- radio/src/translations/es.h.txt | 4 +- radio/src/translations/fi.h.txt | 4 +- radio/src/translations/fr.h.txt | 4 +- radio/src/translations/it.h.txt | 4 +- radio/src/translations/nl.h.txt | 4 +- radio/src/translations/pl.h.txt | 4 +- radio/src/translations/pt.h.txt | 4 +- radio/src/translations/se.h.txt | 4 +- 18 files changed, 93 insertions(+), 53 deletions(-) diff --git a/radio/src/bluetooth.cpp b/radio/src/bluetooth.cpp index 877d7466b..f1be6a9d8 100644 --- a/radio/src/bluetooth.cpp +++ b/radio/src/bluetooth.cpp @@ -73,7 +73,7 @@ char * Bluetooth::readline(bool error_reset) { uint8_t byte; - while (1) { + while (true) { if (!btRxFifo.pop(byte)) { #if defined(PCBX9E) // X9E BT module can get unresponsive @@ -280,7 +280,7 @@ void Bluetooth::receiveTrainer() { uint8_t byte; - while (1) { + while (true) { if (!btRxFifo.pop(byte)) { return; } @@ -451,9 +451,11 @@ void Bluetooth::wakeup() ++reusableBuffer.moduleSetup.bt.devicesCount; } } - /* else if (state == BLUETOOTH_STATE_DISCOVER_START && !strcmp(line, "OK+DISCE")) { +#if defined(PCBHORUS) + else if (state == BLUETOOTH_STATE_DISCOVER_START && !strcmp(line, "OK+DISCE")) { state = BLUETOOTH_STATE_DISCOVER_END; - } */ + } +#endif else if (state == BLUETOOTH_STATE_CLEAR_REQUESTED) { char command[] = "AT+CLEAR"; writeString(command); diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 4587bcded..59dbd299a 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -1023,7 +1023,7 @@ void menuModelSetup(event_t event) } if (bluetooth.state == BLUETOOTH_STATE_DISCOVER_START && reusableBuffer.moduleSetup.bt.devicesCount > 0) { - popupMenuItemsCount = min(reusableBuffer.moduleSetup.bt.devicesCount, 6); + popupMenuItemsCount = min(reusableBuffer.moduleSetup.bt.devicesCount, MAX_BLUETOOTH_DISTANT_ADDR); for (uint8_t i=0; i 0) { - popupMenuItemsCount = min(reusableBuffer.moduleSetup.bt.devicesCount, 6); + popupMenuItemsCount = min(reusableBuffer.moduleSetup.bt.devicesCount, MAX_BLUETOOTH_DISTANT_ADDR); for (uint8_t i=0; i 0) { + popupMenuItemsCount = min(reusableBuffer.moduleSetup.bt.devicesCount, MAX_BLUETOOTH_DISTANT_ADDR); + for (uint8_t i = 0; i < popupMenuItemsCount; i++) { + popupMenuItems[i] = reusableBuffer.moduleSetup.bt.devices[i]; + } + POPUP_MENU_START(onBluetoothConnectMenu); + } + } + else { + if (bluetooth.distantAddr[0]) + lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y+1, bluetooth.distantAddr); + else + lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, "---"); + lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, bluetooth.state == BLUETOOTH_STATE_CONNECTED ? STR_CONNECTED : STR_NOT_CONNECTED); } break; #endif diff --git a/radio/src/gui/480x272/radio_hardware.cpp b/radio/src/gui/480x272/radio_hardware.cpp index a52af8488..4735e05fd 100644 --- a/radio/src/gui/480x272/radio_hardware.cpp +++ b/radio/src/gui/480x272/radio_hardware.cpp @@ -59,6 +59,8 @@ enum MenuRadioHardwareItems { #if defined(BLUETOOTH) ITEM_RADIO_HARDWARE_BLUETOOTH_MODE, ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE, + ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR, + ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR, ITEM_RADIO_HARDWARE_BLUETOOTH_NAME, #endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) @@ -80,7 +82,7 @@ enum MenuRadioHardwareItems { #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1 #if defined(BLUETOOTH) - #define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode != BLUETOOTH_TELEMETRY ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? -1 : 0), + #define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY ? READONLY_ROW : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0), #else #define BLUETOOTH_ROWS #endif @@ -292,12 +294,22 @@ bool menuRadioHardware(event_t event) break; case ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BLUETOOTH_PIN_CODE); + lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_PIN_CODE); lcdDrawText(HW_SETTINGS_COLUMN+50, y, "000000", 0); break; + case ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR: + lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_LOCAL_ADDR); + lcdDrawText(HW_SETTINGS_COLUMN+50, y, bluetooth.localAddr[0] == '\0' ? "---" : bluetooth.localAddr); + break; + + case ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR: + lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_DIST_ADDR); + lcdDrawText(HW_SETTINGS_COLUMN+50, y, bluetooth.distantAddr[0] == '\0' ? "---" : bluetooth.distantAddr); + break; + case ITEM_RADIO_HARDWARE_BLUETOOTH_NAME: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_NAME); + lcdDrawText(INDENT_WIDTH, y, STR_NAME); editName(HW_SETTINGS_COLUMN+50, y, g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME, event, attr); break; #endif diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp index 9ec46442b..27302fa16 100644 --- a/radio/src/gui/480x272/radio_sdmanager.cpp +++ b/radio/src/gui/480x272/radio_sdmanager.cpp @@ -174,6 +174,10 @@ void onSdManagerMenu(const char * result) FrskyDeviceFirmwareUpdate device(SPORT_MODULE); device.flashFirmware(lfn); } + else if (result == STR_FLASH_BLUETOOTH_MODULE) { + getSelectionFullPath(lfn); + bluetooth.flashFirmware(lfn); + } #if defined(MULTIMODULE) #if defined(INTERNAL_MODULE_MULTI) else if (result == STR_FLASH_INTERNAL_MULTI) { diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 9a93701d5..91268de73 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -227,7 +227,7 @@ enum { #elif defined(PCBX9E) #define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0), #else - #define BLUETOOTH_ROWS uint8_t(IS_BLUETOOTH_CHIP_PRESENT() ? 0 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY ? -1 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0), + #define BLUETOOTH_ROWS uint8_t(IS_BLUETOOTH_CHIP_PRESENT() ? 0 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY ? READONLY_ROW : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0), #endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) @@ -561,17 +561,17 @@ void menuRadioHardware(event_t event) break; case ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE: - lcdDrawTextAlignedLeft(y, STR_BLUETOOTH_PIN_CODE); + lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_PIN_CODE); lcdDrawText(HW_SETTINGS_COLUMN2, y, "000000"); break; case ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR: - lcdDrawTextAlignedLeft(y, STR_BLUETOOTH_LOCAL_ADDR); + lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_LOCAL_ADDR); lcdDrawText(HW_SETTINGS_COLUMN2, y, bluetooth.localAddr[0] == '\0' ? "---" : bluetooth.localAddr); break; case ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR: - lcdDrawTextAlignedLeft(y, STR_BLUETOOTH_DIST_ADDR); + lcdDrawText(INDENT_WIDTH, y, STR_BLUETOOTH_DIST_ADDR); lcdDrawText(HW_SETTINGS_COLUMN2, y, bluetooth.distantAddr[0] == '\0' ? "---" : bluetooth.distantAddr); break; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 99ca3cb0d..2fd44ac86 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -780,9 +780,9 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Hledat" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Vzdál. addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Lokál. addr" -#define TR_BLUETOOTH_PIN_CODE TR(INDENT "PIN kód", "PIN kód") +#define TR_BLUETOOTH_DIST_ADDR "Vzdál. addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Lokál. addr" +#define TR_BLUETOOTH_PIN_CODE TR("PIN kód", "PIN kód") #define TR_BAUDRATE "Baudrate BT" #define LEN_BLUETOOTH_MODES "\012" #if defined(PCBX9E) diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 99d5d4d9c..bd92d701d 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -782,9 +782,9 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" -#define TR_BLUETOOTH_PIN_CODE TR(INDENT "PIN code", "PIN code") +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" +#define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" #if defined(PCBX9E) diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 1187ff342..c0280a685 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -780,8 +780,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index acd251727..49c469444 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -805,8 +805,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 626dde6c7..6773fc1aa 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -799,8 +799,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index c1347eca4..5e42b17c4 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -801,8 +801,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Découvrir" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Addr dist." -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Addr locale" +#define TR_BLUETOOTH_DIST_ADDR "Addr dist." +#define TR_BLUETOOTH_LOCAL_ADDR "Addr locale" #define TR_BLUETOOTH_PIN_CODE "Code PIN" #define TR_BAUDRATE "Baudrate BT" #define LEN_BLUETOOTH_MODES "\012" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index f6935d970..2a53c794c 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -800,8 +800,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 90473d9ac..8a322d726 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -788,8 +788,8 @@ TR_GYR_VSRCRAW #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 163a25d42..b2d8d9cc9 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -800,8 +800,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "Prędkość BT" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index e0087fa4c..7d0a6d372 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -790,8 +790,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 043a10eba..8b6b86a02 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -800,8 +800,8 @@ #define TR_BLUETOOTH "Bluetooth" #define TR_BLUETOOTH_DISC "Discover" #define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR INDENT "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR INDENT "Local addr" +#define TR_BLUETOOTH_DIST_ADDR "Dist addr" +#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" #define TR_BLUETOOTH_PIN_CODE "PIN code" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" From aa781337b2cd59693296652a97d18a28bdc1d613 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 11 Oct 2019 08:11:43 +0200 Subject: [PATCH 169/257] Fix segfault on Sky9X (#6930) Add calibration button to hardware screen --- radio/src/gui/128x64/menus.h | 2 +- radio/src/gui/common/stdlcd/radio_hardware.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/128x64/menus.h b/radio/src/gui/128x64/menus.h index a8e47db57..ccde94cc9 100644 --- a/radio/src/gui/128x64/menus.h +++ b/radio/src/gui/128x64/menus.h @@ -78,7 +78,7 @@ void menuRadioCalibration(event_t event); static const MenuHandlerFunc menuTabGeneral[MENU_RADIO_PAGES_COUNT] = { menuRadioSetup, CASE_SDCARD(menuRadioSdManager) -#if defined(LUA) || defined(PXX2) +#if defined(LUA) || defined(PXX2) || defined(MULTIMODULE) menuRadioTools, #endif menuRadioSpecialFunctions, diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 91268de73..a64489528 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -35,7 +35,7 @@ enum { void menuRadioHardware(event_t event) { - MENU(STR_HARDWARE, menuTabGeneral, MENU_RADIO_HARDWARE, ITEM_RADIO_HARDWARE_MAX+1, {0, 0, (uint8_t)-1, 0, 0, 0, CASE_BLUETOOTH(0)}); + MENU(STR_HARDWARE, menuTabGeneral, MENU_RADIO_HARDWARE, ITEM_RADIO_HARDWARE_MAX+1, {0, 0, 0, 0, 0, 0, CASE_BLUETOOTH(0)}); uint8_t sub = menuVerticalPosition - 1; @@ -52,6 +52,10 @@ void menuRadioHardware(event_t event) case ITEM_RADIO_HARDWARE_STICKS_GAINS_LABELS: lcdDrawTextAlignedLeft(y, "Sticks"); + lcdDrawText(LCD_W, y, BUTTON(TR_CALIBRATION), attr| RIGHT); + if (attr && event == EVT_KEY_FIRST(KEY_ENTER)) { + pushMenu(menuRadioCalibration); + } break; case ITEM_RADIO_HARDWARE_STICK_LV_GAIN: From cf184951eb6fded6d055dfcfd3ab060a281d0e79 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 11 Oct 2019 10:50:57 +0200 Subject: [PATCH 170/257] Compile fix --- radio/src/gui/480x272/radio_sdmanager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp index 27302fa16..e375a1a21 100644 --- a/radio/src/gui/480x272/radio_sdmanager.cpp +++ b/radio/src/gui/480x272/radio_sdmanager.cpp @@ -174,10 +174,12 @@ void onSdManagerMenu(const char * result) FrskyDeviceFirmwareUpdate device(SPORT_MODULE); device.flashFirmware(lfn); } +#if defined(BLUETOOTH) else if (result == STR_FLASH_BLUETOOTH_MODULE) { getSelectionFullPath(lfn); bluetooth.flashFirmware(lfn); } +#endif #if defined(MULTIMODULE) #if defined(INTERNAL_MODULE_MULTI) else if (result == STR_FLASH_INTERNAL_MULTI) { From 116fda8ee5dc91f5bc9408b511a6c80cf9e742d7 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 11 Oct 2019 11:57:16 +0200 Subject: [PATCH 171/257] Fix HW screen navigation --- radio/src/gui/480x272/radio_hardware.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/480x272/radio_hardware.cpp b/radio/src/gui/480x272/radio_hardware.cpp index 4735e05fd..283c99f2b 100644 --- a/radio/src/gui/480x272/radio_hardware.cpp +++ b/radio/src/gui/480x272/radio_hardware.cpp @@ -279,7 +279,7 @@ bool menuRadioHardware(event_t event) } } break; -#if defined(BLUETOOTH) + case ITEM_RADIO_HARDWARE_RTC_CHECK: { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_RTC_CHECK); @@ -287,7 +287,7 @@ bool menuRadioHardware(event_t event) g_eeGeneral.disableRtcWarning = 1 - editCheckBox(b, HW_SETTINGS_COLUMN + 50, y, attr, event); break; } - +#if defined(BLUETOOTH) case ITEM_RADIO_HARDWARE_BLUETOOTH_MODE: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BLUETOOTH); g_eeGeneral.bluetoothMode = editChoice(HW_SETTINGS_COLUMN+50, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_TRAINER, attr, event); From c96afeacf42124fb3463200754ebdff16b2b0cb8 Mon Sep 17 00:00:00 2001 From: Kilrah Date: Sat, 12 Oct 2019 09:56:16 +0200 Subject: [PATCH 172/257] Notify about JTX data not supported --- companion/src/mdichild.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index 4d0d7dcb8..ebb5c0492 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1457,6 +1457,23 @@ bool MdiChild::convertStorage(Board::Type from, Board::Type to, bool newFile) { QMessageBox::StandardButtons btns; QMessageBox::StandardButton dfltBtn; + + if (from == Board::BOARD_X10 && to == Board::BOARD_JUMPER_T16) { + QMessageBox msgBox; + msgBox.setWindowTitle(tr("WARNING")); + msgBox.setText(tr("

Due to the way Jumper have handled their JumperTX fork and firmware releases data integrity for settings from JumperTX cannot be trusted when migrating to OpenTX.

\ +

Importing JumperTX data into OpenTX 2.3 is not supported and dangerous.

\ +

It is unfortunately not possible for us to differentiate JumperTX data from legitimate FrSky X10 data, but You should only continue here if the file you opened comes from a real FrSky X10.

\ +

Do you really want to continue?

")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.addButton(QMessageBox::No); + msgBox.addButton(QMessageBox::Yes); + msgBox.setDefaultButton(QMessageBox::No); + + if (msgBox.exec() == QMessageBox::No) + return false; + } + QString q = tr("

Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.

").arg(Boards::getBoardName(to)).arg(Boards::getBoardName(from)).arg(userFriendlyCurrentFile()); if (newFile) { q.append(tr("Do you wish to continue with the conversion?")); From 9398e937cea551a5d74ee8e4aafbeec0d00719e0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 12 Oct 2019 11:49:29 +0200 Subject: [PATCH 173/257] Fix NL compilation --- radio/src/translations/nl.h.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 8a322d726..21ea8354b 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -335,7 +335,6 @@ #else #define TR_GYR_VSRCRAW #endif -TR_GYR_VSRCRAW #if defined(HELI) #define TR_CYC_VSRCRAW "CYC1""CYC2""CYC3" #else From 85ab7243af465c83d89d63ef81257672c6abb83b Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 13 Oct 2019 11:01:40 +0200 Subject: [PATCH 174/257] Trainer mode handling (#6943) * Trainer mode handling * Remove TODO --- companion/src/firmwares/opentx/opentxeeprom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index 24e3779fc..80b56f16f 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -2401,7 +2401,7 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig if (version >= 219) { // Trainer PPM settings - internalField.Append(new SpareBitsField<3>(this)); // TODO mode + internalField.Append(new UnsignedField<3>(this, modelData.trainerMode)); internalField.Append(new SpareBitsField<5>(this)); internalField.Append(new UnsignedField<8>(this, modelData.moduleData[2].channelsStart)); internalField.Append(new ConversionField >(this, modelData.moduleData[2].channelsCount, -8)); From b69128920dfe5f00bde0d6f090c04c73dbbdd856 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 07:49:36 +0200 Subject: [PATCH 175/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index cd3421cf4..d5a27dbd2 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1599,3 +1599,4 @@ Jean-Claude Etiemble Wojciech Winiarski Michael Fleming Russell G Shanks +Mike Sedgwick From 9131543da74cce900867a51a226808fff262e8bd Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 07:50:11 +0200 Subject: [PATCH 176/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index d5a27dbd2..f8c84ae60 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1600,3 +1600,4 @@ Wojciech Winiarski Michael Fleming Russell G Shanks Mike Sedgwick +William Goodrich From 1fee82c28213ba43b9ead107e79410f96e86a19a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 07:51:15 +0200 Subject: [PATCH 177/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index f8c84ae60..ef5f4f615 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1601,3 +1601,4 @@ Michael Fleming Russell G Shanks Mike Sedgwick William Goodrich +Marcel Schäfer From c5abb05e74ee79e34bf60a1536533bf4c5013ec5 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 10:24:13 +0200 Subject: [PATCH 178/257] [Companion] lock not correctly released --- companion/src/modeledit/setup.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index e0fbbf606..270e9b87b 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -298,8 +298,10 @@ void ModulePanel::setupFailsafes() } } - if (!hasFailsafe) + if (!hasFailsafe) { + lock = false; return; + } int row = 0; int col = 0; From 1899c26000332e34750754e2395f69c0fc51157d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 12:06:17 +0200 Subject: [PATCH 179/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index ef5f4f615..f88c86e05 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1602,3 +1602,4 @@ Russell G Shanks Mike Sedgwick William Goodrich Marcel Schäfer +Joseph Santa Cruz From 9084e0eecf84c8e434dfd270074b3daf9b7f1f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Charpentier?= Date: Mon, 14 Oct 2019 16:59:44 +0200 Subject: [PATCH 180/257] Updated French Translation (#6952) * Initial version. * Updated French translation. --- companion/src/translations/companion_fr.ts | 328 ++++++++++++--------- 1 file changed, 182 insertions(+), 146 deletions(-) diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index 90dd8e36b..c949823d1 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -728,58 +728,58 @@ Manche Droit: Profondeur, Direction Boards - + Left Horizontal Gauche Horizontal - + Left Vertical Gauche Vertical - + Right Vertical Droit Vertical - + Right Horizontal Droit Horizontal - + Aux. 1 - + Aux. 2 - - + + Unknown Inconnu - + Rud Dir - + Ele Prf - + Thr Gaz - + Ail @@ -2029,48 +2029,48 @@ Si vous avez un fichier de sauvegarde des paramètres, vous pouvez l'import Erreur de conversion du champ %1 - + Switch Interrupteur - + Switch L'interrupteur - + cannot be exported on this board! n'est pas supporté sur cette carte ! - + Source - + Source %1 cannot be exported on this board! La source %1 n'est pas supportée sur cette plateforme ! - + OpenTX only accepts %1 points in all curves OpenTX n'accepte que %1 points au maximum entre toutes les courbes - + OpenTx only accepts %1 points in all curves OpenTX n'accepte que %1 points au maximum entre toutes les courbes - + OpenTX on this board doesn't accept this function OpenTX ne supporte pas cette fonction sur cette carte - + OpenTX doesn't accept this radio protocol OpenTX ne supporte pas ce protocole radio @@ -2807,252 +2807,268 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Firmware - + Channel values displayed in us Positions de voies affichées en µs - + No OverrideCH functions available Désactive la fonction spéciale "Remplacer VOIExx" - + Possibility to enable FAI MODE (no telemetry) at field Possibilité d'activer le mode FAI (télémétrie désactivée) sur le terrain - + FAI MODE (no telemetry) always enabled Mode FAI (télémétrie toujours désactivée) - + Removes D8 FrSky protocol support which is not legal for use in the EU on radios sold after Jan 1st, 2015 Masque le protocole D8. Légalement obligatoire sur les radios Européennes importées après le 1er janvier 2015 - - + + Disable HELI menu and cyclic mix support Supprimer le menu HELICO et les mixages cycliques - - + + Disable Global variables Supprimer le support des variables globales - - + + Enable Lua custom scripts screen Activer l'écran des scripts Lua personnalisés - + Support for PPM internal module hack Support du remplacement du module interne par un module PPM - + Use alternative SQT5 font Utiliser la police alternative SQT5 - + Disable RAS (SWR) Désactiver le RAS (SWR). Utile uniquement pour les X9D+ avec un RAS/SWR non fonctionnel - + Pots use in menus navigation Support de la navigation dans les menus avec les POTS - + FrSky Taranis X9D+ - + FrSky Taranis X9D+ 2019 - + FrSky Taranis X9D - + Haptic module installed Module vibreur installé - + FrSky Taranis X9E - + Confirmation before radio shutdown Confirmation avant l'arrêt de la radio - + Horus gimbals installed (Hall sensors) Manches Horus à effet HALL installés - + FrSky Taranis X9-Lite - - + + + Support for auto update on boot Prise en charge de la mise à jour automatique au démarrage - + + FrSky Taranis X9-Lite S + + + + FrSky Taranis X7 / X7S - + FrSky Taranis X-Lite S/PRO - + FrSky Taranis X-Lite - + FrSky Horus X10 / X10S - - + + Support for ACCESS internal module replacement Prise en charge du module de remplacement interne ACCESS - + FrSky Horus X10 Express - + FrSky Horus X12S - + Use ONLY with first DEV pcb version Exclusivement pour les Horus DEV - + Jumper T12 - + Enable non certified R9M firmwares Activer les firmwares R9M non certifiés - + + Jumper T16 / T16+ + + + + + Support for MULTI internal module + Prise en charge du module MULTI interne + + + Turnigy 9XR-PRO - + Enable HELI menu and cyclic mix support Activer le menu hélico et les mixages CCPM - + Global variables Variables globales - + Enable non certified firmwares Activer les firmwares non certifiés - + In model setup menus automatically set source by moving the control Sélectionner les sources des mixeurs en bougeant le contrôle désiré - + In model setup menus automatically set switch by moving the control Sélectionner les interrupteurs en bougeant le contrôle désiré - + No graphical check boxes and sliders Pas de cases à cocher et de curseurs graphiques - + Battery graph Graphique de la batterie - + Don't use bold font for highlighting active items Ne pas mettre les lignes actives en gras - + Turnigy 9XR with m128 chip Turnigy 9XR avec une puce m128 - + Turnigy 9XR - + 9X with stock board 9X avec carte mère d'origine - + Enable resetting values by pressing up and down at the same time Permet la remise à zéro des valeurs en pressant haut-bas en même temps, valeur min avec gauche/bas, valeur max avec haut/droite, inversion avec gauche/droite - + 9X with stock board and m128 chip Carte 9x avec un chip m128 - + 9X with AR9X board 9X avec carte AR9X - + 9X with Sky9x board 9X avec carte Sky9x - + 9X with Gruvin9x board 9X avec carte Gruvin9x - + DIY MEGA2560 radio Radio DIY à base de MEGA2560 @@ -5018,7 +5034,7 @@ Cette fonction ne peut pas être désactivée sur la radio. Formulaire - + SQ @@ -5033,7 +5049,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + SP @@ -5053,7 +5069,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + SB @@ -5063,37 +5079,42 @@ Cette fonction ne peut pas être désactivée sur la radio. - + Antenna Antenne - + OFF Eteint - + S-Port Mirror Recopie S. Port - + Telemetry Télémetrie - + SBUS Trainer Écolage SBUS - + Debug Débogage - + + RTC Batt Check + Vérif Batterie RTC + + + S5 @@ -5108,17 +5129,17 @@ Cette fonction ne peut pas être désactivée sur la radio. - + S1 - + S2 - + S3 @@ -5128,12 +5149,12 @@ Cette fonction ne peut pas être désactivée sur la radio. - + Serial Port Port série - + v @@ -5153,7 +5174,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + SA @@ -5178,7 +5199,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + LS @@ -5188,7 +5209,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + Battery Offset Correction tension @@ -5198,12 +5219,12 @@ Cette fonction ne peut pas être désactivée sur la radio. - + SF - + SG @@ -5213,12 +5234,12 @@ Cette fonction ne peut pas être désactivée sur la radio. - + SI - + SJ @@ -5228,7 +5249,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + SL @@ -5243,7 +5264,7 @@ Cette fonction ne peut pas être désactivée sur la radio. - + RS2 @@ -6969,7 +6990,7 @@ Do you wish to continue? MdiChild - + Unable to find file %1! Fichier %1 introuvable ! @@ -7234,37 +7255,47 @@ Do you wish to continue? Impossible de dupliquer le modèle, aucun emplacement libre n’est disponible. - + + WARNING + ATTENTION + + + + <p>Due to the way Jumper have handled their JumperTX fork and firmware releases data integrity for settings from JumperTX cannot be trusted when migrating to OpenTX.</p> <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>En raison de la manière dont Jumper a traité ses versions de firmwares, l'intégrité des données pour les paramètres des radios Jumper n'est pas fiable lors de la migration vers OpenTX.</p> <p>L'importation des données des radios Jumper dans OpenTX 2.3 <b>n'est pas prise en charge et constitue un danger.</b></p> <p>Il ne nous est malheureusement pas possible de différencier les données des radios Jumper par rapport aux données légitimes des radios FrSky X10, mais <b> Vous ne devez continuer ici que si le fichier que vous avez ouvert provient d'une véritable radio FrSky X10.</b></p> <p>Voulez-vous vraiment continuer?</p> + + + Do you wish to continue with the conversion? Souhaitez-vous vraiment lancer la conversion ? - + Choose <i>Apply</i> to convert the file, or <i>Close</i> to close it without conversion. Choisissez <i>Appliquer</i> pour convertir le fichier ou <i>Annuler</i> pour le fermer sans conversion. - + <b>The conversion generated some important messages, please review them below.</b> <b>La conversion a généré des messages importants, veuillez les consulter ci-dessous.</b> - + Companion :: Conversion Result for %1 Companion :: Résultat de conversion de %1 - + Unable to find Horus radio SD card! Impossible de trouver la carte SD de la Horus ! - + Models and Settings written Modèle et paramètres écrit - + Cannot write temporary file! Ecriture de fichier temporaire impossible ! @@ -7274,14 +7305,14 @@ Do you wish to continue? Édition du modèle %1 : - + Error reading file %1: %2. Fichier %1 corrompu: %2. - + Error opening file %1: %2. Erreur à l'ouverture du fichier %1: @@ -7320,17 +7351,17 @@ Do you wish to continue? Nlle categorie - + <p><b>Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.</b></p> <p><b>Le type de radio actuellement sélectionné (%1) n'est pas compatible avec le fichier %3 (à partir de %2), les modèles et les paramètres doivent être convertis.</b></p> - + Open backup Models and Settings file Ouvrir la sauvegarde de paramètres et modèles - + Invalid binary backup File %1 Fichier de sauvegarde %1 invalide @@ -8866,12 +8897,12 @@ Mixage actif par défaut si non-renseigné. ModuleData - + Positive - + Negative Négative @@ -8952,37 +8983,37 @@ 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 @@ -9484,7 +9515,7 @@ Mixage actif par défaut si non-renseigné. DÉFAUT - + Custom - proto %1) Personnaliser - proto %1) @@ -9515,22 +9546,22 @@ Mixage actif par défaut si non-renseigné. OpenTxEepromInterface - + Unknown error Erreur inconnue - + ... plus %1 errors ... plus %1 erreurs - + Cannot write radio settings Impossible d'écrire les paramètres de la radio - + Cannot write model %1 Impossible d'écrire le modèle %1 @@ -10507,7 +10538,7 @@ E - + ??? @@ -10517,17 +10548,22 @@ E Un - + + Act + + + + ---- - + Telemetry Télémétrie - + SW @@ -10902,22 +10938,22 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo SetupPanel - + Timer %1 Chrono %1 - + THR GAZ - + Profile Settings Paramètres du profil - + SD structure path not specified or invalid Chemin de la structure SD non spécifié ou invalide @@ -11641,62 +11677,62 @@ La valeur par défaut est configurée dans le profil radio sélectionné.Simulateur Radio (%1) - + Could not determine startup data source. Impossible de déterminer les données source. - + Could not load data, possibly wrong format. Impossible de charger les données, mauvais format. - + Data Load Error Erreur de lecture des données - + Invalid startup data provided. Plese specify a proper file/path. Données de démarrage fournies non valides. Veuillez spécifier un fichier/chemin approprié. - + Simulator Startup Error Erreur de démarrage du simulateur - + Error saving data: could open file for writing: '%1' Erreur de sauvegarde des données: impossible d'écrire le fichier '%1' - + Error saving data: could not get data from simulator interface. Erreur de sauvegarde des données: impossible de récupérer les données depuis l'interface de simulation. - + An unexpected error occurred while attempting to save radio data to file '%1'. Une erreur inattendue s'est produite lors de l'enregistrement des données radio dans le fichier '%1'. - + Data Save Error Erreur de sauvegarde des données - + Cannot open joystick, joystick disabled Impossible d'accéder au Joystick, Joystick désactivé - + Radio firmware error: %1 Erreur firmware radio: %1 - + - Flight Mode %1 (#%2) - Phase de Vol %1 (#%2) From 2380a7c8d3c2a019d88f8aa5217651c0aa0385a8 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 21:32:55 +0200 Subject: [PATCH 181/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index f88c86e05..7bcdc8b73 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1603,3 +1603,4 @@ Mike Sedgwick William Goodrich Marcel Schäfer Joseph Santa Cruz +Gerald Roedel From 10218b24152284632bec9ca4e0c433187f5ed9ee Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 14 Oct 2019 21:33:22 +0200 Subject: [PATCH 182/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 7bcdc8b73..bd18f6159 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1604,3 +1604,4 @@ William Goodrich Marcel Schäfer Joseph Santa Cruz Gerald Roedel +James D McKeown From c8eaf565e1e6fea9b3c7dee64eba3ecec07b1eba Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 15 Oct 2019 21:33:49 +0200 Subject: [PATCH 183/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index bd18f6159..dfe11e0d8 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1605,3 +1605,4 @@ Marcel Schäfer Joseph Santa Cruz Gerald Roedel James D McKeown +鄭 淳中 From ecc5e7553bc93416d0e5fc71272fe2b0b7df56de Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 16 Oct 2019 10:39:17 +0200 Subject: [PATCH 184/257] Companion : fix channel numbers (#6950) Channels count fix --- companion/src/modeledit/setup.cpp | 52 +++++++++++++++++++++++++++---- companion/src/modeledit/setup.h | 1 + 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 270e9b87b..2cc34455b 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -366,6 +366,48 @@ void ModulePanel::setupFailsafes() lock = false; } +int ModulePanel::getMaxChannelCount() +{ + const PulsesProtocol protocol = (PulsesProtocol)module.protocol; + switch (protocol) { + case PULSES_ACCESS_ISRM: + return 24; + case PULSES_PXX_R9M: + case PULSES_ACCESS_R9M: + case PULSES_ACCESS_R9M_LITE: + case PULSES_ACCESS_R9M_LITE_PRO: + case PULSES_ACCST_ISRM_D16: + case PULSES_XJT_LITE_X16: + case PULSES_PXX_XJT_X16: + case PULSES_CROSSFIRE: + case PULSES_SBUS: + return 16; + case PULSES_XJT_LITE_LR12: + case PULSES_PXX_XJT_LR12: + return 12; + case PULSES_PXX_DJT: + case PULSES_XJT_LITE_D8: + case PULSES_PXX_XJT_D8: + case PULSES_PPM: + return 8; + case PULSES_LP45: + case PULSES_DSM2: + case PULSES_DSMX: + return 6; + case PULSES_MULTIMODULE: + if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2) + return 6; + else + return 16; + break; + case PULSES_OFF: + break; + default: + break; + } + return 8; +} + void ModulePanel::update() { const PulsesProtocol protocol = (PulsesProtocol)module.protocol; @@ -464,10 +506,12 @@ void ModulePanel::update() ui->rxNumber->setValue(module.modelId); ui->label_channelsStart->setVisible(mask & MASK_CHANNELS_RANGE); ui->channelsStart->setVisible(mask & MASK_CHANNELS_RANGE); + ui->channelsStart->setMaximum(33 - module.channelsCount); ui->channelsStart->setValue(module.channelsStart+1); ui->label_channelsCount->setVisible(mask & MASK_CHANNELS_RANGE); ui->channelsCount->setVisible(mask & MASK_CHANNELS_RANGE); ui->channelsCount->setEnabled(mask & MASK_CHANNELS_COUNT); + ui->channelsCount->setMaximum(getMaxChannelCount()); ui->channelsCount->setValue(module.channelsCount); ui->channelsCount->setSingleStep(firmware->getCapability(HasPPMStart) ? 1 : 2); @@ -483,7 +527,7 @@ void ModulePanel::update() ui->ppmDelay->setValue(module.ppm.delay); ui->label_ppmFrameLength->setVisible(mask & MASK_SBUSPPM_FIELDS); ui->ppmFrameLength->setVisible(mask & MASK_SBUSPPM_FIELDS); - ui->ppmFrameLength->setMinimum(module.channelsCount*(model->extendedLimits ? 2.250 : 2)+3.5); + ui->ppmFrameLength->setMinimum(module.channelsCount * (model->extendedLimits ? 2.250 : 2)+3.5); ui->ppmFrameLength->setMaximum(firmware->getCapability(PPMFrameLength)); ui->ppmFrameLength->setValue(22.5+((double)module.ppm.frameLength)*0.5); @@ -612,11 +656,6 @@ void ModulePanel::update() } } } - - if (mask & MASK_CHANNELS_RANGE) { - ui->channelsStart->setMaximum(33 - ui->channelsCount->value()); - ui->channelsCount->setMaximum(qMin(24, 33-ui->channelsStart->value())); - } } void ModulePanel::on_trainerMode_currentIndexChanged(int index) @@ -632,6 +671,7 @@ void ModulePanel::onProtocolChanged(int index) { if (!lock && module.protocol != ui->protocol->itemData(index).toUInt()) { module.protocol = ui->protocol->itemData(index).toInt(); + module.channelsCount = getMaxChannelCount(); update(); emit modified(); } diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index fc1a57cf7..3edb1efd8 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -71,6 +71,7 @@ class ModulePanel : public ModelPanel void channelsRangeChanged(); private slots: + int getMaxChannelCount(); void setupFailsafes(); void on_trainerMode_currentIndexChanged(int index); void onProtocolChanged(int index); From a173dd0adf0f82f6d390ab6dedbda9dff9b73d01 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 16 Oct 2019 10:42:52 +0200 Subject: [PATCH 185/257] Display rxnum in modellist only when needed (#6951) Fix #6926 --- companion/src/firmwares/moduledata.cpp | 21 +++++++++++++++++++++ companion/src/firmwares/moduledata.h | 1 + companion/src/modelslist.cpp | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index e09724b48..8b9b08c2f 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -57,6 +57,27 @@ bool ModuleData::isPxx1Module() const } } +bool ModuleData::supportRxNum() const +{ + switch (protocol) { + case PULSES_PXX_XJT_X16: + case PULSES_PXX_R9M: + case PULSES_PXX_R9M_LITE: + case PULSES_PXX_R9M_LITE_PRO: + case PULSES_MULTIMODULE: + case PULSES_ACCESS_ISRM: + case PULSES_ACCST_ISRM_D16: + case PULSES_ACCESS_R9M: + case PULSES_ACCESS_R9M_LITE: + case PULSES_ACCESS_R9M_LITE_PRO: + case PULSES_XJT_LITE_X16: + case PULSES_XJT_LITE_LR12: + case PULSES_PXX_XJT_LR12: + return true; + default: + return false; + } +} QString ModuleData::rfProtocolToString() const { diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index 4e05e2120..8f3f8cd53 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -186,6 +186,7 @@ class 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; QString subTypeToString(int type = -1) const; diff --git a/companion/src/modelslist.cpp b/companion/src/modelslist.cpp index 50950872c..2fb5cc329 100644 --- a/companion/src/modelslist.cpp +++ b/companion/src/modelslist.cpp @@ -727,7 +727,7 @@ void TreeModel::refresh() protocol = moduleData.protocol; // These are the only RXs that allow nominating RX # but changing RX or copying models can leave residual configuration which can cause issues // if (protocol == PULSES_PXX_XJT_X16 || protocol == PULSES_PXX_XJT_LR12 || protocol == PULSES_PXX_R9M || protocol == PULSES_DSMX || protocol == PULSES_MULTIMODULE) { - if ((protocol != PULSES_OFF && protocol != PULSES_PXX_XJT_D8 ) && moduleData.modelId > 0) { + if (moduleData.supportRxNum() && moduleData.modelId > 0) { if (!rxs.isEmpty()) { rxs.append(", "); } From 26dda3070d71cd662af215635d3135b7e6bcb9cc Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 16 Oct 2019 10:56:22 +0200 Subject: [PATCH 186/257] Add autoupdate to X10E and x9d 2019, they have PMU chip .... (#6942) OK so no choice :( --- companion/src/firmwares/opentx/opentxinterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 16ce23b07..d3b44798a 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -1222,7 +1222,7 @@ void registerOpenTxFirmwares() /* FrSky Taranis X9D+ 2019 board */ firmware = new OpenTxFirmware("opentx-x9d+2019", Firmware::tr("FrSky Taranis X9D+ 2019"), BOARD_TARANIS_X9DP_2019); addOpenTxTaranisOptions(firmware); - addPPMInternalModuleHack(firmware); + firmware->addOption("autoupdate", Firmware::tr("Support for auto update on boot")); registerOpenTxFirmware(firmware); /* FrSky Taranis X9D board */ @@ -1278,6 +1278,7 @@ void registerOpenTxFirmwares() /* FrSky X10 Express board */ firmware = new OpenTxFirmware("opentx-x10express", Firmware::tr("FrSky Horus X10 Express"), BOARD_X10_EXPRESS); addOpenTxFrskyOptions(firmware); + firmware->addOption("autoupdate", Firmware::tr("Support for auto update on boot")); registerOpenTxFirmware(firmware); /* FrSky X12 (Horus) board */ From f1d8083064764b76db2c21c9332fe4f143b6a0b5 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 16 Oct 2019 14:29:17 +0200 Subject: [PATCH 187/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index dfe11e0d8..e760eb3c7 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1606,3 +1606,4 @@ Joseph Santa Cruz Gerald Roedel James D McKeown 鄭 淳中 +Matthias Wuethrich From aaafe445db2f3c510114ea796457090711becfcc Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 16 Oct 2019 15:29:10 +0200 Subject: [PATCH 188/257] Added support for flashing AVR multi on horus targets (#6888) * Added support for flashing AVR multi on horus targets taranis soft serial Added support for flashing AVR multi on horus targets taranis soft serial * Added support for multi V2 signature (hex code) * Check multi signature before flashing * small clean-up * Cosmetics * Fix v2 signature check * Cosmetics --- .../src/gui/common/stdlcd/radio_sdmanager.cpp | 2 + radio/src/io/multi_firmware_update.cpp | 231 +++++++++++++----- radio/src/io/multi_firmware_update.h | 20 +- .../common/arm/stm32/heartbeat_driver.cpp | 3 + .../arm/stm32/rotary_encoder_driver.cpp | 4 + radio/src/targets/horus/board.cpp | 1 + radio/src/targets/horus/board.h | 3 + radio/src/targets/horus/hal.h | 10 + radio/src/targets/horus/telemetry_driver.cpp | 129 +++++++++- radio/src/targets/taranis/board.h | 5 + radio/src/targets/taranis/hal.h | 17 ++ .../src/targets/taranis/telemetry_driver.cpp | 151 +++++++++++- radio/src/trainer.h | 1 + radio/src/translations.cpp | 3 + radio/src/translations.h | 3 + radio/src/translations/cz.h.txt | 3 + radio/src/translations/de.h.txt | 5 +- radio/src/translations/en.h.txt | 3 + radio/src/translations/es.h.txt | 5 +- radio/src/translations/fi.h.txt | 5 +- radio/src/translations/fr.h.txt | 3 + radio/src/translations/it.h.txt | 5 +- radio/src/translations/nl.h.txt | 5 +- radio/src/translations/pl.h.txt | 5 +- radio/src/translations/pt.h.txt | 5 +- radio/src/translations/se.h.txt | 5 +- 26 files changed, 544 insertions(+), 88 deletions(-) diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp index d15c1243c..88bfea658 100644 --- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp +++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp @@ -220,6 +220,7 @@ void onSdManagerMenu(const char * result) FrskyDeviceFirmwareUpdate device(SPORT_MODULE); device.flashFirmware(lfn); } +#if defined(MULTIMODULE) #if defined(INTERNAL_MODULE_MULTI) else if (result == STR_FLASH_INTERNAL_MULTI) { getSelectionFullPath(lfn); @@ -230,6 +231,7 @@ void onSdManagerMenu(const char * result) getSelectionFullPath(lfn); multiFlashFirmware(EXTERNAL_MODULE, lfn); } +#endif #if defined(BLUETOOTH) else if (result == STR_FLASH_BLUETOOTH_MODULE) { getSelectionFullPath(lfn); diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index dcc6d6e7b..bf5ca4105 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -26,8 +26,6 @@ #define UPDATE_MULTI_EXT_BIN ".bin" -//#define DEBUG_EXT_MODULE_FLASH - class MultiFirmwareUpdateDriver { public: @@ -39,6 +37,7 @@ class MultiFirmwareUpdateDriver virtual bool getByte(uint8_t& byte) const = 0; virtual void sendByte(uint8_t byte) const = 0; virtual void clear() const = 0; + virtual void deinit() const {} private: bool getRxByte(uint8_t& byte) const; @@ -47,6 +46,7 @@ class MultiFirmwareUpdateDriver const char * getDeviceSignature(uint8_t* signature) const; const char * loadAddress(uint32_t offset) const; const char * progPage(uint8_t* buffer, uint16_t size) const; + void leaveProgMode() const; }; #if defined(INTERNAL_MODULE_MULTI) @@ -77,16 +77,21 @@ class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver { intmoduleFifo.clear(); } + + void deinit() const override + { + clear(); + } }; static const MultiInternalUpdateDriver multiInternalUpdateDriver; #endif -class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver +class MultiExternalSoftSerialUpdateDriver: public MultiFirmwareUpdateDriver { public: - MultiExternalUpdateDriver() = default; + MultiExternalSoftSerialUpdateDriver() = default; protected: void init() const override @@ -102,7 +107,7 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver #endif EXTERNAL_MODULE_ON(); - telemetryPortInit(57600, TELEMETRY_SERIAL_DEFAULT); + telemetryPortInvertedInit(57600); } bool getByte(uint8_t& byte) const override @@ -119,9 +124,15 @@ class MultiExternalUpdateDriver: public MultiFirmwareUpdateDriver { telemetryClearFifo(); } + + void deinit() const override + { + telemetryPortInvertedInit(0); + clear(); + } }; -static const MultiExternalUpdateDriver multiExternalUpdateDriver; +static const MultiExternalSoftSerialUpdateDriver multiExternalSoftSerialUpdateDriver; bool MultiFirmwareUpdateDriver::getRxByte(uint8_t& byte) const { @@ -150,10 +161,10 @@ bool MultiFirmwareUpdateDriver::checkRxByte(uint8_t byte) const const char * MultiFirmwareUpdateDriver::waitForInitialSync() const { - clear(); - uint8_t byte; int retries = 1000; + + clear(); do { // Send sync request sendByte(STK_GET_SYNC); @@ -214,16 +225,14 @@ const char * MultiFirmwareUpdateDriver::loadAddress(uint32_t offset) const const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size) const { sendByte(STK_PROG_PAGE); - // page size 256 - sendByte(1); - sendByte(0); + + // page size + sendByte(size >> 8); + sendByte(size & 0xFF); + // flash/eeprom flag sendByte(0); - // #if defined(DEBUG_EXT_MODULE_FLASH) - // TRACE("writing at 0x%X", writeOffset << 1); - // #endif - for (uint16_t i=0; i < size; i++) { sendByte(buffer[i]); } @@ -245,6 +254,16 @@ const char * MultiFirmwareUpdateDriver::progPage(uint8_t* buffer, uint16_t size) return nullptr; } +void MultiFirmwareUpdateDriver::leaveProgMode() const +{ + sendByte(STK_LEAVE_PROGMODE); + sendByte(CRC_EOP); + + // eat last sync byte + checkRxByte(STK_INSYNC); + deinit(); +} + const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* label) const { const char* result = nullptr; @@ -255,24 +274,39 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab RTOS_WAIT_MS(500); result = waitForInitialSync(); - if (result != nullptr) + if (result) { + leaveProgMode(); return result; + } unsigned char signature[4]; // 3 bytes signature + STK_OK result = getDeviceSignature(signature); - if (result != nullptr) + if (result) { + leaveProgMode(); return result; + } - uint8_t buffer[256]; // page size = 256 - uint32_t writeOffset = 0x1000; // start offset (word address) + uint8_t buffer[256]; + uint16_t pageSize = 128; + uint32_t writeOffset = 0; + + if (signature[0] != 0x1E) { + leaveProgMode(); + return "Wrong signature"; + } + + if (signature[1] == 0x55 && signature[2] == 0xAA) { + pageSize = 256; + writeOffset = 0x1000; // start offset (word address) + } while (!f_eof(file)) { drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize); UINT count=0; - memclear(buffer, 256); - if (f_read(file, buffer, 256, &count) != FR_OK) { + memclear(buffer, pageSize); + if (f_read(file, buffer, pageSize, &count) != FR_OK) { result = "Error reading file"; break; } @@ -283,28 +317,23 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab clear(); result = loadAddress(writeOffset); - if (result != nullptr) { + if (result) { break; } - result = progPage(buffer, 256); - if (result != nullptr) { + result = progPage(buffer, pageSize); + if (result) { break; } - writeOffset += 128; // page / 2 + writeOffset += pageSize / 2; } if (f_eof(file)) { drawProgressScreen(label, STR_WRITING, file->fptr, file->obj.objsize); } - sendByte(STK_LEAVE_PROGMODE); - sendByte(CRC_EOP); - - // eat last sync byte - checkRxByte(STK_INSYNC); - + leaveProgMode(); return result; } @@ -316,19 +345,9 @@ const char * MultiFirmwareUpdateDriver::flashFirmware(FIL* file, const char* lab #define MULTI_SIGN_TELEM_INVERSION_OFFSET 13 #define MULTI_SIGN_VERSION_OFFSET 15 -const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename) +const char * MultiFirmwareInformation::readV1Signature(const char * buffer) { - FIL file; - f_open(&file, filename, FA_READ); - char buffer[MULTI_SIGN_SIZE]; - UINT count; - - f_lseek(&file, f_size(&file) - MULTI_SIGN_SIZE); - if (f_read(&file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) { - return "Error reading file"; - } - - if(!memcmp(buffer, "multi-stm", 9)) + if (!memcmp(buffer, "multi-stm", 9)) boardType = FIRMWARE_MULTI_STM; else if (!memcmp(buffer, "multi-avr", 9)) boardType = FIRMWARE_MULTI_AVR; @@ -348,9 +367,9 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * bootloaderCheck = false; if(buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 't') - telemetryType = FIRMWARE_MULTI_TELEM_MULTI; + telemetryType = FIRMWARE_MULTI_TELEM_MULTI_STATUS; else if (buffer[MULTI_SIGN_TELEM_TYPE_OFFSET] == 's') - telemetryType = FIRMWARE_MULTI_TELEM_STATUS; + telemetryType = FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY; else telemetryType = FIRMWARE_MULTI_TELEM_NONE; @@ -362,23 +381,115 @@ const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * return nullptr; } +const char * MultiFirmwareInformation::readV2Signature(const char * buffer) +{ + // new format + uint32_t options = 0; + const char * beg = buffer + 7; + const char * cursor = beg; + while (cursor - beg < 8) { + options <<= 4; + if (*cursor >= '0' && *cursor <= '9') + options |= *cursor - '0'; + else if (*cursor >= 'a' && *cursor <= 'f') + options |= *cursor - 'a' + 10; + else if (*cursor >= 'A' && *cursor <= 'F') + options |= *cursor - 'A' + 10; + else + break; // should be '-' + cursor++; + } + if (cursor - beg < 8) + return "Invalid signature"; -const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename) + boardType = options & 0x3; + optibootSupport = options & 0x80 ? true : false; + telemetryInversion = options & 0x200 ? true : false; + bootloaderCheck = options & 0x100 ? true : false; + + telemetryType = FIRMWARE_MULTI_TELEM_NONE; + if (options & 0x400) + telemetryType = FIRMWARE_MULTI_TELEM_MULTI_STATUS; + if (options & 0x800) + telemetryType = FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY; + + return nullptr; +} + +const char * MultiFirmwareInformation::readMultiFirmwareInformation(const char * filename) { FIL file; - const char * result = nullptr; + if (f_open(&file, filename, FA_READ) != FR_OK) + return "Error opening file"; - const char * ext = getFileExtension(filename); - if (ext && strcasecmp(ext, UPDATE_MULTI_EXT_BIN)) { - return "Wrong file extension"; + const char * err = readMultiFirmwareInformation(&file); + f_close(&file); + + return err; +} + +const char * MultiFirmwareInformation::readMultiFirmwareInformation(FIL * file) +{ + char buffer[MULTI_SIGN_SIZE]; + UINT count; + + if (f_size(file) < MULTI_SIGN_SIZE) + return "File too small"; + + f_lseek(file, f_size(file) - MULTI_SIGN_SIZE); + if (f_read(file, buffer, MULTI_SIGN_SIZE, &count) != FR_OK || count != MULTI_SIGN_SIZE) { + return "Error reading file"; } + if (!memcmp(buffer, "multi-x", 7)) { + return readV2Signature(buffer); + } + + return readV1Signature(buffer); +} + +bool multiFlashFirmware(uint8_t moduleIdx, const char * filename) +{ + FIL file; + if (f_open(&file, filename, FA_READ) != FR_OK) { - return "Error opening file"; + POPUP_WARNING("Not a valid file"); + return false; } + MultiFirmwareInformation firmwareFile; + if (firmwareFile.readMultiFirmwareInformation(&file)) { + f_close(&file); + POPUP_WARNING("Not a valid file"); + return false; + } + f_lseek(&file, 0); + + if (moduleIdx == EXTERNAL_MODULE) { + if (!firmwareFile.isMultiExternalFirmware()) { + f_close(&file); + POPUP_WARNING(STR_NEEDS_FILE); + SET_WARNING_INFO(STR_EXT_MULTI_SPEC, strlen(STR_EXT_MULTI_SPEC), 0); + return false; + } + } + else { + if (!firmwareFile.isMultiInternalFirmware()) { + f_close(&file); + POPUP_WARNING(STR_NEEDS_FILE); + SET_WARNING_INFO(STR_INT_MULTI_SPEC, strlen(STR_INT_MULTI_SPEC), 0); + return false; + } + } + + const MultiFirmwareUpdateDriver* driver = &multiExternalSoftSerialUpdateDriver; +#if defined(INTERNAL_MODULE_MULTI) + if (moduleIdx == INTERNAL_MODULE) + driver = &multiInternalUpdateDriver; +#endif + pausePulses(); #if defined(INTERNAL_MODULE_MULTI) @@ -397,14 +508,7 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename) watchdogSuspend(2000); RTOS_WAIT_MS(2000); - // TODO: real update here - const MultiFirmwareUpdateDriver* driver = &multiExternalUpdateDriver; -#if defined(INTERNAL_MODULE_MULTI) - if (moduleIdx == INTERNAL_MODULE) - driver = &multiInternalUpdateDriver; -#endif - - result = driver->flashFirmware(&file, getBasename(filename)); + const char * result = driver->flashFirmware(&file, getBasename(filename)); f_close(&file); AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1 ); @@ -425,8 +529,10 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename) /* wait 2s off */ watchdogSuspend(2000); RTOS_WAIT_MS(2000); - telemetryClearFifo(); + // reset telemetry protocol + telemetryInit(255); + #if defined(INTERNAL_MODULE_MULTI) if (intPwr) { INTERNAL_MODULE_ON(); @@ -439,9 +545,8 @@ const char * multiFlashFirmware(uint8_t moduleIdx, const char * filename) setupPulsesExternalModule(); } - //state = SPORT_IDLE; resumePulses(); - return result; + return result == nullptr; } -#endif \ No newline at end of file +#endif diff --git a/radio/src/io/multi_firmware_update.h b/radio/src/io/multi_firmware_update.h index 45c6f8e91..6713d5cfb 100644 --- a/radio/src/io/multi_firmware_update.h +++ b/radio/src/io/multi_firmware_update.h @@ -21,6 +21,8 @@ #ifndef OPENTX_MULTI_FIRMWARE_H #define OPENTX_MULTI_FIRMWARE_H +#include "ff.h" + /* Signature format is multi-[board type]-[bootloader support][check for bootloader][multi telemetry type][telemetry inversion][debug]-[firmware version] Where: [board type] is avr, stm, or orx @@ -36,15 +38,15 @@ class MultiFirmwareInformation { public: enum MultiFirmwareBoardType { + FIRMWARE_MULTI_AVR = 0, FIRMWARE_MULTI_STM, - FIRMWARE_MULTI_AVR, FIRMWARE_MULTI_ORX, }; enum MultiFirmwareTelemetryType { - FIRMWARE_MULTI_TELEM_MULTI, - FIRMWARE_MULTI_TELEM_STATUS, - FIRMWARE_MULTI_TELEM_NONE, + FIRMWARE_MULTI_TELEM_NONE = 0, + FIRMWARE_MULTI_TELEM_MULTI_STATUS, // erSkyTX + FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY, // OpenTX }; bool isMultiStmFirmware() const @@ -69,15 +71,16 @@ class MultiFirmwareInformation { bool isMultiInternalFirmware() const { - return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == false && optibootSupport == true && telemetryType == FIRMWARE_MULTI_TELEM_STATUS); + return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == false && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY); } bool isMultiExternalFirmware() const { - return (telemetryInversion == false && optibootSupport == true && telemetryType == FIRMWARE_MULTI_TELEM_STATUS); + return (boardType == FIRMWARE_MULTI_STM && telemetryInversion == true && optibootSupport == true && bootloaderCheck == true && telemetryType == FIRMWARE_MULTI_TELEM_MULTI_TELEMETRY); } const char * readMultiFirmwareInformation(const char * filename); + const char * readMultiFirmwareInformation(FIL * file); private: uint8_t boardType; @@ -89,8 +92,11 @@ class MultiFirmwareInformation { uint8_t firmwareVersionMinor; uint8_t firmwareVersionRevision; uint8_t firmwareVersionSubRevision; + + const char * readV1Signature(const char * buffer); + const char * readV2Signature(const char * buffer); }; -const char* multiFlashFirmware(uint8_t module, const char * filename); +bool multiFlashFirmware(uint8_t module, const char * filename); #endif //OPENTX_MULTI_FIRMWARE_H diff --git a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp index 926c05c63..70ce2b394 100644 --- a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp +++ b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp @@ -83,5 +83,8 @@ void check_intmodule_heartbeat() extern "C" void INTMODULE_HEARTBEAT_EXTI_IRQHandler() { check_intmodule_heartbeat(); + #if defined(TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT) + check_telemetry_exti(); + #endif } #endif diff --git a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp index 758043c3a..f43090f04 100644 --- a/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp +++ b/radio/src/targets/common/arm/stm32/rotary_encoder_driver.cpp @@ -133,6 +133,10 @@ extern "C" void ROTARY_ENCODER_EXTI_IRQHandler1(void) #if !defined(BOOT) && defined(INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER) check_intmodule_heartbeat(); #endif + +#if !defined(BOOT) && defined(TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER) + check_telemetry_exti(); +#endif } #if defined(ROTARY_ENCODER_EXTI_IRQn2) diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 0ec6e9746..db0c28416 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -120,6 +120,7 @@ void boardInit() HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph | EXTMODULE_RCC_APB2Periph | + TELEMETRY_RCC_APB2Periph | BT_RCC_APB2Periph | BACKLIGHT_RCC_APB2Periph, ENABLE); diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index c9d72c8ab..1ac470fa3 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -568,6 +568,9 @@ bool telemetryGetByte(uint8_t * byte); void telemetryClearFifo(); extern uint32_t telemetryErrors; +// soft-serial +void telemetryPortInvertedInit(uint32_t baudrate); + // Sport update driver #if defined(PCBX10) && !defined(RADIO_T16) void sportUpdatePowerOn(); diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 0df645d4b..e7afa6ddb 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -365,6 +365,7 @@ // Telemetry #define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1) #define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2 +#define TELEMETRY_RCC_APB2Periph RCC_APB2Periph_TIM10 #define TELEMETRY_DIR_GPIO GPIOD #define TELEMETRY_DIR_GPIO_PIN GPIO_Pin_4 // PD.04 #define TELEMETRY_GPIO GPIOD @@ -374,6 +375,15 @@ #define TELEMETRY_GPIO_PinSource_RX GPIO_PinSource6 #define TELEMETRY_GPIO_AF GPIO_AF_USART2 #define TELEMETRY_USART USART2 +#define TELEMETRY_EXTI_PortSource EXTI_PortSourceGPIOD +#define TELEMETRY_EXTI_PinSource EXTI_PinSource6 +#define TELEMETRY_EXTI_LINE EXTI_Line6 +#define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn +#define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler +#define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising +#define TELEMETRY_TIMER TIM11 +#define TELEMETRY_TIMER_IRQn TIM1_TRG_COM_TIM11_IRQn +#define TELEMETRY_TIMER_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler #if defined(PCBX12S) #define TELEMETRY_DMA_Stream_RX DMA1_Stream5 #define TELEMETRY_DMA_Channel_RX DMA_Channel_4 diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp index 2ca7c6c0a..fe143cfe2 100644 --- a/radio/src/targets/horus/telemetry_driver.cpp +++ b/radio/src/targets/horus/telemetry_driver.cpp @@ -28,6 +28,17 @@ DMAFifo telemetryDMAFifo __DMA (TELEMETRY_DMA_Stream_RX); uint8_t telemetryFifoMode; #endif +static void telemetryInitDirPin() +{ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN; + GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure); + GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN); +} + void telemetryPortInit(uint32_t baudrate, uint8_t mode) { if (baudrate == 0) { @@ -55,11 +66,7 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure); - GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN); + telemetryInitDirPin(); USART_InitStructure.USART_BaudRate = baudrate; if (mode & TELEMETRY_SERIAL_8E2) { @@ -126,6 +133,95 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) #endif } +// soft serial vars +static uint8_t rxBitCount; +static uint8_t rxByte; + +void telemetryPortInvertedInit(uint32_t baudrate) +{ + if (baudrate == 0) { + NVIC_DisableIRQ(TELEMETRY_EXTI_IRQn); + NVIC_DisableIRQ(TELEMETRY_TIMER_IRQn); + + EXTI_InitTypeDef EXTI_InitStructure; + EXTI_StructInit(&EXTI_InitStructure); + EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER; + EXTI_InitStructure.EXTI_LineCmd = DISABLE; + EXTI_Init(&EXTI_InitStructure); + return; + } + + rxBitCount = 0; + + // configure bit sample timer + RCC->APB2ENR |= RCC_APB2ENR_TIM11EN; + TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS + TELEMETRY_TIMER->CCER = 0; + TELEMETRY_TIMER->CCMR1 = 0; + TELEMETRY_TIMER->CR1 = TIM_CR1_CEN; + TELEMETRY_TIMER->DIER = TIM_DIER_UIE; + + NVIC_SetPriority(TELEMETRY_TIMER_IRQn, 0); + NVIC_EnableIRQ(TELEMETRY_TIMER_IRQn); + + // init TELEMETRY_RX_GPIO_PIN + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_InitStructure.GPIO_Pin = TELEMETRY_RX_GPIO_PIN; + GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure); + + telemetryInitDirPin(); + + // Connect EXTI line to TELEMETRY RX pin + SYSCFG_EXTILineConfig(TELEMETRY_EXTI_PortSource, TELEMETRY_EXTI_PinSource); + + // Configure EXTI for raising edge (start bit) + EXTI_InitTypeDef EXTI_InitStructure; + EXTI_StructInit(&EXTI_InitStructure); + EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + NVIC_SetPriority(TELEMETRY_EXTI_IRQn, 0); + NVIC_EnableIRQ(TELEMETRY_EXTI_IRQn); +} + +void telemetryPortInvertedRxBit() +{ + if (rxBitCount < 8) { + if (rxBitCount == 0) { + TELEMETRY_TIMER->ARR = 34; + rxByte = 0; + } + else { + rxByte >>= 1; + } + + if (GPIO_ReadInputDataBit(TELEMETRY_GPIO, TELEMETRY_RX_GPIO_PIN) == Bit_RESET) + rxByte |= 0x80; + + ++rxBitCount; + } + else if (rxBitCount == 8) { + + telemetryNoDMAFifo.push(rxByte); + rxBitCount = 0; + + // disable timer + TELEMETRY_TIMER->CR1 &= ~TIM_CR1_CEN; + + // re-enable start bit interrupt + EXTI->IMR |= EXTI_IMR_MR6; + } +} + void telemetryPortSetDirectionOutput() { TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable @@ -253,6 +349,29 @@ extern "C" void TELEMETRY_USART_IRQHandler(void) } } +extern "C" void TELEMETRY_EXTI_IRQHandler(void) +{ + if (EXTI_GetITStatus(TELEMETRY_EXTI_LINE) != RESET) { + + if (rxBitCount == 0) { + + TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps + TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN; + + // disable start bit interrupt + EXTI->IMR &= ~EXTI_IMR_MR6; + } + + EXTI_ClearITPendingBit(TELEMETRY_EXTI_LINE); + } +} + +extern "C" void TELEMETRY_TIMER_IRQHandler() +{ + TELEMETRY_TIMER->SR &= ~TIM_SR_UIF; + telemetryPortInvertedRxBit(); +} + // TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp bool telemetryGetByte(uint8_t * byte) { diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 903d3a19b..e21267199 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -192,6 +192,8 @@ void check_intmodule_heartbeat(); #define check_intmodule_heartbeat() #endif +void check_telemetry_exti(); + // SBUS int sbusGetByte(uint8_t * byte); @@ -680,6 +682,9 @@ bool telemetryGetByte(uint8_t * byte); void telemetryClearFifo(); extern uint32_t telemetryErrors; +// soft-serial +void telemetryPortInvertedInit(uint32_t baudrate); + // PCBREV driver #if defined(PCBX7) #define IS_PCBREV_40() (GPIO_ReadInputDataBit(PCBREV_GPIO, PCBREV_GPIO_PIN) == Bit_SET) diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 4a0bb49d7..53cc66618 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -1284,6 +1284,23 @@ #define TELEMETRY_DMA_TX_FLAG_TC DMA_IT_TCIF6 #define TELEMETRY_USART_IRQHandler USART2_IRQHandler #define TELEMETRY_USART_IRQn USART2_IRQn +#define TELEMETRY_EXTI_PortSource EXTI_PortSourceGPIOD +#define TELEMETRY_EXTI_PinSource EXTI_PinSource6 +#define TELEMETRY_EXTI_LINE EXTI_Line6 +#define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn +#define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising + +#if defined(RADIO_X7) + #define TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER +#elif defined(PCBXLITE) || defined(PCBX9LITE) || (defined(PCBX9DP) && PCBREV >= 2019) + #define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler +#else + #define TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT +#endif + +#define TELEMETRY_TIMER TIM11 +#define TELEMETRY_TIMER_IRQn TIM1_TRG_COM_TIM11_IRQn +#define TELEMETRY_TIMER_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler // PCBREV #if defined(PCBX7) diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp index b439dc906..3c9618f03 100644 --- a/radio/src/targets/taranis/telemetry_driver.cpp +++ b/radio/src/targets/taranis/telemetry_driver.cpp @@ -23,6 +23,17 @@ Fifo telemetryFifo; uint32_t telemetryErrors = 0; +static void telemetryInitDirPin() +{ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN; + GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure); + TELEMETRY_DIR_INPUT(); +} + void telemetryPortInit(uint32_t baudrate, uint8_t mode) { if (baudrate == 0) { @@ -48,11 +59,7 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure); - TELEMETRY_DIR_INPUT(); + telemetryInitDirPin(); USART_DeInit(TELEMETRY_USART); USART_InitTypeDef USART_InitStructure; @@ -77,6 +84,110 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode) NVIC_EnableIRQ(TELEMETRY_USART_IRQn); } +// soft serial vars +static uint8_t rxBitCount; +static uint8_t rxByte; + +//TODO: +// - only 57600 supported for now +// - handle other bitrates as well? +// +void telemetryPortInvertedInit(uint32_t baudrate) +{ + if (baudrate == 0) { + + //TODO: + // - handle conflict with HEARTBEAT disabled for trainer input... + // - probably need to stop trainer input/output and restore after this is closed +#if !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER) && !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT) + NVIC_DisableIRQ(TELEMETRY_EXTI_IRQn); +#endif + NVIC_DisableIRQ(TELEMETRY_TIMER_IRQn); + + EXTI_InitTypeDef EXTI_InitStructure; + EXTI_StructInit(&EXTI_InitStructure); + EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER; + EXTI_InitStructure.EXTI_LineCmd = DISABLE; + EXTI_Init(&EXTI_InitStructure); + return; + } + + rxBitCount = 0; + + // configure bit sample timer + RCC->APB2ENR |= RCC_APB2ENR_TIM11EN; + TELEMETRY_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1; // 0.5uS + TELEMETRY_TIMER->CCER = 0; + TELEMETRY_TIMER->CCMR1 = 0; + TELEMETRY_TIMER->CR1 = TIM_CR1_CEN; + TELEMETRY_TIMER->DIER = TIM_DIER_UIE; + + NVIC_SetPriority(TELEMETRY_TIMER_IRQn, 0); + NVIC_EnableIRQ(TELEMETRY_TIMER_IRQn); + + // init TELEMETRY_RX_GPIO_PIN + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; + GPIO_InitStructure.GPIO_Pin = TELEMETRY_RX_GPIO_PIN; + GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure); + + telemetryInitDirPin(); + + // Connect EXTI line to TELEMETRY RX pin + SYSCFG_EXTILineConfig(TELEMETRY_EXTI_PortSource, TELEMETRY_EXTI_PinSource); + + // Configure EXTI for raising edge (start bit) + EXTI_InitTypeDef EXTI_InitStructure; + EXTI_StructInit(&EXTI_InitStructure); + EXTI_InitStructure.EXTI_Line = TELEMETRY_EXTI_LINE; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = TELEMETRY_EXTI_TRIGGER; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + //TODO: + // - handle conflict with HEARTBEAT disabled for trainer input... + // - probably need to stop trainer input/output and restore after this is closed +#if !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER) && !defined(TELEMETRY_EXTI_REUSE_INTERRUPT_INTMODULE_HEARTBEAT) + NVIC_SetPriority(TELEMETRY_EXTI_IRQn, 0); + NVIC_EnableIRQ(TELEMETRY_EXTI_IRQn); +#endif +} + +void telemetryPortInvertedRxBit() +{ + if (rxBitCount < 8) { + if (rxBitCount == 0) { + TELEMETRY_TIMER->ARR = 34; + rxByte = 0; + } + else { + rxByte >>= 1; + } + + if (GPIO_ReadInputDataBit(TELEMETRY_GPIO, TELEMETRY_RX_GPIO_PIN) == Bit_RESET) + rxByte |= 0x80; + + ++rxBitCount; + } + else if (rxBitCount == 8) { + + telemetryFifo.push(rxByte); + rxBitCount = 0; + + // disable timer + TELEMETRY_TIMER->CR1 &= ~TIM_CR1_CEN; + + // re-enable start bit interrupt + EXTI->IMR |= EXTI_IMR_MR6; + } +} + void telemetryPortSetDirectionOutput() { TELEMETRY_DIR_OUTPUT(); @@ -217,6 +328,36 @@ extern "C" void TELEMETRY_USART_IRQHandler(void) } } +void check_telemetry_exti() +{ + if (EXTI_GetITStatus(TELEMETRY_EXTI_LINE) != RESET) { + + if (rxBitCount == 0) { + + TELEMETRY_TIMER->ARR = 48; // 1,5 cycle from start at 57600bps + TELEMETRY_TIMER->CR1 |= TIM_CR1_CEN; + + // disable start bit interrupt + EXTI->IMR &= ~EXTI_IMR_MR6; + } + + EXTI_ClearITPendingBit(TELEMETRY_EXTI_LINE); + } +} + +#if defined(TELEMETRY_EXTI_IRQHandler) +extern "C" void TELEMETRY_EXTI_IRQHandler(void) +{ + check_telemetry_exti(); +} +#endif + +extern "C" void TELEMETRY_TIMER_IRQHandler() +{ + TELEMETRY_TIMER->SR &= ~TIM_SR_UIF; + telemetryPortInvertedRxBit(); +} + // TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp bool telemetryGetByte(uint8_t * byte) { diff --git a/radio/src/trainer.h b/radio/src/trainer.h index 6f5549cc7..e3c67acac 100644 --- a/radio/src/trainer.h +++ b/radio/src/trainer.h @@ -35,6 +35,7 @@ extern uint8_t currentTrainerMode; void checkTrainerSignalWarning(); void checkTrainerSettings(); +void forceResetTrainerSettings(); // Needs to be inlined to avoid slow function calls in ISR routines inline void captureTrainerPulses(uint16_t capture) diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 55758d390..9f7f8247e 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -677,6 +677,9 @@ const char STR_PROTOCOL_INVALID[] = TR_PROTOCOL_INVALID; const char STR_MODULE_STATUS[] = TR_MODULE_STATUS; const char STR_MODULE_SYNC[] = TR_MODULE_SYNC; const char STR_MULTI_SERVOFREQ[] = TR_MULTI_SERVOFREQ; +const char STR_NEEDS_FILE[] = TR_NEEDS_FILE; +const char STR_EXT_MULTI_SPEC[] = TR_EXT_MULTI_SPEC; +const char STR_INT_MULTI_SPEC[] = TR_INT_MULTI_SPEC; #endif #if LCD_W < 212 diff --git a/radio/src/translations.h b/radio/src/translations.h index 814d2669c..038c4eea1 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -537,6 +537,9 @@ extern const char STR_WAITING_FOR_TX[]; #define STR_UPDATE_LIST STR_DELAYDOWN #endif +extern const char STR_NEEDS_FILE[]; +extern const char STR_EXT_MULTI_SPEC[]; +extern const char STR_INT_MULTI_SPEC[]; extern const char STR_CAT_NOT_EMPTY[]; extern const char STR_WARNING[]; extern const char STR_STORAGE_WARNING[]; diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 2fd44ac86..bb1916f94 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -714,6 +714,9 @@ #define TR_SPECTRUM_ANALYSER_EXT "Spektální an. (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spektální an. (INT)" #define TR_SDCARD_FULL "Plná SD karta" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Nekompatibilní" #define TR_WARNING "KONTROLA" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index bd92d701d..9ca6518ae 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -715,7 +715,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD-Karte voll" +#define TR_SDCARD_FULL "SD-Karte voll" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Nicht kompatibel" #define TR_WARNING "WARNUNG" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index c0280a685..1e1f9f2e0 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -715,6 +715,9 @@ #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" #define TR_SDCARD_FULL "SD card full" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompatible" #define TR_WARNING "WARNING" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 49c469444..f68de52c7 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -738,7 +738,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD Card Full" +#define TR_SDCARD_FULL "SD Card Full" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompatible" #define TR_WARNING "AVISO" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 6773fc1aa..490dfc35b 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -732,7 +732,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD Card Full" +#define TR_SDCARD_FULL "SD Card Full" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompatible" #define TR_WARNING "WARNING" #define TR_EEPROMWARN "FINSKA" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 5e42b17c4..be2e60f4b 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -736,6 +736,9 @@ #define TR_SPECTRUM_ANALYSER_EXT TR("Spectre (EXT)", "Analyseur spectre (EXT)") #define TR_SPECTRUM_ANALYSER_INT TR("Spectre (INT)", "Analyseur spectre (INT)") #define TR_SDCARD_FULL "Carte SD pleine" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompatible" #define TR_WARNING "ALERTE" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 2a53c794c..167f8240d 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -733,7 +733,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD Card Piena" +#define TR_SDCARD_FULL "SD Card Piena" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompatibile" #define TR_WARNING "AVVISO" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 21ea8354b..f57f1eb75 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -720,7 +720,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD-Kaart vol" +#define TR_SDCARD_FULL "SD-Kaart vol" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Niet compatibel" #define TR_WARNING "MELDING" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index b2d8d9cc9..45c2d3807 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -733,7 +733,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "Karta Pełna " +#define TR_SDCARD_FULL "Karta Pełna " +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Niekompatybilne" #define TR_WARNING "UWAGA" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 7d0a6d372..217590c1f 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -723,7 +723,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD Card Full" +#define TR_SDCARD_FULL "SD Card Full" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompativel" #define TR_WARNING "AVISO" #define TR_EEPROMWARN "EEPROM" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 8b6b86a02..7e6aa1499 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -732,7 +732,10 @@ #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD-kort Fullt" +#define TR_SDCARD_FULL "SD-kort Fullt" +#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_EXT_MULTI_SPEC "opentx-inv" +#define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Inkompatibel" #define TR_WARNING "VARNING" #define TR_EEPROMWARN "EEPROM" From 2b24b41ea2adf51f4cd79d959d7032797ad24f28 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 16 Oct 2019 16:14:57 +0200 Subject: [PATCH 189/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index e760eb3c7..4d4020715 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1607,3 +1607,4 @@ Gerald Roedel James D McKeown 鄭 淳中 Matthias Wuethrich +Michael Tessler From 8d52022f3d2ca6d66735b6a15499d6fa5830dbfe Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 17 Oct 2019 07:33:29 +0200 Subject: [PATCH 190/257] Display LP45, DSM2 and DSMX receiver number in model list --- companion/src/firmwares/moduledata.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/companion/src/firmwares/moduledata.cpp b/companion/src/firmwares/moduledata.cpp index 8b9b08c2f..b4457345a 100644 --- a/companion/src/firmwares/moduledata.cpp +++ b/companion/src/firmwares/moduledata.cpp @@ -73,6 +73,9 @@ bool ModuleData::supportRxNum() const case PULSES_XJT_LITE_X16: case PULSES_XJT_LITE_LR12: case PULSES_PXX_XJT_LR12: + case PULSES_LP45: + case PULSES_DSM2: + case PULSES_DSMX: return true; default: return false; From e119dee3cb889c4954c16bb5fbd7dc851caa5f94 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 17 Oct 2019 07:38:20 +0200 Subject: [PATCH 191/257] This fixes #6959 --- companion/src/firmwares/boards.cpp | 2 +- companion/src/firmwares/opentx/opentxinterface.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 809bc159a..726cae256 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -526,7 +526,7 @@ QString Boards::getBoardName(Board::Type board) case BOARD_X10: return "Horus X10/X10S"; case BOARD_X10_EXPRESS: - return "Horus X10 Express"; + return "Horus X10/X10S Express"; case BOARD_JUMPER_T16: return "Jumper T16"; default: diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index d3b44798a..044a191f7 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -1276,7 +1276,7 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); /* FrSky X10 Express board */ - firmware = new OpenTxFirmware("opentx-x10express", Firmware::tr("FrSky Horus X10 Express"), BOARD_X10_EXPRESS); + firmware = new OpenTxFirmware("opentx-x10express", Firmware::tr("FrSky Horus X10 / X10S Express"), BOARD_X10_EXPRESS); addOpenTxFrskyOptions(firmware); firmware->addOption("autoupdate", Firmware::tr("Support for auto update on boot")); registerOpenTxFirmware(firmware); From c6e7fa644422287c4a3a5e57ba6e9dad1d89fcff Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 17 Oct 2019 18:52:29 +0200 Subject: [PATCH 192/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 4d4020715..5c14a0d13 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1608,3 +1608,4 @@ James D McKeown 鄭 淳中 Matthias Wuethrich Michael Tessler +John Beech From 5a298a2362f4d0fc9d12c0875e7b75ab2ac85a71 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 18 Oct 2019 11:51:13 +0200 Subject: [PATCH 193/257] Credits --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 5c14a0d13..8ec9716c3 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -27,6 +27,8 @@ Michael Byrne [Companies and projects who have donated to OpenTX]
FrSky (monthly) +FlySky (monthly) +JumperRC (monthly) Aloft Hobbies Jonathan Modellismo WsTech From 8b49daa455cb4c24f16e9a9ea7429cbaa93bb836 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 18 Oct 2019 16:15:21 +0200 Subject: [PATCH 194/257] Fix T16 companion inport warning (#6965) * Add JumperTX wartning also when reading from radio * Reuse * Reword * Cosmetics * Cosmetics --- companion/src/helpers.cpp | 17 +++++++++++++++++ companion/src/helpers.h | 2 ++ companion/src/mdichild.cpp | 13 +------------ companion/src/radiointerface.cpp | 5 +++++ 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/companion/src/helpers.cpp b/companion/src/helpers.cpp index 8ecf55f12..eb594b9b6 100644 --- a/companion/src/helpers.cpp +++ b/companion/src/helpers.cpp @@ -435,6 +435,23 @@ static bool caseInsensitiveLessThan(const QString &s1, const QString &s2) return s1.toLower() < s2.toLower(); } +bool displayT16ImportWarning() +{ + QMessageBox msgBox; + msgBox.setWindowTitle(QObject::tr("WARNING")); + msgBox.setText(QObject::tr("

Importing JumperTX data into OpenTX 2.3 is not supported and dangerous.

\ +

It is unfortunately not possible for us to differentiate JumperTX data from legitimate FrSky X10 data, but You should only continue here if the file you opened comes from a real FrSky X10.

\ +

Do you really want to continue?

")); + msgBox.setIcon(QMessageBox::Warning); + msgBox.addButton(QMessageBox::No); + msgBox.addButton(QMessageBox::Yes); + msgBox.setDefaultButton(QMessageBox::No); + + if (msgBox.exec() == QMessageBox::No) + return false; + return true; +} + void Helpers::populateFileComboBox(QComboBox * b, const QSet & set, const QString & current) { b->clear(); diff --git a/companion/src/helpers.h b/companion/src/helpers.h index 0ce75e7fb..8a7399c56 100644 --- a/companion/src/helpers.h +++ b/companion/src/helpers.h @@ -52,6 +52,8 @@ extern const QColor colors[CPN_MAX_CURVES]; #define TRIM_MODE_NONE 0x1F // 0b11111 +bool displayT16ImportWarning(); + class CompanionIcon: public QIcon { public: CompanionIcon(const QString &baseimage); diff --git a/companion/src/mdichild.cpp b/companion/src/mdichild.cpp index ebb5c0492..358f85817 100644 --- a/companion/src/mdichild.cpp +++ b/companion/src/mdichild.cpp @@ -1459,18 +1459,7 @@ bool MdiChild::convertStorage(Board::Type from, Board::Type to, bool newFile) QMessageBox::StandardButton dfltBtn; if (from == Board::BOARD_X10 && to == Board::BOARD_JUMPER_T16) { - QMessageBox msgBox; - msgBox.setWindowTitle(tr("WARNING")); - msgBox.setText(tr("

Due to the way Jumper have handled their JumperTX fork and firmware releases data integrity for settings from JumperTX cannot be trusted when migrating to OpenTX.

\ -

Importing JumperTX data into OpenTX 2.3 is not supported and dangerous.

\ -

It is unfortunately not possible for us to differentiate JumperTX data from legitimate FrSky X10 data, but You should only continue here if the file you opened comes from a real FrSky X10.

\ -

Do you really want to continue?

")); - msgBox.setIcon(QMessageBox::Warning); - msgBox.addButton(QMessageBox::No); - msgBox.addButton(QMessageBox::Yes); - msgBox.setDefaultButton(QMessageBox::No); - - if (msgBox.exec() == QMessageBox::No) + if (displayT16ImportWarning() == false) return false; } diff --git a/companion/src/radiointerface.cpp b/companion/src/radiointerface.cpp index d83f40c5c..63befdd0c 100644 --- a/companion/src/radiointerface.cpp +++ b/companion/src/radiointerface.cpp @@ -333,6 +333,11 @@ bool readEeprom(const QString & filename, ProgressWidget * progress) QMessageBox::critical(progress, CPN_STR_TTL_ERROR, outputStorage.error()); return false; } + + if (getCurrentBoard() == Board::BOARD_JUMPER_T16 && inputStorage.getBoard() == Board::BOARD_X10) { + if (displayT16ImportWarning() == false) + return false; + } } else { if (IS_ARM(board)) { From fea0ec73e8beb52018b64400162e0f6d3316227a Mon Sep 17 00:00:00 2001 From: WismyYao Date: Fri, 18 Oct 2019 22:17:54 +0800 Subject: [PATCH 195/257] Fixed the issue that the power option changes when R9M (without access) bind with 'ch1-8 tele ON' option. (#6964) --- radio/src/gui/common/stdlcd/model_setup_pxx1.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp b/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp index 84cc284fd..24091dcd7 100644 --- a/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp +++ b/radio/src/gui/common/stdlcd/model_setup_pxx1.cpp @@ -26,16 +26,10 @@ void onBindMenu(const char * result) if (result == STR_BINDING_1_8_TELEM_ON) { g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = false; g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = false; - if (isModuleR9MLiteNonPro(moduleIdx) && isModuleR9M_LBT(moduleIdx)) { - g_model.moduleData[moduleIdx].pxx.power = R9M_LITE_LBT_POWER_25_8CH; - } } else if (result == STR_BINDING_1_8_TELEM_OFF) { g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = true; g_model.moduleData[moduleIdx].pxx.receiverHigherChannels = false; - if (isModuleR9MLiteNonPro(moduleIdx) && isModuleR9M_LBT(moduleIdx)) { - g_model.moduleData[moduleIdx].pxx.power = R9M_LITE_LBT_POWER_100_16CH_NOTELEM; - } } else if (result == STR_BINDING_9_16_TELEM_ON) { g_model.moduleData[moduleIdx].pxx.receiverTelemetryOff = false; From 58ff019423a04b79502b56f5f589c953684cb6e9 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 18 Oct 2019 16:56:31 +0200 Subject: [PATCH 196/257] Add T16 to nightlies --- tools/build-companion-nightly.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index 0b21114dc..0f0ac3f1f 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -80,6 +80,9 @@ make -j${JOBS} libsimulator cmake ${COMMON_OPTIONS} -DPCB=X10 ${SRCDIR} make -j${JOBS} libsimulator +cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T16 ${SRCDIR} +make -j${JOBS} libsimulator + cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=EXPRESS ${SRCDIR} make -j${JOBS} libsimulator From 2e8b4857c8a434f6cb3f30b416d4ceb733a6dfd8 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 18 Oct 2019 19:25:42 +0200 Subject: [PATCH 197/257] clang 8.0 does not like "= default" constructor in static initialisation --- radio/src/io/multi_firmware_update.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index bf5ca4105..d4f2d976a 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -29,7 +29,7 @@ class MultiFirmwareUpdateDriver { public: - MultiFirmwareUpdateDriver() = default; + MultiFirmwareUpdateDriver() {} const char* flashFirmware(FIL* file, const char* label) const; protected: @@ -54,7 +54,7 @@ class MultiFirmwareUpdateDriver class MultiInternalUpdateDriver: public MultiFirmwareUpdateDriver { public: - MultiInternalUpdateDriver() = default; + MultiInternalUpdateDriver() {} protected: void init() const override @@ -91,7 +91,7 @@ static const MultiInternalUpdateDriver multiInternalUpdateDriver; class MultiExternalSoftSerialUpdateDriver: public MultiFirmwareUpdateDriver { public: - MultiExternalSoftSerialUpdateDriver() = default; + MultiExternalSoftSerialUpdateDriver() {} protected: void init() const override From b9eec0c0b2c55b5d1ab5e9b882e5fc94375553e0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 18 Oct 2019 20:46:10 +0200 Subject: [PATCH 198/257] Attend to fix macosx Sierra cmake cache issue --- tools/build-companion-nightly.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index 0f0ac3f1f..eaa8d355e 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -40,54 +40,71 @@ cd build cmake ${COMMON_OPTIONS} -DPCB=AR9X ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=SKY9X ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=9XRPRO ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X9LITE ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X9LITES ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X7 ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=T12 ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X9D ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X9D+ ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X9D+ -DPCBREV=2019 ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=XLITE ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=XLITES ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X9E ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X10 ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=T16 ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X10 -DPCBREV=EXPRESS ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X12S ${SRCDIR} make -j${JOBS} libsimulator +rm CMakeCache.txt make -j${JOBS} package From 0bb8cea94876351c5a1387010c4c449aa03ad73c Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 18 Oct 2019 21:09:44 +0200 Subject: [PATCH 199/257] Attend to fix macosx Sierra cmake cache issue continued --- tools/build-companion-nightly.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh index eaa8d355e..ac2004b16 100755 --- a/tools/build-companion-nightly.sh +++ b/tools/build-companion-nightly.sh @@ -104,7 +104,6 @@ rm CMakeCache.txt cmake ${COMMON_OPTIONS} -DPCB=X12S ${SRCDIR} make -j${JOBS} libsimulator -rm CMakeCache.txt make -j${JOBS} package From 18880e751148efbb3f9c131c94aa6c470873e5d3 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 19 Oct 2019 08:31:44 +0200 Subject: [PATCH 200/257] Review module availablity --- companion/src/firmwares/opentx/opentxinterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 044a191f7..e1902f73e 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -772,9 +772,9 @@ bool OpenTxFirmware::isAvailable(PulsesProtocol proto, int port) return true; case PULSES_PXX_XJT_X16: case PULSES_PXX_XJT_LR12: - return !IS_ACCESS_RADIO(board, id); + return !IS_ACCESS_RADIO(board, id) && board != BOARD_JUMPER_T16; case PULSES_PXX_XJT_D8: - return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")); + return !(IS_ACCESS_RADIO(board, id) || id.contains("eu")) && board != BOARD_JUMPER_T16; case PULSES_PPM: return id.contains("internalppm"); case PULSES_ACCESS_ISRM: From 4cacf9852231ca06e74aa96f36a49d78924132a5 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 19 Oct 2019 13:43:43 +0200 Subject: [PATCH 201/257] Horus has screenshot too --- companion/src/modeledit/customfunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index 552b31038..dfcc1809e 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -688,7 +688,7 @@ void CustomFunctionsPanel::populateFuncCB(QComboBox *b, unsigned int value) ((i==FuncLogs) && !firmware->getCapability(HasSDLogs)) || ((i==FuncSetTimer1 || i==FuncSetTimer2) && !IS_ARM(firmware->getBoard())) || ((i==FuncSetTimer3) && firmware->getCapability(Timers) < 3) || - ((i==FuncScreenshot) && !IS_TARANIS(firmware->getBoard())) || + ((i==FuncScreenshot) && !IS_HORUS_OR_TARANIS(firmware->getBoard())) || ((i>=FuncRangeCheckInternalModule && i<=FuncBindExternalModule) && (!model || !firmware->getCapability(DangerousFunctions))) || ((i>=FuncAdjustGV1 && i<=FuncAdjustGVLast) && (!model || !firmware->getCapability(Gvars))) ) { From c09d686606115e6d1ed467759a70af092c281df0 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 19 Oct 2019 14:19:14 +0200 Subject: [PATCH 202/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 8ec9716c3..c9fb904f5 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1611,3 +1611,4 @@ James D McKeown Matthias Wuethrich Michael Tessler John Beech +Stefan Möst From 03dbabd4b4abf525a9cdbf279cb2f2040b65528b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 19 Oct 2019 14:19:50 +0200 Subject: [PATCH 203/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index c9fb904f5..93e5362b2 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1612,3 +1612,4 @@ Matthias Wuethrich Michael Tessler John Beech Stefan Möst +Thomas McGraw From 81d6c452d1cc2bc27b7019f62736dc2df8f67bb2 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 20 Oct 2019 19:30:50 +0200 Subject: [PATCH 204/257] Fix failsafe warning on internal multi --- radio/src/telemetry/multi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 268fb533c..7c24ac48c 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -209,7 +209,7 @@ static void processMultiStatusPacket(const uint8_t * data, uint8_t module) if (getMultiModuleStatus(module).requiresFailsafeCheck) { getMultiModuleStatus(module).requiresFailsafeCheck = false; - if (getMultiModuleStatus(module).supportsFailsafe() && g_model.moduleData[EXTERNAL_MODULE].failsafeMode == FAILSAFE_NOT_SET) + if (getMultiModuleStatus(module).supportsFailsafe() && g_model.moduleData[module].failsafeMode == FAILSAFE_NOT_SET) POPUP_WARNING(STR_NO_FAILSAFE); } From 084d7dc8464962f54ae460c3246fac17c85480ad Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 20 Oct 2019 19:59:47 +0200 Subject: [PATCH 205/257] Fix T16 power led --- radio/src/targets/horus/board.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index db0c28416..fd93f15ee 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -172,8 +172,8 @@ void boardInit() DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM4_STOP|DBGMCU_TIM5_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM7_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM9_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM11_STOP|DBGMCU_TIM12_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE); #endif -#if defined(PCBX10) && !defined(RADIO_T16) ledInit(); +#if defined(PCBX10) && !defined(RADIO_T16) sportUpdateInit(); #endif From 98d75f89e23900dc63768b13f698d6449e14a1a3 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 20 Oct 2019 22:20:28 +0200 Subject: [PATCH 206/257] Review Sky9x model setup screen (#6978) Fix sky9x model setup screen --- radio/src/gui/128x64/model_setup.cpp | 56 ++++++++++++++++++++-------- radio/src/pulses/modules_helpers.h | 8 +++- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 59dbd299a..00cc5d85b 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -205,7 +205,7 @@ inline uint8_t EXTERNAL_MODULE_TYPE_ROW() #define TIMER_ROWS 2, 0, 0, 0, 0 #if defined(PCBSKY9X) - #define EXTRA_MODULE_ROWS LABEL(ExtraModule), 1, 2, + #define EXTRA_MODULE_ROWS LABEL(ExtraModule), 1, 2, #else #define EXTRA_MODULE_ROWS #endif @@ -346,18 +346,46 @@ void menuModelSetup(event_t event) TRAINER_ROWS }); #else - MENU_TAB({ HEADER_LINE_COLUMNS 0, TIMER_ROWS, TIMER_ROWS, TIMER_ROWS, 0, 1, 0, 0, 0, 0, 0, LABEL(PreflightCheck), 0, 0, NUM_SWITCHES-1, NUM_STICKS+NUM_POTS+NUM_SLIDERS-1, 0, + MENU_TAB({ + HEADER_LINE_COLUMNS + 0, + TIMER_ROWS, + TIMER_ROWS, + TIMER_ROWS, + 0, // Extended limits + 1, // Extended trims + 0, // Show trims + 0, // Trims step + 0, // Throttle reverse + 0, // Throttle trace source + 0, // Throttle trim + + LABEL(PreflightCheck), + 0, // Checklist + 0, // Throttle warning + NUM_SWITCHES-1, // Switch warning + + NUM_STICKS+NUM_POTS+NUM_SLIDERS-1, // Center beeps + 0, // Global functions + LABEL(ExternalModule), - EXTERNAL_MODULE_TYPE_ROW(), - MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) - MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) - MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), - MODULE_BIND_ROWS(EXTERNAL_MODULE), - OUTPUT_TYPE_ROW - MODULE_OPTION_ROW(EXTERNAL_MODULE), - MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) - MODULE_POWER_ROW(EXTERNAL_MODULE), - FAILSAFE_ROWS(EXTERNAL_MODULE), + EXTERNAL_MODULE_TYPE_ROW(), + MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) + MODULE_POWER_ROW(EXTERNAL_MODULE), + MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), + IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings + OUTPUT_TYPE_ROW + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum + IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), + MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) + FAILSAFE_ROWS(EXTERNAL_MODULE), + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons + IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 1 + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 2 + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 3 + EXTRA_MODULE_ROWS TRAINER_ROWS }); @@ -846,7 +874,6 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(lcdNextPos + 3, y, STR_MULTI_PROTOCOLS, multi_rfProto, menuHorizontalPosition==1 ? attr : 0); } #endif -#if defined(PCBTARANIS) if (attr && menuHorizontalPosition == 0) { if (s_editMode > 0) { g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_NONE; @@ -860,7 +887,6 @@ void menuModelSetup(event_t event) g_model.moduleData[EXTERNAL_MODULE].type = reusableBuffer.moduleSetup.newType; } } -#endif if (attr) { if (s_editMode > 0) { switch (menuHorizontalPosition) { @@ -1194,12 +1220,10 @@ void menuModelSetup(event_t event) #if defined(PCBSKY9X) case ITEM_MODEL_SETUP_EXTRA_MODULE_BIND: #endif -#if defined(PCBTARANIS) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_BIND: #endif case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_BIND: -#endif { uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); ModuleData & moduleData = g_model.moduleData[moduleIdx]; diff --git a/radio/src/pulses/modules_helpers.h b/radio/src/pulses/modules_helpers.h index 8b03d419e..aaf367c00 100644 --- a/radio/src/pulses/modules_helpers.h +++ b/radio/src/pulses/modules_helpers.h @@ -127,9 +127,13 @@ inline bool isModuleTypePPM(uint8_t type) return type == MODULE_TYPE_PPM; } -inline bool isModulePPM(uint8_t idx) +inline bool isModulePPM(uint8_t moduleIdx) { - return isModuleTypePPM(g_model.moduleData[idx].type); +#if defined(PCBSKY9X) + if (moduleIdx == EXTRA_MODULE) + return true; +#endif + return isModuleTypePPM(g_model.moduleData[moduleIdx].type); } inline bool isModuleTypeR9MNonAccess(uint8_t type) From ba166627750a7b4d5a9fe120a81e700832aa0fa9 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 22 Oct 2019 10:36:32 +0200 Subject: [PATCH 207/257] Tools icon needed for Darkblue theme as well --- .../horus/THEMES/Darkblue/mask_radio_tools.png | Bin 0 -> 1195 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 radio/sdcard/horus/THEMES/Darkblue/mask_radio_tools.png diff --git a/radio/sdcard/horus/THEMES/Darkblue/mask_radio_tools.png b/radio/sdcard/horus/THEMES/Darkblue/mask_radio_tools.png new file mode 100755 index 0000000000000000000000000000000000000000..711d499deafa2283a1ff2a4577c1de5edabddc42 GIT binary patch literal 1195 zcmV;c1XTNpP)(hI=4z~+!amKXtZ(xQKEv;oUI4_wP-s8Owrn&c= z`Q3Z&SvUZo|51v6%ka<)9FNSZ!da!dZ5v0AP53xXJ_LB zpP!$h)oR6)DwRrE=D?v0G4H#osUtb3Rn9XKnWo1e1YHMpHZkw^rcot+>e?Ck6S z0OA(D*=(kjl@)TiTx7LcX=-YU4i670KR;h$S65d@85tS$`T0ptPfuht8mX_Zk2sE_ za5zjvL@6mL(S;vR6B85Qc^-Pb9w#R!3HgLVA(WJqfQS+c>9@wm$HDVF3)US4o}dkeqc55M1!}Ng31-jjC@H~&q%uIN_ z-k3I9TU$`8)lo?k3kCoj5PLki-EL}XY9hT}PwVUJWHOneY__+z$!4=rC={al`g&rF zQCeCWDHIA)tJT!j)<%LL$WM!J4G#~4F%~yL_V@Rp)oP(sD&g^Xu(q~_hK2?>91gs` zzRE@|3YZA&;NSo{oeoN+5=%=<*xK5HN~ID*X|-Ar3M{pd6s;a6e*wxh)a&mIO7{kcONX!F; z!(p_vw8#RJlas}I6yLD8xEO*UU}a@R{L#(L4RUjH!Eqc02M1%qz7;RL?d|Q-8vAo=}%3WY*cSXdaV^ZjGV_R{}Ke*qfvkvN2ZqrLzD002ov JPDHLkV1kEi41E9q literal 0 HcmV?d00001 From 546b37ccfff8ac87e5d188a2aa557278dc2dc7a0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 22 Oct 2019 15:47:36 +0200 Subject: [PATCH 208/257] Prevent uneeded unmount!:mount f already mounted of sdcard (#6986) Prevent double SD mount on Horus --- radio/src/main.cpp | 4 +--- radio/src/opentx.cpp | 2 -- radio/src/opentx.h | 3 +-- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 9237ace55..785c5e423 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -502,11 +502,9 @@ void perMain() #endif #if defined(STM32) - bool sdcardPresent = SD_CARD_PRESENT(); - if (sdcardPresent && !globalData.sdcardPresent) { + if (SD_CARD_PRESENT() && !sdMounted()) { sdMount(); } - globalData.sdcardPresent = sdcardPresent; #endif #if !defined(EEPROM) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 7e3bc3edf..d4697e51a 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1859,8 +1859,6 @@ void opentxInit() } #if defined(SDCARD) - globalData.sdcardPresent = SD_CARD_PRESENT(); - // SDCARD related stuff, only done if not unexpectedShutdown if (!globalData.unexpectedShutdown) { sdInit(); diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 34931dd44..c448edae0 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -569,9 +569,8 @@ void flightReset(uint8_t check=true); PACK(struct GlobalData { uint8_t unexpectedShutdown:1; - uint8_t sdcardPresent:1; uint8_t externalAntennaEnabled: 1; - uint8_t spare:5; + uint8_t spare:6; }); extern GlobalData globalData; From 5c9fba04c7d7d851f52920f73856431346e55293 Mon Sep 17 00:00:00 2001 From: Marco Robustini Date: Tue, 22 Oct 2019 15:49:03 +0200 Subject: [PATCH 209/257] IT TTS update (#6985) --- radio/util/tts_it.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/radio/util/tts_it.py b/radio/util/tts_it.py index 91a796e9c..8ba62493f 100755 --- a/radio/util/tts_it.py +++ b/radio/util/tts_it.py @@ -42,7 +42,7 @@ for i, (s, f) in enumerate([("volt", "volt0"), ("minuto", "minute0"), ("minuti", "minute1"), ("secondo", "second0"), ("secondi", "second1"), ]): - systemSounds.append((s, filename(f, PROMPT_SYSTEM_BASE + 113 + i))) + systemSounds.append((s, filename(f, PROMPT_SYSTEM_BASE + 116 + i))) for s, f, a in [("radio inattiva controllare", "inactiv", 486), ("batteria della radio scarica", "lowbatt", 485), ("controllo motore non in posizione, verificare", "thralert", 481), @@ -71,6 +71,9 @@ for s, f, a in [("radio inattiva controllare", "inactiv", 486), ("Problema all'antenna della radio", "swr_red", NO_ALTERNATE), ("Telemetria assente", "telemko", NO_ALTERNATE), ("Telemetria disponibile", "telemok", NO_ALTERNATE), + ("Segnale trainer perso", "trainko", NO_ALTERNATE), + ("Segnale trainer disponibile", "trainok", NO_ALTERNATE), + ("Sensore perso", "sensorko", NO_ALTERNATE), ("sovraccarico servo", "servoko", NO_ALTERNATE), ("sovraccarico di alimentazione", "rxko", NO_ALTERNATE), ("ricevente ancora connessa", "modelpwr", NO_ALTERNATE), @@ -80,11 +83,13 @@ for i, s in enumerate(["timer", "", "tensione", "tensione", "trasmissione", "ric "carburante", "temperatura", "temperatura", "velocità", "distanza", "altitudine", "cella lipo", "totale lipo", "tensione", "corrente", "consumo", "potenza", "accelerazione X", "accelerazione Y", "accelerazione Z", "direzione", "variometro", "minimo", "massimo"]): - systemSounds.append((s, filename(PROMPT_SYSTEM_BASE + 135 + i))) + systemSounds.append((s, filename(PROMPT_SYSTEM_BASE + 155 + i))) for i, (s, f) in enumerate([("carrello chiuso", "gearup"), ("carrello aperto", "geardn"), ("flap rientrati", "flapup"), ("flap estesi", "flapdn"), + ("spoiler su", "splrup"), + ("spoiler giù", "splrdn"), ("atterraggio", "attero"), ("modalità maestro attiva", "trnon"), ("modalità maestro disattiva", "trnoff"), @@ -92,11 +97,15 @@ for i, (s, f) in enumerate([("carrello chiuso", "gearup"), ("troppo alto", "tohigh"), ("troppo basso", "tolow"), ("batteria scarica", "lowbat"), - ("crow on", "crowon"), - ("crow off", "crowof"), + ("crow attivato", "crowon"), + ("crow disattivato", "crowof"), + ("segnale radio basso", "siglow"), + ("segnale radio critico", "sigcrt"), ("modo velocità", "spdmod"), ("modo termica", "thmmod"), ("modo volo normale", "nrmmod"), + ("modo atterraggio", "lnding"), + ("modo acro", "acro"), ("fase di volo 1", "fltmd1"), ("fase di volo 2", "fltmd2"), ("fase di volo 3", "fltmd3"), @@ -104,7 +113,21 @@ for i, (s, f) in enumerate([("carrello chiuso", "gearup"), ("fase di volo 5", "fltmd5"), ("fase di volo 6", "fltmd6"), ("fase di volo 7", "fltmd7"), - ("fase di volo 8", "fltmd8"), - ("fase di volo 9", "fltmd9"), + ("variometro attivato", "vrion"), + ("variometro disabilitato", "vrioff"), + ("fase di volo power", "fm-pwr"), + ("fase di volo land", "fm-lnd"), + ("fase di volo planata", "fm-flt"), + ("fase di volo velocità", "fm-spd"), + ("fase di volo veloce", "fm-fst"), + ("fase di volo normale", "fm-nrm"), + ("fase di volo cruise", "fm-crs"), + ("fase di volo acro", "fm-acr"), + ("fase di volo race", "fm-rce"), + ("fase di volo lancio", "fm-lch"), + ("fase di volo ping", "fm-png"), + ("fase di volo termica", "fm-thm"), + ("fase di volo termica sinistra", "fm-thl"), + ("fase di volo termica destra", "fm-thr"), ]): sounds.append((s, filename(f, PROMPT_CUSTOM_BASE + i))) From 6d77932f89b3c4d7726169fb284a204f6e659cf0 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 22 Oct 2019 15:53:12 +0200 Subject: [PATCH 210/257] Add support for multi-protocol trainer (#6896) * Add support for multi-protocol trainer * Fix telemetry condition * Trainer mode not supported on Sky9X * fixed radio trainer screen - convert values properly. - apply the weights as setup. * Fix T16 with BT * String fixes * Cosmetics --- radio/src/dataconstants.h | 5 +- radio/src/gui/480x272/radio_trainer.cpp | 7 ++- radio/src/gui/common/stdlcd/radio_trainer.cpp | 7 ++- radio/src/telemetry/multi.cpp | 55 ++++++++++++++++++- radio/src/telemetry/telemetry.h | 34 +++++------- 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 | 3 +- 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 | 3 +- radio/src/translations/pl.h.txt | 1 + radio/src/translations/pt.h.txt | 1 + radio/src/translations/se.h.txt | 1 + radio/src/translations/untranslated.h | 12 ++-- 17 files changed, 107 insertions(+), 40 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index a4bef6c77..d433541dc 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -197,6 +197,7 @@ enum TrainerMode { TRAINER_MODE_MASTER_BLUETOOTH, TRAINER_MODE_SLAVE_BLUETOOTH, #endif + TRAINER_MODE_MULTI, }; #elif defined(PCBSKY9X) enum ModuleIndex { @@ -206,7 +207,9 @@ enum TrainerMode { }; #endif -#if defined(BLUETOOTH) +#if defined(MULTIMODULE) + #define TRAINER_MODE_MAX() TRAINER_MODE_MULTI +#elif defined(BLUETOOTH) #define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH #elif defined(RADIO_T16) #define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE diff --git a/radio/src/gui/480x272/radio_trainer.cpp b/radio/src/gui/480x272/radio_trainer.cpp index 48c6305ef..71b1adfd8 100644 --- a/radio/src/gui/480x272/radio_trainer.cpp +++ b/radio/src/gui/480x272/radio_trainer.cpp @@ -86,10 +86,13 @@ bool menuRadioTrainer(event_t event) if (attr) s_editMode = 0; lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP + 6*FH, STR_CAL, attr); for (int i=0; i<4; i++) { + int32_t chVal = ppmInput[i] - g_eeGeneral.trainer.calib[i]; + chVal *= g_eeGeneral.trainer.mix[i].studWeight * 10; + chVal /= 512; #if defined (PPM_UNIT_PERCENT_PREC1) - lcdDrawNumber(TRAINER_COLUMN_1+i*TRAINER_COLUMN_WIDTH, MENU_CONTENT_TOP + 6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])*2, LEFT|PREC1); + lcdDrawNumber(TRAINER_COLUMN_1+i*TRAINER_COLUMN_WIDTH, MENU_CONTENT_TOP + 6*FH, chVal, LEFT|PREC1); #else - lcdDrawNumber(TRAINER_COLUMN_1+i*TRAINER_COLUMN_WIDTH, MENU_CONTENT_TOP + 6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])/5, LEFT); + lcdDrawNumber(TRAINER_COLUMN_1+i*TRAINER_COLUMN_WIDTH, MENU_CONTENT_TOP + 6*FH, chVal / 10, LEFT); #endif } diff --git a/radio/src/gui/common/stdlcd/radio_trainer.cpp b/radio/src/gui/common/stdlcd/radio_trainer.cpp index a4d6f5e56..58c338a8d 100644 --- a/radio/src/gui/common/stdlcd/radio_trainer.cpp +++ b/radio/src/gui/common/stdlcd/radio_trainer.cpp @@ -88,10 +88,13 @@ void menuRadioTrainer(event_t event) lcdDrawText(0*FW, MENU_HEADER_HEIGHT+1+6*FH, STR_CAL, attr); for (uint8_t i=0; i<4; i++) { uint8_t x = (i*TRAINER_CALIB_COLUMN_WIDTH + 16) * FW/2; + int32_t chVal = ppmInput[i] - g_eeGeneral.trainer.calib[i]; + chVal *= g_eeGeneral.trainer.mix[i].studWeight * 10; + chVal /= 512; #if defined (PPM_UNIT_PERCENT_PREC1) - lcdDrawNumber(x, MENU_HEADER_HEIGHT+1+6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])*2, PREC1|RIGHT); + lcdDrawNumber(x, MENU_HEADER_HEIGHT+1+6*FH, chVal, PREC1|RIGHT); #else - lcdDrawNumber(x, MENU_HEADER_HEIGHT+1+6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])/5, RIGHT); + lcdDrawNumber(x, MENU_HEADER_HEIGHT+1+6*FH, chVal / 10, RIGHT); #endif } diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index 7c24ac48c..ec6bdef8d 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -21,6 +21,8 @@ #include "telemetry.h" #include "multi.h" +#define MULTI_CHAN_BITS 11 + extern uint8_t g_moduleIdx; enum MultiPacketTypes : uint8_t @@ -36,7 +38,8 @@ enum MultiPacketTypes : uint8_t FrskySportPolling, HitecTelemetry, SpectrumScannerPacket, - FlyskyIBusTelemetryAC + FlyskyIBusTelemetryAC, + MultiRxChannels }; enum MultiBufferState : uint8_t @@ -239,6 +242,43 @@ static void processMultiSyncPacket(const uint8_t * data, uint8_t module) #endif } +#if defined(PCBTARANIS) || defined(PCBHORUS) +static void processMultiRxChannels(const uint8_t * data, uint8_t len) +{ + if (g_model.trainerData.mode != TRAINER_MODE_MULTI) + return; + + //uint8_t pps = data[0]; + //uint8_t rssi = data[1]; + int ch = max(data[2], (uint8_t)0); + int maxCh = min(ch + data[3], MAX_TRAINER_CHANNELS); + + uint32_t bits = 0; + uint8_t bitsavailable = 0; + uint8_t byteIdx = 4; + + while(ch < maxCh) { + + while((bitsavailable < MULTI_CHAN_BITS) && byteIdx < len) { + bits |= (uint32_t)(data[byteIdx++]) << (uint32_t)bitsavailable; + bitsavailable += 8; + } + + int value = bits & ((1 << MULTI_CHAN_BITS) - 1); + bitsavailable -= MULTI_CHAN_BITS; + bits >>= MULTI_CHAN_BITS; + + ppmInput[ch] = (value - 1024) * 500 / 800; + ch++; + + if (byteIdx >= len) + break; + } + + if (ch == maxCh) + ppmInputValidityTimer = PPM_IN_VALID_TIMEOUT; +} +#endif static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) { @@ -328,6 +368,15 @@ static void processMultiTelemetryPaket(const uint8_t * packet, uint8_t module) TRACE("[MP] Received spectrum scanner len %d != 6", len); break; +#if defined(PCBTARANIS) || defined(PCBHORUS) + case MultiRxChannels: + if (len >= 4) + processMultiRxChannels(data, len); + else + TRACE("[MP] Received RX channels len %d < 4", len); + break; +#endif + default: TRACE("[MP] Unkown multi packet type 0x%02X, len %d", type, len); break; @@ -458,7 +507,7 @@ void MultiModuleStatus::getStatusString(char * statusText) if (!isValid()) { #if defined(PCBTARANIS) || defined(PCBHORUS) #if !defined(INTERNAL_MODULE_MULTI) - if (IS_INTERNAL_MODULE_ENABLED()) + if (isSportLineUsedByInternalModule()) strcpy(statusText, STR_DISABLE_INTERNAL); else #endif @@ -552,7 +601,7 @@ void processMultiTelemetryData(uint8_t data, uint8_t module) uint8_t * rxBuffer = getRxBuffer(module); uint8_t &rxBufferCount = getRxBufferCount(module); - debugPrintf("State: %d, byte received %02X, buflen: %d\r\n", multiTelemetryBufferState, data, rxBufferCount); + //debugPrintf("State: %d, byte received %02X, buflen: %d\r\n", multiTelemetryBufferState, data, rxBufferCount); switch (getMultiTelemetryBufferState(module)) { case NoProtocolDetected: if (data == 'M') { diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index 35964e893..442ec7e43 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -111,13 +111,21 @@ extern uint8_t telemetryProtocol; #endif #define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM) +#if defined(PCBTARANIS) || defined(PCBHORUS) +inline bool isSportLineUsedByInternalModule() +{ + return g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT_PXX1; +} +#else +inline bool isSportLineUsedByInternalModule() +{ + return false; +} +#endif + inline uint8_t modelTelemetryProtocol() { - bool internalModuleInUse = IS_INTERNAL_MODULE_ENABLED(); -#if defined(INTERNAL_MODULE_MULTI) - //internal muli module is not conflicting with external one - internalModuleInUse = false; -#endif + bool sportUsed = isSportLineUsedByInternalModule(); #if defined(CROSSFIRE) if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) { @@ -125,12 +133,12 @@ inline uint8_t modelTelemetryProtocol() } #endif - if (!internalModuleInUse && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) { + if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) { return g_model.telemetryProtocol; } #if defined(MULTIMODULE) - if (!internalModuleInUse && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) { + if (!sportUsed && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) { return PROTOCOL_TELEMETRY_MULTIMODULE; } #endif @@ -236,18 +244,6 @@ extern OutputTelemetryBuffer outputTelemetryBuffer __DMA; extern Fifo * luaInputTelemetryFifo; #endif -#if defined(PCBTARANIS) || defined(PCBHORUS) -inline bool isSportLineUsedByInternalModule() -{ - return g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT_PXX1; -} -#else -inline bool isSportLineUsedByInternalModule() -{ - return false; -} -#endif - void processPXX2Frame(uint8_t module, uint8_t *frame); #endif // _TELEMETRY_H_ diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index bb1916f94..638af0653 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -353,7 +353,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Učitel/SBUS Modul\0" #define TR_VTRAINER_MASTER_CPPM_MODULE "Učitel/CPPM Modul\0" #define TR_VTRAINER_MASTER_BATTERY "Učitel/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\012" #define TR_VFAILSAFE "Nenastaven""Držet\0 ""Vlastní\0 ""Bez pulzů\0""Přijímač\0" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 9ca6518ae..5538e33b6 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -356,7 +356,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Lehrer/SBUS Modul\0" #define TR_VTRAINER_MASTER_CPPM_MODULE "Lehrer/CPPM Modul\0" #define TR_VTRAINER_MASTER_BATTERY "Lehrer/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\015" // "\013" original #define TR_VFAILSAFE "Kein Failsafe""Halte Pos.\0 ""Kanäle\0 ""Kein Signal\0 ""Empfänger\0 " diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 1e1f9f2e0..4fa537891 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -356,7 +356,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/SBUS Module" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE "Not set\0 ""Hold\0 ""Custom\0 ""No pulses""Receiver\0" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index f68de52c7..44d2fed5c 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -371,7 +371,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/SBUS Module" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE "Not set\0 ""Guardar\0 ""Adaptar\0 ""Sin pulso""Receiver\0" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 490dfc35b..4350b43a5 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -371,7 +371,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/SBUS Module" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE "Not set\0 ""Hold\0 ""Custom\0 ""No pulses""Receiver\0" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index be2e60f4b..8a54e8592 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -373,7 +373,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Maître/SBUS Module" #define TR_VTRAINER_MASTER_CPPM_MODULE "Maître/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Maître/Série\0 " -#define TR_VTRAINER_BLUETOOTH TR("Maître/BT\0 ""Elève/BT\0", "Maître/Bluetooth\0 ""Elève/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Maître/BT\0 ""Elève/BT\0 ", "Maître/Bluetooth\0 ""Elève/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE TR("Pas déf.\0""Maintien\0""Prédéf.\0 ""Pas d'imp""Récepteur", "Pas déf.\0""Maintien\0""Prédéfini""Pas d'imp""Récepteur") diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 167f8240d..2804358c5 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -374,7 +374,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/Modulo SBUS" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/Modulo CPPM" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\013" #define TR_VFAILSAFE "Non settato""Mantieni\0 ""Personali\0 ""No impulsi\0""Ricevente\0 " diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index f57f1eb75..36c4189cb 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -353,7 +353,8 @@ #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/SBUS Module" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " -#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE TR("\013","\011") #define TR_VFAILSAFE TR("Niet Gezet\0""Vasthouden\0""Custom\0 ""Geen Pulsen""Ontvanger\0 ","Not Set\0 ""Hold\0 ""Custom\0 ""No Pulses""Receiver\0") diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 45c2d3807..66ecb032b 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -375,6 +375,7 @@ #define TR_VTRAINER_MASTER_CPPM_MODULE "Trener/CPPM Moduł " #define TR_VTRAINER_MASTER_BATTERY "Trener/Serial\0 " #define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" /*9 decimal*/ #define TR_VFAILSAFE "Brak \0 ""Utrzymuj\0""Własne \0""0 sygnału""Odbiornik" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 217590c1f..669c4c4c4 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -357,6 +357,7 @@ #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/CPPM Module" #define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " #define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE "Not set\0 ""Hold\0 ""Custom\0 ""No pulses""Receiver\0" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 7e6aa1499..7164ba97c 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -370,6 +370,7 @@ #define TR_VTRAINER_MASTER_CPPM_MODULE "Lärare/CPPM-Modul\0" #define TR_VTRAINER_MASTER_BATTERY "Lärare/Serial\0 " #define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") +#define TR_VTRAINER_MULTI "Master/Multi" #define LEN_VFAILSAFE "\011" #define TR_VFAILSAFE "Ej givet\0""Lås Servo""Anpassat\0""Pulsfritt""Mottagare" diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index dc72f9f58..5c55aad6d 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -68,14 +68,16 @@ #define TR_VSWITCHES "---" "ID0""ID1""ID2" "THR""RUD""ELE""AIL""GEA""TRN" TR_TRIMS_SWITCHES TR_ROTENC_SWITCHES TR_ON_ONE_SWITCHES #endif -#if defined(PCBHORUS) - #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_BLUETOOTH +#if defined(PCBHORUS) && !defined(BLUETOOTH) + #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MULTI +#elif defined(PCBHORUS) + #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI #elif defined(PCBX9E) - #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH + #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI #elif defined(PCBTARANIS) && defined(BLUETOOTH) - #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH + #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_BLUETOOTH TR_VTRAINER_MULTI #elif defined(PCBTARANIS) - #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY + #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_SBUS_MODULE TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY TR_VTRAINER_MULTI #else #define TR_VTRAINERMODES TR_VTRAINER_MASTER_JACK TR_VTRAINER_SLAVE_JACK TR_VTRAINER_MASTER_CPPM_MODULE TR_VTRAINER_MASTER_BATTERY #endif From a7be18e8b7e4403ffa712ee133005f0fe275a36c Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 22 Oct 2019 16:10:24 +0200 Subject: [PATCH 211/257] Trigger SDCard : Italian and missing tools icon for Darkblue --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2178a5f1..e7e0057db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(VERSION_REVISION "2") 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 "0022") +set(SDCARD_REVISION "0023") set(SDCARD_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}V${SDCARD_REVISION}) cmake_minimum_required(VERSION 2.8) From 87c3cd35333e530b61a2bbbdf5befb337f6448bb Mon Sep 17 00:00:00 2001 From: Marco Robustini Date: Tue, 22 Oct 2019 21:47:43 +0200 Subject: [PATCH 212/257] Updated IT language (#6987) Updated IT language --- radio/src/translations/it.h.txt | 306 ++++++++++++++++---------------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 2804358c5..54314e60c 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -597,9 +597,9 @@ #define TR_ALARMSDISABLED "Avvisi Disattivati!" #define TR_PRESSANYKEY "\010Premi un tasto" #define TR_BADEEPROMDATA "Dati corrotti!" -#define TR_BAD_RADIO_DATA "Bad Radio Data" +#define TR_BAD_RADIO_DATA "Dati radio errati" #define TR_EEPROMFORMATTING "Formatto EEPROM..." -#define TR_STORAGE_FORMAT "Storage Preparation" +#define TR_STORAGE_FORMAT "Preparazione storage" #define TR_EEPROMOVERFLOW "EEPROM Piena" #define TR_MENURADIOSETUP "CONFIGURATX" #define TR_MENUDATEANDTIME "DATA E ORA" @@ -614,8 +614,8 @@ #else #define TR_TRIMS2OFFSETS "\006Trim => Offset " #endif -#define TR_CHANNELS2FAILSAFE "Channels=>Failsafe" -#define TR_CHANNEL2FAILSAFE "Channel=>Failsafe" +#define TR_CHANNELS2FAILSAFE "Canali=>Failsafe" +#define TR_CHANNEL2FAILSAFE "Canale=>Failsafe" #define TR_MENUMODELSEL "MODELLI" #define TR_MENUSETUP "CONFIGURA" #define TR_MENUFLIGHTMODE "FASE DI VOLO" @@ -635,46 +635,46 @@ #define TR_MENUTEMPLATES "ESEMPI GUIDA" #define TR_MENUSTAT "STATO" #define TR_MENUDEBUG "DEBUG" -#define TR_MONITOR_CHANNELS1 "CHANNELS MONITOR 1/8" -#define TR_MONITOR_CHANNELS2 "CHANNELS MONITOR 9/16" -#define TR_MONITOR_SWITCHES "LOGICAL SWITCHES MONITOR" -#define TR_MONITOR_CHANNELS3 "CHANNELS MONITOR 17/24" -#define TR_MONITOR_CHANNELS4 "CHANNELS MONITOR 25/32" -#define TR_MONITOR_OUTPUT_DESC "Outputs" +#define TR_MONITOR_CHANNELS1 "MONITOR CANALI 1/8" +#define TR_MONITOR_CHANNELS2 "MONITOR CANALI 9/16" +#define TR_MONITOR_SWITCHES "MONITOR INTERRUTTORI LOGICI" +#define TR_MONITOR_CHANNELS3 "MONITOR CANALI 17/24" +#define TR_MONITOR_CHANNELS4 "MONITOR CANALI 25/32" +#define TR_MONITOR_OUTPUT_DESC "Uscite" #define TR_MONITOR_MIXER_DESC "Mixers" #define TR_RECEIVER_NUM TR("RxNum", "Ricevente No.") -#define TR_RECEIVER "Receiver" -#define TR_MULTI_RFTUNE TR("Freq tune", "RF Freq. fine tune") -#define TR_MULTI_TELEMETRY "Telemetry" -#define TR_MULTI_VIDFREQ TR("Vid. freq.", "Video frequency") -#define TR_RFPOWER "RF Power" +#define TR_RECEIVER "Ricevente" +#define TR_MULTI_RFTUNE TR("Tune RF", "Tune fine Freq. RF") +#define TR_MULTI_TELEMETRY "Telemetria" +#define TR_MULTI_VIDFREQ TR("Freq. video", "Frequenza video") +#define TR_RFPOWER "Potenza RF" #define TR_MULTI_FIXEDID TR("FixedID", "Fixed ID") -#define TR_MULTI_OPTION TR("Option", "Option value") -#define TR_MULTI_AUTOBIND TR(INDENT "Autobind",INDENT "Bind on channel") -#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Autodetect", INDENT "Autodetect format") -#define TR_MULTI_LOWPOWER TR(INDENT "Low power", INDENT "Low power mode") -#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "S.Port link") -#define TR_MODULE_TELEM_ON TR("ON", "Enabled") -#define TR_DISABLE_INTERNAL TR("Disable int. RF", "Disable internal RF") -#define TR_MODULE_NO_SERIAL_MODE TR("!serial mode", "Not in serial mode") -#define TR_MODULE_NO_INPUT TR("No input", "No serial input") -#define TR_MODULE_NO_TELEMETRY TR3( "No telmetry", "No MULTI_TELEMETRY", "No telemetry (enable MULTI_TELEMETRY)") -#define TR_MODULE_WAITFORBIND "Bind to load protocol" -#define TR_MODULE_BINDING "Binding" -#define TR_REBIND "Rebinding required" -#define TR_REG_OK "Registration ok" -#define TR_BIND_OK "Bind successful" +#define TR_MULTI_OPTION TR("Opzione", "Opzione valore") +#define TR_MULTI_AUTOBIND TR(INDENT "Autoassocia",INDENT "Associa al canale") +#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Trova autom.", INDENT "Autorileva il formato") +#define TR_MULTI_LOWPOWER TR(INDENT "Bassa pot.", INDENT "Modalità bassa potenza") +#define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "Link S.Port") +#define TR_MODULE_TELEM_ON TR("ON", "Abilitato") +#define TR_DISABLE_INTERNAL TR("Disatt. RF int.", "Disattiva RF interna") +#define TR_MODULE_NO_SERIAL_MODE TR("!modo seriale", "Non in modo seriale") +#define TR_MODULE_NO_INPUT TR("Nessun input", "Nessun input seriale") +#define TR_MODULE_NO_TELEMETRY TR3( "No telemetria", "MULTI_TELEMETRY disattivato", "Nessuna telemetria (abilita MULTI_TELEMETRY)") +#define TR_MODULE_WAITFORBIND "Associa per caricare il protocollo" +#define TR_MODULE_BINDING "Associa" +#define TR_REBIND "Richiede associazione" +#define TR_REG_OK "Registrazione ok" +#define TR_BIND_OK "Associazione riuscita" #define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON" #define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF" #define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON" #define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem OFF" -#define TR_PROTOCOL_INVALID TR("Prot. invalid", "Protocol invalid") -#define TR_MODULE_STATUS TR(INDENT "Status", INDENT "Module Status") -#define TR_MODULE_SYNC TR(INDENT "Sync", INDENT "Module Sync") -#define TR_MULTI_SERVOFREQ TR("Servo rate", "Servo update rate") +#define TR_PROTOCOL_INVALID TR("Prot. invalido", "Protocollo invalido") +#define TR_MODULE_STATUS TR(INDENT "Stato", INDENT "Stato del modulo") +#define TR_MODULE_SYNC TR(INDENT "Sinc.", INDENT "Sinc. del modulo") +#define TR_MULTI_SERVOFREQ TR("Servo rate", "Aggiorna servo rate") #define TR_SYNCMENU "[Sync]" #define TR_LIMIT INDENT "Limiti" -#define TR_MINRSSI "Min Rssi" +#define TR_MINRSSI "Min. Rssi" #define TR_LATITUDE "Latitud." #define TR_LONGITUDE "Longitud." #define TR_GPSCOORD TR("GPS Coords", INDENT "Formato Coordinate") @@ -689,53 +689,53 @@ #define TR_VOLTAGE TR(INDENT "Voltagg.",INDENT "Voltaggio") #define TR_CURRENT TR(INDENT "Corrente",INDENT "Corrente") #define TR_SELECT_MODEL "Scegli Memo." -#define TR_CREATE_CATEGORY "Create Category" -#define TR_RENAME_CATEGORY "Rename Category" -#define TR_DELETE_CATEGORY "Delete Category" +#define TR_CREATE_CATEGORY "Crea Categoria" +#define TR_RENAME_CATEGORY "Rinomina Categoria" +#define TR_DELETE_CATEGORY "Cancella Categoria" #define TR_CREATE_MODEL "Crea Modello" -#define TR_DUPLICATE_MODEL "Duplicate Model" +#define TR_DUPLICATE_MODEL "Duplica Modello" #define TR_COPY_MODEL "Copia Modello" #define TR_MOVE_MODEL "Sposta Modello" #define TR_BACKUP_MODEL "Salva Modello" #define TR_DELETE_MODEL TR("Elim. Modello","Elimina Modello") // TODO merged into DELETEMODEL? #define TR_RESTORE_MODEL TR("Ripr. Modello","Ripristina Modello") -#define TR_DELETE_ERROR "Delete error" -#define TR_CAT_NOT_EMPTY "Category is not empty" +#define TR_DELETE_ERROR "Errore cancell." +#define TR_CAT_NOT_EMPTY "Categoria non vuota" #define TR_SDCARD_ERROR "Errore SD" #define TR_NO_SDCARD "No SDCARD" -#define TR_WAITING_FOR_RX "Waiting for RX..." -#define TR_WAITING_FOR_TX "Waiting for TX..." -#define TR_NO_TOOLS "No tools available" -#define TR_NORMAL "Normal" -#define TR_NOT_INVERTED "Not inv" -#define TR_NOT_CONNECTED "!Connected" -#define TR_CONNECTED "Connected" +#define TR_WAITING_FOR_RX "Attendo la RX..." +#define TR_WAITING_FOR_TX "Attendo la TX..." +#define TR_NO_TOOLS "Tools non disp." +#define TR_NORMAL "Normale" +#define TR_NOT_INVERTED "No inv." +#define TR_NOT_CONNECTED "!Connesso" +#define TR_CONNECTED "Connesso" #define TR_FLEX_915 "Flex 915MHz" #define TR_FLEX_868 "Flex 868MHz" -#define TR_16CH_WITHOUT_TELEMETRY TR("16CH without telem.", "16CH without telemetry") -#define TR_16CH_WITH_TELEMETRY TR("16CH with telem.", "16CH with telemetry") -#define TR_8CH_WITH_TELEMETRY TR("8CH with telem.", "8CH with telemetry") -#define TR_EXT_ANTENNA "Ext. antenna" +#define TR_16CH_WITHOUT_TELEMETRY TR("16CH senza telem.", "16CH senza telemetria") +#define TR_16CH_WITH_TELEMETRY TR("16CH con telem.", "16CH con telemetria") +#define TR_8CH_WITH_TELEMETRY TR("8CH con telem.", "8CH con telemetria") +#define TR_EXT_ANTENNA "Antenna Ext." #define TR_PIN "Pin" -#define TR_UPDATE_RX_OPTIONS "Update RX options?" -#define TR_UPDATE_TX_OPTIONS "Update TX options?" -#define TR_MODULES_RX_VERSION "Modules / RX version" -#define TR_MENU_MODULES_RX_VERSION "MODULES / RX VERSION" -#define TR_MENU_FIRM_OPTIONS "FIRMWARE OPTIONS" +#define TR_UPDATE_RX_OPTIONS "Agg. opzioni RX?" +#define TR_UPDATE_TX_OPTIONS "Agg. opzioni TX?" +#define TR_MODULES_RX_VERSION "Versioni Moduli / RX" +#define TR_MENU_MODULES_RX_VERSION "VERSIONI MODULI / RX" +#define TR_MENU_FIRM_OPTIONS "OPZIONI FIRMWARE" #define TR_GYRO "Gyro" -#define TR_STICKS_POTS_SLIDERS "Sticks/Pots/Sliders" -#define TR_PWM_STICKS_POTS_SLIDERS "PWM Sticks/Pots/Sliders" -#define TR_RF_PROTOCOL "RF Protocol" -#define TR_MODULE_OPTIONS "Module options" -#define TR_POWER "Power" -#define TR_NO_TX_OPTIONS "No TX options" +#define TR_STICKS_POTS_SLIDERS "Interruttori/Pots/Sliders" +#define TR_PWM_STICKS_POTS_SLIDERS "PWM Interruttori/Pots/Sliders" +#define TR_RF_PROTOCOL "Protocollo RF" +#define TR_MODULE_OPTIONS "Optioni modulo" +#define TR_POWER "Potenza" +#define TR_NO_TX_OPTIONS "No Opzioni TX" #define TR_RTC_BATT "RTC Batt" #define TR_POWER_METER_EXT "Power Meter (EXT)" #define TR_POWER_METER_INT "Power Meter (INT)" #define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" #define TR_SDCARD_FULL "SD Card Piena" -#define TR_NEEDS_FILE "NEEDS FILE" +#define TR_NEEDS_FILE "RICHIEDE FILE" #define TR_EXT_MULTI_SPEC "opentx-inv" #define TR_INT_MULTI_SPEC "stm-opentx-noinv" #define TR_INCOMPATIBLE "Incompatibile" @@ -748,14 +748,14 @@ #define TR_SWITCHWARN "CONTROLLI" #define TR_FAILSAFEWARN "FAILSAFE" #define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD") -#define TR_NIGHTLY_NOTSAFE "Version not safe to fly" -#define TR_WRONG_SDCARDVERSION TR("Expected ver: ","Expected version: ") -#define TR_WARN_RTC_BATTERY_LOW "RTC Battery low" -#define TR_WARN_MULTI_LOWPOWER "Low power mode" -#define TR_BATTERY "BATTERY" -#define TR_WRONG_PCBREV "Wrong PCB detected" -#define TR_EMERGENCY_MODE "EMERGENCY MODE" -#define TR_PCBREV_ERROR "PCB error" +#define TR_NIGHTLY_NOTSAFE "Versione non sicura per volare" +#define TR_WRONG_SDCARDVERSION TR("Richiede ver: ","Richiede versione: ") +#define TR_WARN_RTC_BATTERY_LOW "Batteria RTC scarica" +#define TR_WARN_MULTI_LOWPOWER "Modalità bassa pot." +#define TR_BATTERY "BATTERIA" +#define TR_WRONG_PCBREV "PCB sbagliato" +#define TR_EMERGENCY_MODE "MODALITA' EMERGENZA" +#define TR_PCBREV_ERROR "Errore PCB" #define TR_NO_FAILSAFE "Failsafe non settato" #define TR_KEYSTUCK "Tasto bloccato" #define TR_INVERT_THR "Inverti Mot?" @@ -810,11 +810,11 @@ #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" #if defined(PCBX9E) -#define TR_BLUETOOTH_MODES "---\0 ""Enabled\0 " +#define TR_BLUETOOTH_MODES "---\0 ""Attivo\0 " #else -#define TR_BLUETOOTH_MODES "---\0 ""Telemetry""Trainer\0" +#define TR_BLUETOOTH_MODES "---\0 ""Telemetria""Trainer\0" #endif -#define TR_SD_INFO_TITLE "SD INFO" +#define TR_SD_INFO_TITLE "INFO SD" #define TR_SD_TYPE "Tipo:" #define TR_SD_SPEED "Veloc.:" #define TR_SD_SECTORS "Settori:" @@ -826,33 +826,33 @@ #define TR_MENUGLOBALVARS "VARIABILI GLOBALI" #define TR_OWN "Fase" #define TR_DATE "Data" -#define TR_MONTHS { "Jan", "Fev", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } +#define TR_MONTHS { "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Auo", "Set", "Ott", "Nov", "Dic" } #define TR_ROTARY_ENCODER "R.E." #define TR_CHANNELS_MONITOR "MONITOR CANALI" #define TR_MIXERS_MONITOR "MONITOR MIXER" #define TR_PATH_TOO_LONG "Path troppo lungo" #define TR_VIEW_TEXT "Vedi testo" -#define TR_FLASH_BOOTLOADER "Flash bootloader" -#define TR_FLASH_EXTERNAL_DEVICE "Progr. Dispositivo Esterno" -#define TR_FLASH_RECEIVER_OTA "Flash receiver OTA" -#define TR_FLASH_BLUETOOTH_MODULE TR("Flash BT module", "Flash Bluetooth module") -#define TR_FLASH_POWER_MANAGEMENT_UNIT "Flash pwr mngt unit" -#define TR_CURRENT_VERSION TR("Current vers. ", "Current version: ") +#define TR_FLASH_BOOTLOADER "Prog. bootloader" +#define TR_FLASH_EXTERNAL_DEVICE "Progr. dispositivo Esterno" +#define TR_FLASH_RECEIVER_OTA "Prog. ricevente OTA" +#define TR_FLASH_BLUETOOTH_MODULE TR("Prog modulo BT", "Prog. modulo Bluetooth") +#define TR_FLASH_POWER_MANAGEMENT_UNIT "Programmazione PMU" +#define TR_CURRENT_VERSION TR("Vers. currente ", "Versione corrente: ") #define TR_FLASH_INTERNAL_MODULE "Progr. Modulo Interno" -#define TR_FLASH_INTERNAL_MULTI TR("Flash Int. Multi", "Flash Internal Multi") -#define TR_FLASH_EXTERNAL_MODULE "Flash external module" -#define TR_FLASH_EXTERNAL_MULTI TR("Flash Ext. Multi", "Flash External Multi") -#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error") -#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful" +#define TR_FLASH_INTERNAL_MULTI TR("Prog. Multi int.", "Prog. Multi interno") +#define TR_FLASH_EXTERNAL_MODULE "Prog. modulo esterno" +#define TR_FLASH_EXTERNAL_MULTI TR("Prog. Multi est.", "Prog. Multi esterno") +#define TR_FIRMWARE_UPDATE_ERROR TR("Errore agg. FW","Errore aggiornamento firmware") +#define TR_FIRMWARE_UPDATE_SUCCESS "Agg. riuscito" #define TR_WRITING "\032Scrivendo..." -#define TR_CONFIRM_FORMAT "Confermi Format?" +#define TR_CONFIRM_FORMAT "Confermi Formattazione?" #define TR_INTERNALRF "Modulo Interno" -#define TR_INTERNAL_MODULE TR("Int. module","Internal module") -#define TR_EXTERNAL_MODULE TR("Ext. module","External module") -#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX upgrade required" -#define TR_TELEMETRY_DISABLED "Telem. disabled" -#define TR_MORE_OPTIONS_AVAILABLE "More options available" -#define TR_NO_MODULE_INFORMATION "No module information" +#define TR_INTERNAL_MODULE TR("Modulo int.","Modulo interno") +#define TR_EXTERNAL_MODULE TR("Modulo est.","Modulo esterno") +#define TR_OPENTX_UPGRADE_REQUIRED "OpenTX richiede aggiornamento" +#define TR_TELEMETRY_DISABLED "Telem. disabilitata" +#define TR_MORE_OPTIONS_AVAILABLE "Altre opzioni assenti" +#define TR_NO_MODULE_INFORMATION "Nessuna info del modulo" #define TR_EXTERNALRF "Modulo esterno" #define TR_FAILSAFE "Modo failsafe" #define TR_FAILSAFESET TR("FAILSAFE","IMPOSTAZIONI FAILSAFE") @@ -869,14 +869,14 @@ #define TR_POWERMETER_ATTN "Attn" #define TR_POWERMETER_FREQ "Freq." #define TR_MENUTOOLS "TOOLS" -#define TR_TURN_OFF_RECEIVER "Turn off receiver" -#define TR_STOPPING "Stopping..." +#define TR_TURN_OFF_RECEIVER "Spegni la rx" +#define TR_STOPPING "Fermando..." #define TR_MENU_SPECTRUM_ANALYSER "SPECTRUM ANALYSER" #define TR_MENU_POWER_METER "POWER METER" -#define TR_SENSOR "SENSOR" +#define TR_SENSOR "SENSORE" #define TR_COUNTRYCODE TR("Codice Paese","Standard 2.4Ghz") -#define TR_USBMODE "USB Mode" -#define TR_JACKMODE "Jack Mode" +#define TR_USBMODE "Modo USB" +#define TR_JACKMODE "Modo JACK" #define TR_VOICELANG "Lingua Voce" #define TR_UNITSSYSTEM "Unità" #define TR_EDIT "Modifica" @@ -894,10 +894,10 @@ #define TR_RESET_TELEMETRY "Azzera Telemetria" #define TR_STATISTICS "Statistiche" #define TR_ABOUT_US "Info su" -#define TR_USB_JOYSTICK "USB Joystick (HID)" -#define TR_USB_MASS_STORAGE "USB Storage (SD)" -#define TR_USB_SERIAL "USB Serial (Debug)" -#define TR_SETUP_SCREENS "Setup screens" +#define TR_USB_JOYSTICK "Joystick USB (HID)" +#define TR_USB_MASS_STORAGE "Storage USB (SD)" +#define TR_USB_SERIAL "Seriale USB (Debug)" +#define TR_SETUP_SCREENS "Schermate conf." #define TR_MONITOR_SCREENS "Monitors" #define TR_AND_SWITCH "Inter. AND" #define TR_SF "CF" @@ -906,32 +906,32 @@ #define TR_BUZZER INDENT"Buzzer" #define TR_BYTES "Bytes" #define TR_MODULE_BIND "[Bind]" -#define TR_POWERMETER_ATTN_NEEDED "Attenuator needed" -#define TR_PXX2_SELECT_RX "Select RX..." +#define TR_POWERMETER_ATTN_NEEDED "Attenuatore necessario" +#define TR_PXX2_SELECT_RX "Seleziona RX..." #define TR_PXX2_DEFAULT "" -#define TR_BT_SELECT_DEVICE "Select device..." +#define TR_BT_SELECT_DEVICE "Seleziona device..." #define TR_DISCOVER "Discover" #define TR_BUTTON_INIT BUTTON("Init") -#define TR_WAITING "Waiting..." -#define TR_RECEIVER_DELETE "Delete receiver?" -#define TR_RECEIVER_RESET "Reset receiver?" -#define TR_SHARE "Share" +#define TR_WAITING "In attesa..." +#define TR_RECEIVER_DELETE "Cancello RX?" +#define TR_RECEIVER_RESET "Resetto RX?" +#define TR_SHARE "Condividere" #define TR_BIND "Bind" -#define TR_REGISTER TR("Reg", "Register") +#define TR_REGISTER TR("Reg", "Registrare") #define TR_MODULE_RANGE "[Range]" -#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS") -#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete")) +#define TR_RECEIVER_OPTIONS TR("OPZIONI RX", "OPZIONI RICEVENTE") +#define TR_DEL_BUTTON BUTTON(TR("Canc.", "Cancella")) #define TR_RESET_BTN "[Reset]" #define TR_DEBUG "Debug" -#define TR_KEYS_BTN BUTTON(TR("SW","Switches")) -#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs")) -#define TR_CALIBRATION "Calibration" +#define TR_KEYS_BTN BUTTON(TR("SW","Interruttori")) +#define TR_ANALOGS_BTN BUTTON(TR("Analogico","Analogici")) +#define TR_CALIBRATION "Calibrazione" #define TR_SET "[Set]" #define TR_TRAINER TR("Trainer","Maestro/Allievo") #define TR_ANTENNAPROBLEM CENTER "Problemi antenna TX!" #define TR_MODELIDUSED TR("ID già usato","ID Modello già usato") #define TR_MODULE "Modulo" -#define TR_RX_NAME "Rx Name" +#define TR_RX_NAME "Nome RX" #define TR_TELEMETRY_TYPE "Tipo Telemetria" #define TR_TELEMETRY_SENSORS "Sensori" #define TR_VALUE "Valore" @@ -942,23 +942,23 @@ #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" -#define TR_ANTENNA_MODES "Internal\0 ""Ask\0 ""Per model\0 ""Internal + External" +#define TR_ANTENNA_MODES "Interna\0 ""Chiedi\0 ""Per modello\0 ""Interna + esterna" #else #define LEN_ANTENNA_MODES "\011" -#define TR_ANTENNA_MODES "Internal\0""Ask\0 ""Per model""External" +#define TR_ANTENNA_MODES "Interna\0""Chiedi\0 ""Per modello""Esterna" #endif -#define TR_USE_INTERNAL_ANTENNA TR("Use int. antenna", "Use internal antenna") -#define TR_USE_EXTERNAL_ANTENNA TR("Use ext. antenna", "Use external antenna") -#define TR_ANTENNACONFIRM2 TR("Check antenna", "Make sure antenna is installed!") -#define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Requires non" -#define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Requires FCC" -#define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Requires EU" -#define TR_MODULE_PROTOCOL_WARN_LINE2 "certified firmware" +#define TR_USE_INTERNAL_ANTENNA TR("Usa antenna int.", "Usa antenna interna") +#define TR_USE_EXTERNAL_ANTENNA TR("Usa antenna est.", "Usa antenna esterna") +#define TR_ANTENNACONFIRM2 TR("Controlla antenna", "Controlla se l'antenna è installata!") +#define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Non richiede" +#define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Richiede FCC" +#define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Richiede EU" +#define TR_MODULE_PROTOCOL_WARN_LINE2 "firmware certificato" #define TR_LOWALARM INDENT "Allarme Basso" #define TR_CRITICALALARM INDENT "Allarme Critico" #define TR_RSSIALARM_WARN TR("RSSI","TELEMETRY RSSI") -#define TR_NO_RSSIALARM TR(INDENT "Alarms disabled", INDENT "Telemetry alarms disabled") -#define TR_DISABLE_ALARM TR(INDENT "Disable alarms", INDENT "Disable telemetry alarms") +#define TR_NO_RSSIALARM TR(INDENT "Allarmi disabilitati", INDENT "Allarmi telemetrici disabilitati") +#define TR_DISABLE_ALARM TR(INDENT "Allarmi disabilitati", INDENT "Allarmi telemetrici disabilitati") #define TR_ENABLE_POPUP "Abilita Popup" #define TR_DISABLE_POPUP "Disabilita Popup" #define TR_POPUP "Popup" @@ -1034,7 +1034,7 @@ #define TR_GVAR_HEADERS_FM8 "Value on FM8" // Horus footer descriptions -#define TR_LSW_DESCRIPTIONS { "Comparison type or function", "First variable", "Second variable or constant", "Second variable or constant", "Additional condition for line to be enabled", "Minimum ON duration of the logical switch", "Minimum TRUE duration for the switch to become ON" } +#define TR_LSW_DESCRIPTIONS { "Tipo o funzione di confronto", "Prima variabile", "Seconda variabile o costante", "Seconda variabile o costante", "Condizione aggiuntiva da abilitare linea", "Durata minima ON dell'interruttore logico", "Durata minima TRUE affinché l'interruttore si accenda" } // About screen #define TR_ABOUTUS TR(" INFO ", "INFO SU") @@ -1099,14 +1099,14 @@ #define TR_BG_VOLUME "Volume Sf" #define TR_TOP_BAR "Barra sup." -#define TR_FLASH_ERASE "Flash erase..." -#define TR_FLASH_WRITE "Flash write..." -#define TR_OTA_UPDATE "OTA update..." -#define TR_MODULE_RESET "Module reset..." -#define TR_UNKNOWN_RX "Unknown RX" -#define TR_UNSUPPORTED_RX "Unsupported RX" -#define TR_OTA_UPDATE_ERROR "OTA update error" -#define TR_DEVICE_RESET "Device reset..." +#define TR_FLASH_ERASE "Cancello flash..." +#define TR_FLASH_WRITE "Scrivo flash..." +#define TR_OTA_UPDATE "Aggiorn. OTA..." +#define TR_MODULE_RESET "Reset modulo..." +#define TR_UNKNOWN_RX "RX sconociuta" +#define TR_UNSUPPORTED_RX "RX non compatibile" +#define TR_OTA_UPDATE_ERROR "Errore agg. OTA" +#define TR_DEVICE_RESET "Resetto dispositivo..." #define TR_ALTITUDE INDENT "Altitudine" #define TR_SCALE "Scala" #define TR_VIEW_CHANNELS "Vedi Canali" @@ -1121,7 +1121,7 @@ #define TR_CELLINDEX "Indice cella" #define TR_LOGS "Logs" #define TR_OPTIONS "Opzioni" -#define TR_FIRMWARE_OPTIONS "Firmware options" +#define TR_FIRMWARE_OPTIONS "Opzioni firmware" #define TR_ALTSENSOR "Sensore Alt" #define TR_CELLSENSOR "Sensore Cell" @@ -1140,20 +1140,20 @@ #define TR_STOP_DISCOVER_SENSORS "Ferma ricerca.." #define TR_DELETE_ALL_SENSORS "Elimina tutti i sensori" #define TR_CONFIRMDELETE "Confermi " LCDW_128_480_LINEBREAK "eliminazione ?" -#define TR_SELECT_WIDGET "Select widget" -#define TR_REMOVE_WIDGET "Remove widget" -#define TR_WIDGET_SETTINGS "Widget settings" -#define TR_REMOVE_SCREEN "Remove screen" -#define TR_SETUP_WIDGETS "Setup widgets" -#define TR_USER_INTERFACE "User interface" -#define TR_THEME "Theme" -#define TR_SETUP "Setup" -#define TR_MAINVIEWX "Main view X" +#define TR_SELECT_WIDGET "Seleziona widget" +#define TR_REMOVE_WIDGET "Rimuovi widget" +#define TR_WIDGET_SETTINGS "Settaggio widget" +#define TR_REMOVE_SCREEN "Rimuovi schermo" +#define TR_SETUP_WIDGETS "Setta widgets" +#define TR_USER_INTERFACE "Interfaccia utente" +#define TR_THEME "Tema" +#define TR_SETUP "Imposta" +#define TR_MAINVIEWX "Vista princ. X" #define TR_LAYOUT "Layout" -#define TR_ADDMAINVIEW "Add main view" -#define TR_BACKGROUND_COLOR "Background color" -#define TR_MAIN_COLOR "Main color" -#define TR_TEXT_VIEWER "Text Viewer" +#define TR_ADDMAINVIEW "Aggiungi vista princ." +#define TR_BACKGROUND_COLOR "Colore background" +#define TR_MAIN_COLOR "Colore principale" +#define TR_TEXT_VIEWER "Visualizzatore testi" #define TR_MENU_INPUTS "\314Ingressi" #define TR_MENU_LUA "\322Lua scripts" @@ -1171,8 +1171,8 @@ #define TR_MENU_DISPLAY "DISPLAY" #define TR_MENU_OTHER "Altro" #define TR_MENU_INVERT "Inverti" -#define TR_JITTER_FILTER "ADC Filter" -#define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_JITTER_FILTER "Filtro ADC" +#define TR_RTC_CHECK TR("Controllo RTC", "Controllo voltaggio RTC") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" From 2017c724f4112800b2bafbdd044e72a588f4088a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 23 Oct 2019 08:21:35 +0200 Subject: [PATCH 213/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 93e5362b2..de05cd9c7 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1613,3 +1613,4 @@ Michael Tessler John Beech Stefan Möst Thomas McGraw +Bruno N Russo Jr From 71230537a2750eab333c5f7be07525cd14700117 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 23 Oct 2019 09:02:59 +0200 Subject: [PATCH 214/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index de05cd9c7..afd6266c6 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1614,3 +1614,4 @@ John Beech Stefan Möst Thomas McGraw Bruno N Russo Jr +Daniel Eikenkötter From 4f300d4b21e3246af1a18c7107b47b9116574433 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 23 Oct 2019 11:47:34 +0200 Subject: [PATCH 215/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index afd6266c6..8a09af536 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1615,3 +1615,4 @@ Stefan Möst Thomas McGraw Bruno N Russo Jr Daniel Eikenkötter +Guy Poignonec From 1c977c5821e6c0caf9fcabb1f9c91661cdc88388 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 23 Oct 2019 19:02:37 +0200 Subject: [PATCH 216/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 8a09af536..d2e71d520 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1616,3 +1616,4 @@ Thomas McGraw Bruno N Russo Jr Daniel Eikenkötter Guy Poignonec +Gérard Falaise From c8160f5f9bff24f8034384c5b6a559ead0279f23 Mon Sep 17 00:00:00 2001 From: WismyYao Date: Thu, 24 Oct 2019 14:59:46 +0800 Subject: [PATCH 217/257] Wismy/x10(s) upgrade kit (#6981) X10(S) / X12S Upgrade Kit supported --- .gitmodules | 3 ++ radio/src/CMakeLists.txt | 4 +++ radio/src/opentx.h | 4 +++ radio/src/pulses/pulses.cpp | 21 +++++++------- radio/src/pulses/pulses.h | 1 + radio/src/pulses/pxx2.cpp | 27 ++++++++++++++++-- radio/src/pulses/pxx2.h | 39 +++++++++++++++++--------- radio/src/targets/horus/CMakeLists.txt | 4 +++ radio/src/telemetry/frsky_pxx2.cpp | 24 ++++++++++++++++ radio/src/thirdparty/libACCESS | 1 + 10 files changed, 102 insertions(+), 26 deletions(-) create mode 160000 radio/src/thirdparty/libACCESS diff --git a/.gitmodules b/.gitmodules index a761ef67a..f25a4edaf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "radio/src/thirdparty/GCS_MAVLink/include_v1.0"] path = radio/src/thirdparty/GCS_MAVLink/include_v1.0 url = https://github.com/mavlink/c_library_v1.git +[submodule "radio/src/thirdparty/libACCESS"] + path = radio/src/thirdparty/libACCESS + url = https://github.com/FrSky-OS/libACCESS.git diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 1f7c2c542..8a84c983a 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -452,6 +452,10 @@ if(NOT MSVC) # these are in addition to CMAKE_CXX_FLAGS set(CMAKE_EXE_LINKER_FLAGS "-lm -T${RADIO_SRC_DIRECTORY}/${LINKER_SCRIPT} -Wl,-Map=firmware.map,--cref,--no-warn-mismatch,--gc-sections") + if(ACCESS_LIB) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--whole-archive ${RADIO_SRC_DIRECTORY}/${THIRDPARTY_DIR}/libACCESS/libAccess.a -Wl,--no-whole-archive") + endif() + if(SEMIHOSTING) add_definitions(-DSEMIHOSTING) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --specs=rdimon.specs") diff --git a/radio/src/opentx.h b/radio/src/opentx.h index c448edae0..218a3b9fb 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1397,4 +1397,8 @@ inline bool isAsteriskDisplayed() return globalData.unexpectedShutdown; } +#if defined(ACCESS_LIB) +#include "thirdparty/libACCESS/libAccess.h" +#endif + #endif // _OPENTX_H_ diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp index 6d869e484..63b43943f 100755 --- a/radio/src/pulses/pulses.cpp +++ b/radio/src/pulses/pulses.cpp @@ -322,14 +322,14 @@ static void enablePulsesInternalModule(uint8_t protocol) } } -void setupPulsesInternalModule(uint8_t protocol) +bool setupPulsesInternalModule(uint8_t protocol) { switch (protocol) { #if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART) case PROTOCOL_CHANNELS_PXX1_PULSES: intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE); scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); - break; + return true; #endif #if defined(PXX1) && defined(INTMODULE_USART) @@ -338,12 +338,13 @@ void setupPulsesInternalModule(uint8_t protocol) #if !defined(INTMODULE_HEARTBEAT) scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX1_SERIAL_PERIOD); #endif - break; + return true; #endif #if defined(PXX2) case PROTOCOL_CHANNELS_PXX2_HIGHSPEED: - intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE); + { + bool result = intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE); if (moduleState[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleState[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER) { scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_TOOLS_PERIOD); } @@ -352,25 +353,26 @@ void setupPulsesInternalModule(uint8_t protocol) scheduleNextMixerCalculation(INTERNAL_MODULE, PXX2_PERIOD); } #endif - break; + return result; + } #endif #if defined(PCBTARANIS) && defined(INTERNAL_MODULE_PPM) case PROTOCOL_CHANNELS_PPM: setupPulsesPPMInternalModule(); scheduleNextMixerCalculation(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE)); - break; + return true; #endif #if defined(INTERNAL_MODULE_MULTI) case PROTOCOL_CHANNELS_MULTIMODULE: setupPulsesMultiInternalModule(); scheduleNextMixerCalculation(INTERNAL_MODULE, MULTIMODULE_PERIOD); - break; + return true; #endif default: - break; + return true; } } @@ -387,8 +389,7 @@ bool setupPulsesInternalModule() return false; } else { - setupPulsesInternalModule(protocol); - return true; + return setupPulsesInternalModule(protocol); } } #endif diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 8dc12ee68..b7b5e5f27 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -74,6 +74,7 @@ enum ModuleSettingsMode MODULE_MODE_SHARE, MODULE_MODE_RANGECHECK, MODULE_MODE_RESET, + MODULE_MODE_AUTHENTICATION, MODULE_MODE_OTA_UPDATE, }; diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index baa421de7..13b2f231c 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -357,10 +357,31 @@ void Pxx2Pulses::sendOtaUpdate(uint8_t module, const char * rxName, uint32_t add extmoduleSendNextFrame(); } -void Pxx2Pulses::setupFrame(uint8_t module) +void Pxx2Pulses::setupAuthenticationFrame(uint8_t module, uint8_t mode, const uint8_t * outputMessage) +{ + initFrame(); + + addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_AUTHENTICATION); + + Pxx2Transport::addByte(mode); + if (outputMessage) { + for (uint8_t i = 0; i < 16; i++) { + Pxx2Transport::addByte(outputMessage[i]); + } + } + + endFrame(); +} + +bool Pxx2Pulses::setupFrame(uint8_t module) { if (moduleState[module].mode == MODULE_MODE_OTA_UPDATE) - return; + return false; + + if (moduleState[module].mode == MODULE_MODE_AUTHENTICATION) { + moduleState[module].mode = MODULE_MODE_NORMAL; + return false; + } initFrame(); @@ -413,6 +434,8 @@ void Pxx2Pulses::setupFrame(uint8_t module) } endFrame(); + + return true; } bool Pxx2OtaUpdate::waitStep(uint8_t step, uint8_t timeout) diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index ed8c07418..23eae9934 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -25,16 +25,17 @@ #include "io/frsky_pxx2.h" #include "./pxx.h" -#define PXX2_TYPE_C_MODULE 0x01 - #define PXX2_TYPE_ID_REGISTER 0x01 - #define PXX2_TYPE_ID_BIND 0x02 - #define PXX2_TYPE_ID_CHANNELS 0x03 - #define PXX2_TYPE_ID_TX_SETTINGS 0x04 - #define PXX2_TYPE_ID_RX_SETTINGS 0x05 - #define PXX2_TYPE_ID_HW_INFO 0x06 - #define PXX2_TYPE_ID_SHARE 0x07 - #define PXX2_TYPE_ID_RESET 0x08 - #define PXX2_TYPE_ID_TELEMETRY 0xFE +#define PXX2_TYPE_C_MODULE 0x01 + #define PXX2_TYPE_ID_REGISTER 0x01 + #define PXX2_TYPE_ID_BIND 0x02 + #define PXX2_TYPE_ID_CHANNELS 0x03 + #define PXX2_TYPE_ID_TX_SETTINGS 0x04 + #define PXX2_TYPE_ID_RX_SETTINGS 0x05 + #define PXX2_TYPE_ID_HW_INFO 0x06 + #define PXX2_TYPE_ID_SHARE 0x07 + #define PXX2_TYPE_ID_RESET 0x08 + #define PXX2_TYPE_ID_AUTHENTICATION 0x09 + #define PXX2_TYPE_ID_TELEMETRY 0xFE #define PXX2_TYPE_C_POWER_METER 0x02 #define PXX2_TYPE_ID_POWER_METER 0x01 @@ -75,7 +76,10 @@ enum PXX2ModuleModelID { PXX2_MODULE_R9M_LITE_PRO, PXX2_MODULE_ISRM_N, PXX2_MODULE_ISRM_S_X9, - PXX2_MODULE_ISRM_S_X10 + PXX2_MODULE_ISRM_S_X10E, + PXX2_MODULE_XJT_LITE, + PXX2_MODULE_ISRM_S_X10S, + PXX2_MODULE_ISRM_S_X9LITE, }; static const char * const PXX2ModulesNames[] = { @@ -89,7 +93,10 @@ static const char * const PXX2ModulesNames[] = { "R9MLite-PRO", "ISRM-N", "ISRM-S-X9", - "ISRM-S-X10", + "ISRM-S-X10E", + "XJT Lite", + "ISRM-S-X10S", + "ISRM-S-X9Lite" }; inline const char * getPXX2ModuleName(uint8_t modelId) @@ -128,7 +135,10 @@ static const uint8_t PXX2ModuleOptions[] = { 0b00000110, // R9MLite-PRO 0b00000100, // ISRM-N 0b00000100, // ISRM-S-X9 - 0b00000101, // ISRM-S-X10 + 0b00000101, // ISRM-S-X10E + 0b00000001, // XJT_LITE + 0b00000101, // ISRM-S-X10S + 0b00000101, // ISRM-S-X9LITE }; inline uint8_t getPXX2ModuleOptions(uint8_t modelId) @@ -332,7 +342,8 @@ class Pxx2Pulses: public Pxx2Transport { friend class Pxx2OtaUpdate; public: - void setupFrame(uint8_t module); + bool setupFrame(uint8_t module); + void setupAuthenticationFrame(uint8_t module, uint8_t mode, const uint8_t * outputMessage); protected: void setupHardwareInfoFrame(uint8_t module); diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index bc16f5961..1673dff08 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -109,6 +109,10 @@ if(INTERNAL_MODULE_PXX2) set(PXX2 ON) add_definitions(-DHARDWARE_INTERNAL_MODULE) add_definitions(-DINTERNAL_MODULE_PXX2) + if (NOT PCBREV STREQUAL EXPRESS) + set(ACCESS_LIB ON) + add_definitions(-DACCESS_LIB) + endif() endif() if(INTERNAL_MODULE_MULTI) diff --git a/radio/src/telemetry/frsky_pxx2.cpp b/radio/src/telemetry/frsky_pxx2.cpp index d41ef1add..582e098a4 100644 --- a/radio/src/telemetry/frsky_pxx2.cpp +++ b/radio/src/telemetry/frsky_pxx2.cpp @@ -39,6 +39,8 @@ class Pxx2Telemetry static void processPowerMeterFrame(uint8_t module, uint8_t * frame); + static void processAuthenticationFrame(uint8_t module, uint8_t * frame); + public: }; @@ -219,6 +221,24 @@ void processTelemetryFrame(uint8_t module, uint8_t * frame) } } +#if defined(ACCESS_LIB) +void processAuthenticationFrame(uint8_t module, uint8_t * frame) +{ + uint8_t cryptoType = frame[3]; + uint8_t messageDigest[16] = {0}; + + if (INTERNAL_MODULE == module && accessCRL(cryptoType, frame+4, messageDigest)) { + moduleState[module].mode = MODULE_MODE_AUTHENTICATION; + Pxx2Pulses & pxx2 = intmodulePulsesData.pxx2; + pxx2.setupAuthenticationFrame(module, cryptoType, (const uint8_t *)messageDigest); + intmoduleSendBuffer(pxx2.getData(), pxx2.getSize()); + // we remain in AUTHENTICATION mode to avoid a CHANNELS frame is sent at the end of the mixing process + } +} +#else +#define processAuthenticationFrame(module, frame) +#endif + void processSpectrumAnalyserFrame(uint8_t module, uint8_t * frame) { if (moduleState[module].mode != MODULE_MODE_SPECTRUM_ANALYSER) { @@ -311,6 +331,10 @@ void processModuleFrame(uint8_t module, uint8_t *frame) processTelemetryFrame(module, frame); break; + case PXX2_TYPE_ID_AUTHENTICATION: + processAuthenticationFrame(module, frame); + break; + case PXX2_TYPE_ID_RESET: processResetFrame(module, frame); break; diff --git a/radio/src/thirdparty/libACCESS b/radio/src/thirdparty/libACCESS new file mode 160000 index 000000000..1bae46726 --- /dev/null +++ b/radio/src/thirdparty/libACCESS @@ -0,0 +1 @@ +Subproject commit 1bae467262bbe8232111a6baee7195850cef2531 From 039febefc713e3e146a121b7717f6cd75eb5fb59 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 24 Oct 2019 09:00:24 +0200 Subject: [PATCH 218/257] - max chan for multi dsm is 12 (as oposed to dsm hack module : 6) (#6997) - on multi change, set channelCount to max (was already done for non multi protocol change) --- companion/src/modeledit/setup.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index 2cc34455b..271dcd8b6 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -396,7 +396,7 @@ int ModulePanel::getMaxChannelCount() return 6; case PULSES_MULTIMODULE: if (module.multi.rfProtocol == MODULE_SUBTYPE_MULTI_DSM2) - return 6; + return 12; else return 16; break; @@ -766,6 +766,7 @@ void ModulePanel::onMultiProtocolChanged(int index) if (module.multi.customProto) maxSubTypes=8; module.subType = std::min(module.subType, maxSubTypes -1); + module.channelsCount = getMaxChannelCount(); update(); emit modified(); lock = false; From 5801ad71991354f3d3e6e51f5797e1e0fa6eaec2 Mon Sep 17 00:00:00 2001 From: Marco Robustini Date: Thu, 24 Oct 2019 09:01:29 +0200 Subject: [PATCH 219/257] IT language: voice and text updated for OpenTX V2.3.x (#6993) Update it.h.txt --- radio/src/translations/it.h.txt | 321 ++++++++++++++++---------------- radio/util/tts_it.py | 2 +- 2 files changed, 162 insertions(+), 161 deletions(-) diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 54314e60c..5359c97fc 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -20,6 +20,7 @@ */ // IT translations author: Romolo Manfredini +// IT integrations for OpenTX V2.3.x author: Marco Robustini /* * !!!!! DO NOT EDIT it.h - EDIT it.h.txt INSTEAD !!!!!!! @@ -69,13 +70,13 @@ #endif #define LEN_SWTYPES "\006" -#define TR_SWTYPES "None\0 ""Toggle""2POS\0 ""3POS\0" +#define TR_SWTYPES "Dis.\0 ""Toggle""2POS\0 ""3POS\0" #define LEN_POTTYPES TR("\013","\017") -#define TR_POTTYPES TR("None\0 ""Pot w. det\0""Multipos\0 ""Pot\0 ", "None\0 ""Pot. con centro""Inter. Multipos""Potenziometro\0 ") +#define TR_POTTYPES TR("Dis.\0 ""Pot c. fer\0""Multipos\0 ""Pot\0 ", "Dis.\0 ""Pot. con centro""Inter. Multipos""Potenziometro\0 ") #define LEN_SLIDERTYPES "\006" -#define TR_SLIDERTYPES "Niente""Slider" +#define TR_SLIDERTYPES "Disat.""Slider" #define LEN_VLCD "\006" #define TR_VLCD "NormalOptrex" @@ -87,15 +88,15 @@ #define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europa\0") #define LEN_USBMODES TR("\006", "\010") -#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ") +#define TR_USBMODES TR("Chiedi\0 ""Joyst\0""Storage""Seriale", "Chiedi\0 ""Joystick""Storage\0""Seriale\0 ") #define LEN_JACKMODES "\007" -#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer" +#define TR_JACKMODES "Chiedi\0 ""Audio\0 ""Trainer" #define LEN_TELEMETRY_PROTOCOLS "\017" #define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry" -#define TR_MULTI_CUSTOM "Custom" +#define TR_MULTI_CUSTOM "Person." #define LEN_VTRIMINC "\006" #define TR_VTRIMINC "Exp ""ExFine""Fine ""Medio ""Ampio " @@ -107,7 +108,7 @@ #define TR_VBEEPCOUNTDOWN "NienteSuoni\0Voce\0 Vibra\0" #define LEN_VVARIOCENTER "\006" -#define TR_VVARIOCENTER "Tono\0 ""Silent" +#define TR_VVARIOCENTER "Tono\0 ""Silenz." #define LEN_CURVE_TYPES "\010" #define TR_CURVE_TYPES "Fisso\0 ""Modific." @@ -202,9 +203,9 @@ #define TR_SF_BG_MUSIC "Musica Sf\0 ""Musica Sf ||\0" #if defined(SDCARD) - #define TR_SDCLOGS "SDCARD Logs\0 " + #define TR_SDCLOGS "Logs SDCard\0 " #else - #define TR_SDCLOGS "[SDCARD Logs]\0" + #define TR_SDCLOGS "[Logs SDCard]\0" #endif #if defined(GVARS) @@ -373,7 +374,7 @@ #define TR_VTRAINER_SLAVE_JACK "Allievo/Jack\0 " #define TR_VTRAINER_MASTER_SBUS_MODULE "Master/Modulo SBUS" #define TR_VTRAINER_MASTER_CPPM_MODULE "Master/Modulo CPPM" -#define TR_VTRAINER_MASTER_BATTERY "Master/Serial\0 " +#define TR_VTRAINER_MASTER_BATTERY "Master/Seriale\0 " #define TR_VTRAINER_BLUETOOTH TR("Master/BT\0 ""Slave/BT\0 ", "Master/Bluetooth\0 ""Slave/Bluetooth\0 ") #define TR_VTRAINER_MULTI "Master/Multi" @@ -431,53 +432,53 @@ #endif #define TR_MENUWHENDONE CENTER "\007" TR_ENTER " Conferma" -#define TR_FREE "disp" +#define TR_FREE "Disp." #define TR_DELETEMODEL "Elimina modello?" #define TR_COPYINGMODEL "Copia in corso.." #define TR_MOVINGMODEL "Spostamento..." #define TR_LOADINGMODEL "Caricamento..." #define TR_NAME "Nome" -#define TR_MODELNAME "Nome modello" +#define TR_MODELNAME TR(INDENT"Nome Mode.", INDENT"Nome Modello") #define TR_PHASENAME "Nome fase" #define TR_MIXNAME "Nome mix" #define TR_INPUTNAME "Nome Ingr." #define TR_EXPONAME "Nome expo" #define TR_BITMAP "Immagine" -#define TR_TIMER TR("Timer","Timer ") -#define TR_ELIMITS TR("Limiti.E","Limiti Estesi") -#define TR_ETRIMS TR("Trim Ext","Trim Estesi") +#define TR_TIMER TR(INDENT"Timer", INDENT"Timer ") +#define TR_ELIMITS TR(INDENT"Limiti.E", INDENT"Limiti Estesi") +#define TR_ETRIMS TR(INDENT"Trim Ext", INDENT"Trim Estesi") #define TR_TRIMINC "Passo Trim" -#define TR_DISPLAY_TRIMS "Mostra Trims" -#define TR_TTRACE TR("T-Source", INDENT "Sorgente Motore") -#define TR_TTRIM TR("T-Trim", INDENT "Trim Motore") -#define TR_BEEPCTR TR("Ctr Beep","Beep al centro") -#define TR_USE_GLOBAL_FUNCS "Usa Funz Globali" +#define TR_DISPLAY_TRIMS TR(INDENT "Mos. Trims", INDENT "Mostra Trims") +#define TR_TTRACE TR(INDENT "So. motore", INDENT "Sorgente Motore") +#define TR_TTRIM TR(INDENT "Trim Mot.", INDENT "Trim Motore") +#define TR_BEEPCTR TR(INDENT "Beep al c.", INDENT "Beep al centro") +#define TR_USE_GLOBAL_FUNCS "Usa Funz. Globali" #if defined(PCBSKY9X) && defined(REVX) - #define TR_OUTPUT_TYPE INDENT "Output" + #define TR_OUTPUT_TYPE INDENT "Uscita" #endif -#define TR_PROTO TR(INDENT "Proto", INDENT "Protocollo") - #define TR_PPMFRAME INDENT "PPM frame" +#define TR_PROTO TR(INDENT "Protoc.", INDENT "Protocollo") + #define TR_PPMFRAME INDENT "Frame PPM" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") -#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") +#define STR_WARN_BATTVOLTAGE TR(INDENT "Uscita è VBAT: ", INDENT "Att.: livel. uscita è VBAT: ") #define TR_MS "ms" -#define TR_FREQUENCY INDENT "Frequency" +#define TR_FREQUENCY INDENT "Frequenza" #define TR_SWITCH "Inter." #define TR_TRIMS "Trims" #define TR_FADEIN "Diss.In" #define TR_FADEOUT "Diss.Out" #define TR_DEFAULT "(Predefinita)" -#define TR_CHECKTRIMS CENTER "\006Check\012Trims" +#define TR_CHECKTRIMS CENTER "\006Contr.\012Trims" #define OFS_CHECKTRIMS CENTER_OFS+(9*FW) #define TR_SWASHTYPE "Tipo Ciclico" -#define TR_COLLECTIVE TR("Collettivo","Origine Collettivo") -#define TR_AILERON TR("Lateral cyc.", "Lateral cyc. source") -#define TR_ELEVATOR TR("Long. cyc.", "Long. cyc. source") +#define TR_COLLECTIVE TR(INDENT"Collettivo", INDENT"Origine Collettivo") +#define TR_AILERON TR(INDENT"Cic. later.", INDENT"Sorg. cic. later.") +#define TR_ELEVATOR TR(INDENT"Cic. long.", INDENT"Sorg. cic. long.") #define TR_SWASHRING "Anello Ciclico" -#define TR_ELEDIRECTION TR("Direzione ELE","Direzione Long. cyc.") -#define TR_AILDIRECTION TR("Direzione AIL","Direzione Lateral cyc.") -#define TR_COLDIRECTION TR("Direzione PIT","Direzione Coll. Passo") +#define TR_ELEDIRECTION TR(INDENT"Direzione ELE", INDENT"Direzione cic. long.") +#define TR_AILDIRECTION TR(INDENT"Direzione AIL", INDENT"Direzione cic. lat.") +#define TR_COLDIRECTION TR(INDENT"Direzione PIT", INDENT"Direzione passo coll.") #define TR_MODE "Modo" -#define TR_SUBTYPE INDENT "Subtype" +#define TR_SUBTYPE INDENT "Sottotipo" #define TR_NOFREEEXPO "Expo pieni!" #define TR_NOFREEMIXER "Mixer pieni!" #define TR_SOURCE "Sorg." @@ -494,12 +495,12 @@ #define TR_MIXWARNING "Avviso" #define TR_OFF "OFF" #define TR_ANTENNA "Antenna" -#define TR_NO_INFORMATION TR("No info", "No information") +#define TR_NO_INFORMATION TR(INDENT"No info", INDENT"No informazione") #define TR_MULTPX "MultPx" #define TR_DELAYDOWN "Post.Giù " -#define TR_DELAYUP "Post.Sù" +#define TR_DELAYUP "Post.Su" #define TR_SLOWDOWN "Rall.Giù " -#define TR_SLOWUP "Rall.Sù" +#define TR_SLOWUP "Rall.Su" #define TR_MIXER "MIXER" #define TR_CV "CV" #define TR_GV TR("G", "GV") @@ -510,53 +511,53 @@ #define TR_ALARM TR(INDENT"Allar.", INDENT"Allarme") #define TR_USRDATA "Dati" #define TR_BLADES INDENT"Pale" -#define TR_SCREEN "Schermo " +#define TR_SCREEN TR(INDENT"Scher. ", INDENT"Schermo ") #define TR_SOUND_LABEL "Suono" #define TR_LENGTH INDENT"Durata" #define TR_BEEP_LENGTH INDENT "Lung. Beep" #define TR_SPKRPITCH INDENT"Tono" -#define TR_HAPTIC_LABEL "Vibraz" +#define TR_HAPTIC_LABEL "Vibrazione" #define TR_HAPTICSTRENGTH INDENT"Forza" #define TR_GYRO_LABEL "Gyro" #define TR_GYRO_OFFSET "Offset" #define TR_GYRO_MAX "Max" #define TR_CONTRAST "Contrasto" #define TR_ALARMS_LABEL "Allarmi" -#define TR_BATTERY_RANGE TR("Interv. Batt", "Intervallo batteria") -#define TR_BATTERYWARNING INDENT"Avviso batteria" -#define TR_INACTIVITYALARM INDENT"Inattivita'" -#define TR_MEMORYWARNING INDENT"Avviso memoria" +#define TR_BATTERY_RANGE TR(INDENT "Int. Batt.", INDENT "Intervallo batteria") +#define TR_BATTERYWARNING TR(INDENT "Avv. Batt.", INDENT "Avviso Batteria") +#define TR_INACTIVITYALARM INDENT"Inattività" +#define TR_MEMORYWARNING TR(INDENT "Avv. Mem.", INDENT "Avviso Memoria") #define TR_ALARMWARNING INDENT"Spegni suono" -#define TR_RSSISHUTDOWNALARM TR(INDENT "Rssi Shutdown", INDENT "Check Rssi on Shutdown") -#define TR_MODEL_STILL_POWERED "Model still powered" -#define TR_MODEL_SHUTDOWN "Shutdown ?" -#define TR_PRESS_ENTER_TO_CONFIRM "Press enter to confirm" +#define TR_RSSISHUTDOWNALARM TR(INDENT "RSSI Shut.", INDENT "Control. RSSI al Shutdown") +#define TR_MODEL_STILL_POWERED "Modello ancora acceso" +#define TR_MODEL_SHUTDOWN "Shutdown?" +#define TR_PRESS_ENTER_TO_CONFIRM "Premi [ENT] per confermare" #define TR_THROTTLE_LABEL "Motore" -#define TR_THROTTLEREVERSE TR("Mot inv.", INDENT "Motore Inverso") +#define TR_THROTTLEREVERSE TR(INDENT "Mot inv.", INDENT "Motore Inverso") #define TR_MINUTEBEEP "Minuto" #define TR_BEEPCOUNTDOWN TR(INDENT"Conto rov", INDENT"Conto rovescia") #define TR_PERSISTENT TR(INDENT"Persist.", INDENT"Persistente") -#define TR_BACKLIGHT_LABEL TR("Retroillum.", "Retroilluminazione") +#define TR_BACKLIGHT_LABEL TR(INDENT "Retroillu.", INDENT "Retroilluminazione") #define TR_BLDELAY INDENT"Durata" -#define TR_BLONBRIGHTNESS TR(INDENT"Lumin. ON",INDENT"Luminosità ON") -#define TR_BLOFFBRIGHTNESS TR(INDENT"Lumin. OFF",INDENT"Luminosità OFF") +#define TR_BLONBRIGHTNESS TR(INDENT"Lumin. ON", INDENT"Luminosità ON") +#define TR_BLOFFBRIGHTNESS TR(INDENT"Lumin. OFF", INDENT"Luminosità OFF") #define TR_BLCOLOR INDENT "Colore" -#define TR_SPLASHSCREEN TR("Schermo avvio", "Schermata di avvio") -#define TR_PWR_ON_DELAY "Pwr On delay" -#define TR_PWR_OFF_DELAY "Pwr Off delay" -#define TR_THROTTLEWARNING TR("All. Mot.", INDENT "Allarme Motore") -#define TR_SWITCHWARNING TR("Avv. Int.", INDENT "Avviso Interr.") +#define TR_SPLASHSCREEN TR(INDENT "Sch. avvio", INDENT "Schermata d'avvio") +#define TR_PWR_ON_DELAY "Rit. PWR ON" +#define TR_PWR_OFF_DELAY "Rit. PWR OFF" +#define TR_THROTTLEWARNING TR(INDENT "All. Mot.", INDENT "Allarme Motore") +#define TR_SWITCHWARNING TR(INDENT "Avv. Int.", INDENT "Avviso Interr.") #define TR_POTWARNINGSTATE TR(INDENT "Pot&Slid.", INDENT "Pots & sliders") -#define TR_SLIDERWARNING TR(INDENT "Slid. pos.", INDENT "Slider positions") -#define TR_POTWARNING TR("Avv. Pot.", INDENT "Avviso Pot.") +#define TR_SLIDERWARNING TR(INDENT "Pos. slid.", INDENT "Posizione slider") +#define TR_POTWARNING TR(INDENT "Avv. Pot.", INDENT "Avviso Pot.") #define TR_TIMEZONE "Ora locale" -#define TR_ADJUST_RTC TR("Aggiusta RTC", INDENT "Aggiusta RTC") +#define TR_ADJUST_RTC TR(INDENT "Agg. RTC", INDENT "Aggiusta RTC") #define TR_GPS "GPS" -#define TR_RXCHANNELORD "Ordine ch RX" +#define TR_RXCHANNELORD "Ordine CH RX" #define TR_STICKS "Sticks" #define TR_POTS "Pot." #define TR_SWITCHES "Interutt." -#define TR_SWITCHES_DELAY "Ritardo voce FV" +#define TR_SWITCHES_DELAY TR(INDENT "Rit. V. FV", INDENT "Ritardo Voce FV") #define TR_SLAVE "Allievo" #define TR_MODESRC "Modo\006% Origine" #define TR_MULTIPLIER "Moltiplica" @@ -564,11 +565,11 @@ #define TR_VTRIM "Trim- +" #define TR_BG "BG:" #if defined(PCBHORUS) - #define TR_MENUTOSTART "Press [Enter] to start" - #define TR_SETMIDPOINT "Center sticks/pots/sliders and press [Enter]" - #define TR_MOVESTICKSPOTS "Move sticks, pots and sliders and press [Enter]" + #define TR_MENUTOSTART "Premi [ENT] per partire" + #define TR_SETMIDPOINT "Centra sticks/pots/sliders e premi [ENT]" + #define TR_MOVESTICKSPOTS "Muovi sticks/pots/sliders e premi [ENT]" #elif defined(COLORLCD) - #define TR_MENUTOSTART TR_ENTER " TO START" + #define TR_MENUTOSTART TR_ENTER " PER PART." #define TR_SETMIDPOINT "CENTRA STICKS/SLIDERS" #define TR_MOVESTICKSPOTS "MUOVI STICKS/POTS" #else @@ -584,7 +585,7 @@ #define TR_US "us" #define TR_TMIXMAXMS "Tmix max" #define TR_FREE_STACK "Free stack" -#define TR_MENUTORESET TR_ENTER" x Azzerare" +#define TR_MENUTORESET TR_ENTER" per azzerare" #define TR_PPM_TRAINER "TR" #define TR_CH "CH" #define TR_MODEL "MODELLO" @@ -593,7 +594,7 @@ #define TR_EEPROMLOWMEM "EEPROM quasi piena!" #define TR_ALERT "\016ALERT" #define TR_PRESSANYKEYTOSKIP "\010Premi un tasto" -#define TR_THROTTLENOTIDLE TR("Motore non in posiz.","Motore non in posizione") +#define TR_THROTTLENOTIDLE TR(INDENT"Motore non in posiz.", INDENT"Motore non in posizione") #define TR_ALARMSDISABLED "Avvisi Disattivati!" #define TR_PRESSANYKEY "\010Premi un tasto" #define TR_BADEEPROMDATA "Dati corrotti!" @@ -601,8 +602,8 @@ #define TR_EEPROMFORMATTING "Formatto EEPROM..." #define TR_STORAGE_FORMAT "Preparazione storage" #define TR_EEPROMOVERFLOW "EEPROM Piena" -#define TR_MENURADIOSETUP "CONFIGURATX" -#define TR_MENUDATEANDTIME "DATA E ORA" +#define TR_MENURADIOSETUP "CONFIGURA TX" +#define TR_MENUDATEANDTIME "DATA ED ORA" #define TR_MENUTRAINER "MAESTRO/ALLIEVO" #define TR_MENUSPECIALFUNCS "FUNZIONI GLOBALI" #define TR_MENUVERSION "VERSIONE" @@ -612,10 +613,10 @@ #if defined(COLORLCD) #define TR_TRIMS2OFFSETS "Trims => Subtrims" #else - #define TR_TRIMS2OFFSETS "\006Trim => Offset " + #define TR_TRIMS2OFFSETS "\006Trims => Offset " #endif -#define TR_CHANNELS2FAILSAFE "Canali=>Failsafe" -#define TR_CHANNEL2FAILSAFE "Canale=>Failsafe" +#define TR_CHANNELS2FAILSAFE "Canali => Failsafe" +#define TR_CHANNEL2FAILSAFE "Canale => Failsafe" #define TR_MENUMODELSEL "MODELLI" #define TR_MENUSETUP "CONFIGURA" #define TR_MENUFLIGHTMODE "FASE DI VOLO" @@ -628,8 +629,8 @@ #define TR_MENUCURVES "CURVE" #define TR_MENUCURVE "CURVA" #define TR_MENULOGICALSWITCH "INTER. PERSON." -#define TR_MENULOGICALSWITCHES TR("INTER. LOGICI","INTERRUTTORI LOGICI") -#define TR_MENUCUSTOMFUNC TR("FUNZ. SPECIALI","FUNZIONI SPECIALI") +#define TR_MENULOGICALSWITCHES TR(INDENT"INTER. LOGICI", INDENT"INTERRUTTORI LOGICI") +#define TR_MENUCUSTOMFUNC TR(INDENT"FUNZ. SPECIALI", INDENT"FUNZIONI SPECIALI") #define TR_MENUCUSTOMSCRIPTS "SCRIPTS UTENTE" #define TR_MENUTELEMETRY "TELEMETRIA" #define TR_MENUTEMPLATES "ESEMPI GUIDA" @@ -642,23 +643,23 @@ #define TR_MONITOR_CHANNELS4 "MONITOR CANALI 25/32" #define TR_MONITOR_OUTPUT_DESC "Uscite" #define TR_MONITOR_MIXER_DESC "Mixers" -#define TR_RECEIVER_NUM TR("RxNum", "Ricevente No.") +#define TR_RECEIVER_NUM TR(INDENT"RxNum", INDENT"Ricevente N.") #define TR_RECEIVER "Ricevente" -#define TR_MULTI_RFTUNE TR("Tune RF", "Tune fine Freq. RF") +#define TR_MULTI_RFTUNE TR(INDENT"Tune RF", INDENT"Tune fine Freq. RF") #define TR_MULTI_TELEMETRY "Telemetria" -#define TR_MULTI_VIDFREQ TR("Freq. video", "Frequenza video") +#define TR_MULTI_VIDFREQ TR(INDENT"Freq. video", INDENT"Frequenza video") #define TR_RFPOWER "Potenza RF" -#define TR_MULTI_FIXEDID TR("FixedID", "Fixed ID") -#define TR_MULTI_OPTION TR("Opzione", "Opzione valore") -#define TR_MULTI_AUTOBIND TR(INDENT "Autoassocia",INDENT "Associa al canale") -#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Trova autom.", INDENT "Autorileva il formato") -#define TR_MULTI_LOWPOWER TR(INDENT "Bassa pot.", INDENT "Modalità bassa potenza") +#define TR_MULTI_FIXEDID TR(INDENT"FixedID", INDENT"Fixed ID") +#define TR_MULTI_OPTION TR(INDENT"Opzione", INDENT"Opzione valore") +#define TR_MULTI_AUTOBIND TR(INDENT "Autoassoc.",INDENT "Associa automat.") +#define TR_MULTI_DSM_AUTODTECT TR(INDENT "Trova autom.", INDENT "Autoril. il formato") +#define TR_MULTI_LOWPOWER TR(INDENT "Bassa pot.", INDENT "Modo bassa potenza") #define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "Link S.Port") -#define TR_MODULE_TELEM_ON TR("ON", "Abilitato") -#define TR_DISABLE_INTERNAL TR("Disatt. RF int.", "Disattiva RF interna") -#define TR_MODULE_NO_SERIAL_MODE TR("!modo seriale", "Non in modo seriale") -#define TR_MODULE_NO_INPUT TR("Nessun input", "Nessun input seriale") -#define TR_MODULE_NO_TELEMETRY TR3( "No telemetria", "MULTI_TELEMETRY disattivato", "Nessuna telemetria (abilita MULTI_TELEMETRY)") +#define TR_MODULE_TELEM_ON TR(INDENT"ON", INDENT"Abilitato") +#define TR_DISABLE_INTERNAL TR(INDENT"Disatt. RF int.", INDENT"Disattiva RF interna") +#define TR_MODULE_NO_SERIAL_MODE TR(INDENT"!modo seriale", INDENT"Non in modo seriale") +#define TR_MODULE_NO_INPUT TR(INDENT"Nessun input", INDENT"Nessun input seriale") +#define TR_MODULE_NO_TELEMETRY TR3("No telemetria", "MULTI_TELEMETRY disattivato", "Nessuna telem. (abilita MULTI_TELEMETRY)") #define TR_MODULE_WAITFORBIND "Associa per caricare il protocollo" #define TR_MODULE_BINDING "Associa" #define TR_REBIND "Richiede associazione" @@ -668,17 +669,17 @@ #define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF" #define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON" #define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem OFF" -#define TR_PROTOCOL_INVALID TR("Prot. invalido", "Protocollo invalido") +#define TR_PROTOCOL_INVALID TR(INDENT"Prot. invalido", INDENT"Protocollo invalido") #define TR_MODULE_STATUS TR(INDENT "Stato", INDENT "Stato del modulo") #define TR_MODULE_SYNC TR(INDENT "Sinc.", INDENT "Sinc. del modulo") -#define TR_MULTI_SERVOFREQ TR("Servo rate", "Aggiorna servo rate") +#define TR_MULTI_SERVOFREQ TR(INDENT"Servo rate", INDENT"Aggiorna servo rate") #define TR_SYNCMENU "[Sync]" #define TR_LIMIT INDENT "Limiti" -#define TR_MINRSSI "Min. Rssi" +#define TR_MINRSSI "Min. RSSI" #define TR_LATITUDE "Latitud." #define TR_LONGITUDE "Longitud." -#define TR_GPSCOORD TR("GPS Coords", INDENT "Formato Coordinate") -#define TR_VARIO TR("Vario", "Variometro") +#define TR_GPSCOORD TR(INDENT"GPS Coords", INDENT "Formato Coordinate") +#define TR_VARIO TR(INDENT"Vario", INDENT"Variometro") #define TR_PITCH_AT_ZERO INDENT "Tono a Zero" #define TR_PITCH_AT_MAX INDENT "Tono al Max" #define TR_REPEAT_AT_ZERO INDENT "Ripeti a Zero" @@ -697,8 +698,8 @@ #define TR_COPY_MODEL "Copia Modello" #define TR_MOVE_MODEL "Sposta Modello" #define TR_BACKUP_MODEL "Salva Modello" -#define TR_DELETE_MODEL TR("Elim. Modello","Elimina Modello") // TODO merged into DELETEMODEL? -#define TR_RESTORE_MODEL TR("Ripr. Modello","Ripristina Modello") +#define TR_DELETE_MODEL TR(INDENT"Elim. Modello",INDENT"Elimina Modello") // TODO merged into DELETEMODEL? +#define TR_RESTORE_MODEL TR(INDENT"Ripr. Modello",INDENT"Ripristina Modello") #define TR_DELETE_ERROR "Errore cancell." #define TR_CAT_NOT_EMPTY "Categoria non vuota" #define TR_SDCARD_ERROR "Errore SD" @@ -712,9 +713,9 @@ #define TR_CONNECTED "Connesso" #define TR_FLEX_915 "Flex 915MHz" #define TR_FLEX_868 "Flex 868MHz" -#define TR_16CH_WITHOUT_TELEMETRY TR("16CH senza telem.", "16CH senza telemetria") -#define TR_16CH_WITH_TELEMETRY TR("16CH con telem.", "16CH con telemetria") -#define TR_8CH_WITH_TELEMETRY TR("8CH con telem.", "8CH con telemetria") +#define TR_16CH_WITHOUT_TELEMETRY TR(INDENT"16CH senza telem.", INDENT"16CH senza telemetria") +#define TR_16CH_WITH_TELEMETRY TR(INDENT"16CH con telem.", INDENT"16CH con telemetria") +#define TR_8CH_WITH_TELEMETRY TR(INDENT"8CH con telem.", INDENT"8CH con telemetria") #define TR_EXT_ANTENNA "Antenna Ext." #define TR_PIN "Pin" #define TR_UPDATE_RX_OPTIONS "Agg. opzioni RX?" @@ -730,11 +731,11 @@ #define TR_POWER "Potenza" #define TR_NO_TX_OPTIONS "No Opzioni TX" #define TR_RTC_BATT "RTC Batt" -#define TR_POWER_METER_EXT "Power Meter (EXT)" +#define TR_POWER_METER_EXT "Power Meter (EST)" #define TR_POWER_METER_INT "Power Meter (INT)" -#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EXT)" +#define TR_SPECTRUM_ANALYSER_EXT "Spectrum (EST)" #define TR_SPECTRUM_ANALYSER_INT "Spectrum (INT)" -#define TR_SDCARD_FULL "SD Card Piena" +#define TR_SDCARD_FULL "SDCard Piena" #define TR_NEEDS_FILE "RICHIEDE FILE" #define TR_EXT_MULTI_SPEC "opentx-inv" #define TR_INT_MULTI_SPEC "stm-opentx-noinv" @@ -747,9 +748,9 @@ #define TR_ALARMSWARN "ALLARMI" #define TR_SWITCHWARN "CONTROLLI" #define TR_FAILSAFEWARN "FAILSAFE" -#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD") +#define TR_NIGHTLY_WARNING TR(INDENT"NIGHTLY", INDENT"NIGHTLY BUILD") #define TR_NIGHTLY_NOTSAFE "Versione non sicura per volare" -#define TR_WRONG_SDCARDVERSION TR("Richiede ver: ","Richiede versione: ") +#define TR_WRONG_SDCARDVERSION TR(INDENT"Richiede ver: ", INDENT"Richiede versione: ") #define TR_WARN_RTC_BATTERY_LOW "Batteria RTC scarica" #define TR_WARN_MULTI_LOWPOWER "Modalità bassa pot." #define TR_BATTERY "BATTERIA" @@ -799,20 +800,20 @@ #define TR_FORMATTING "Formattazione." #define TR_TEMP_CALIB "Temp. Calib" #define TR_TIME "Ora" -#define TR_MAXBAUDRATE "Max bauds" +#define TR_MAXBAUDRATE "Bauds Max" #define TR_BLUETOOTH "Bluetooth" -#define TR_BLUETOOTH_DISC "Discover" -#define TR_BLUETOOTH_INIT "Init" -#define TR_BLUETOOTH_DIST_ADDR "Dist addr" -#define TR_BLUETOOTH_LOCAL_ADDR "Local addr" -#define TR_BLUETOOTH_PIN_CODE "PIN code" +#define TR_BLUETOOTH_DISC "Cerca" +#define TR_BLUETOOTH_INIT "Iniz." +#define TR_BLUETOOTH_DIST_ADDR "Ind. Dist." +#define TR_BLUETOOTH_LOCAL_ADDR "Ind. Loc." +#define TR_BLUETOOTH_PIN_CODE "Codice PIN" #define TR_BAUDRATE "BT Baudrate" #define LEN_BLUETOOTH_MODES "\011" #if defined(PCBX9E) #define TR_BLUETOOTH_MODES "---\0 ""Attivo\0 " #else -#define TR_BLUETOOTH_MODES "---\0 ""Telemetria""Trainer\0" +#define TR_BLUETOOTH_MODES "---\0 ""Telemetr.""Trainer\0" #endif #define TR_SD_INFO_TITLE "INFO SD" #define TR_SD_TYPE "Tipo:" @@ -835,27 +836,27 @@ #define TR_FLASH_BOOTLOADER "Prog. bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Progr. dispositivo Esterno" #define TR_FLASH_RECEIVER_OTA "Prog. ricevente OTA" -#define TR_FLASH_BLUETOOTH_MODULE TR("Prog modulo BT", "Prog. modulo Bluetooth") +#define TR_FLASH_BLUETOOTH_MODULE TR(INDENT"Prog modulo BT", INDENT"Prog. modulo Bluetooth") #define TR_FLASH_POWER_MANAGEMENT_UNIT "Programmazione PMU" -#define TR_CURRENT_VERSION TR("Vers. currente ", "Versione corrente: ") +#define TR_CURRENT_VERSION TR(INDENT"Vers. currente ", INDENT"Versione corrente: ") #define TR_FLASH_INTERNAL_MODULE "Progr. Modulo Interno" -#define TR_FLASH_INTERNAL_MULTI TR("Prog. Multi int.", "Prog. Multi interno") +#define TR_FLASH_INTERNAL_MULTI TR(INDENT"Prog. Multi int.", INDENT"Prog. Multi interno") #define TR_FLASH_EXTERNAL_MODULE "Prog. modulo esterno" -#define TR_FLASH_EXTERNAL_MULTI TR("Prog. Multi est.", "Prog. Multi esterno") -#define TR_FIRMWARE_UPDATE_ERROR TR("Errore agg. FW","Errore aggiornamento firmware") +#define TR_FLASH_EXTERNAL_MULTI TR(INDENT"Prog. Multi est.", INDENT"Prog. Multi esterno") +#define TR_FIRMWARE_UPDATE_ERROR TR(INDENT"Errore agg. FW",INDENT"Errore aggiornamento firmware") #define TR_FIRMWARE_UPDATE_SUCCESS "Agg. riuscito" #define TR_WRITING "\032Scrivendo..." #define TR_CONFIRM_FORMAT "Confermi Formattazione?" #define TR_INTERNALRF "Modulo Interno" -#define TR_INTERNAL_MODULE TR("Modulo int.","Modulo interno") -#define TR_EXTERNAL_MODULE TR("Modulo est.","Modulo esterno") +#define TR_INTERNAL_MODULE TR(INDENT"Modulo int.",INDENT"Modulo interno") +#define TR_EXTERNAL_MODULE TR(INDENT"Modulo est.", INDENT"Modulo esterno") #define TR_OPENTX_UPGRADE_REQUIRED "OpenTX richiede aggiornamento" #define TR_TELEMETRY_DISABLED "Telem. disabilitata" #define TR_MORE_OPTIONS_AVAILABLE "Altre opzioni assenti" #define TR_NO_MODULE_INFORMATION "Nessuna info del modulo" #define TR_EXTERNALRF "Modulo esterno" #define TR_FAILSAFE "Modo failsafe" -#define TR_FAILSAFESET TR("FAILSAFE","IMPOSTAZIONI FAILSAFE") +#define TR_FAILSAFESET TR(INDENT"FAILSAFE", INDENT"IMPOSTAZIONI FAILSAFE") #define TR_REG_ID "Reg. ID" #define TR_OWNER_ID "Owner ID" #define TR_PINMAPSET "PINMAP" @@ -865,16 +866,16 @@ #define TR_NONE_UPPERCASE "NONE" #define TR_MENUSENSOR "SENSOR" #define TR_POWERMETER_PEAK "Peak" -#define TR_POWERMETER_POWER "Power" -#define TR_POWERMETER_ATTN "Attn" +#define TR_POWERMETER_POWER "Potenza" +#define TR_POWERMETER_ATTN "Att." #define TR_POWERMETER_FREQ "Freq." #define TR_MENUTOOLS "TOOLS" -#define TR_TURN_OFF_RECEIVER "Spegni la rx" +#define TR_TURN_OFF_RECEIVER "Spegni la RX" #define TR_STOPPING "Fermando..." -#define TR_MENU_SPECTRUM_ANALYSER "SPECTRUM ANALYSER" -#define TR_MENU_POWER_METER "POWER METER" +#define TR_MENU_SPECTRUM_ANALYSER "ANALIZZATORE SPETTRO" +#define TR_MENU_POWER_METER "MISURATORE POTENZA" #define TR_SENSOR "SENSORE" -#define TR_COUNTRYCODE TR("Codice Paese","Standard 2.4Ghz") +#define TR_COUNTRYCODE TR(INDENT"Cod. Paese", INDENT"Codice del Paese") #define TR_USBMODE "Modo USB" #define TR_JACKMODE "Modo JACK" #define TR_VOICELANG "Lingua Voce" @@ -909,27 +910,27 @@ #define TR_POWERMETER_ATTN_NEEDED "Attenuatore necessario" #define TR_PXX2_SELECT_RX "Seleziona RX..." #define TR_PXX2_DEFAULT "" -#define TR_BT_SELECT_DEVICE "Seleziona device..." -#define TR_DISCOVER "Discover" +#define TR_BT_SELECT_DEVICE "Seleziona dispositivo" +#define TR_DISCOVER "Cerca" #define TR_BUTTON_INIT BUTTON("Init") #define TR_WAITING "In attesa..." #define TR_RECEIVER_DELETE "Cancello RX?" #define TR_RECEIVER_RESET "Resetto RX?" #define TR_SHARE "Condividere" #define TR_BIND "Bind" -#define TR_REGISTER TR("Reg", "Registrare") +#define TR_REGISTER TR(INDENT"Reg", INDENT"Registrare") #define TR_MODULE_RANGE "[Range]" -#define TR_RECEIVER_OPTIONS TR("OPZIONI RX", "OPZIONI RICEVENTE") +#define TR_RECEIVER_OPTIONS TR(INDENT"OPZIONI RX", INDENT"OPZIONI RICEVENTE") #define TR_DEL_BUTTON BUTTON(TR("Canc.", "Cancella")) #define TR_RESET_BTN "[Reset]" #define TR_DEBUG "Debug" #define TR_KEYS_BTN BUTTON(TR("SW","Interruttori")) #define TR_ANALOGS_BTN BUTTON(TR("Analogico","Analogici")) -#define TR_CALIBRATION "Calibrazione" +#define TR_CALIBRATION TR(INDENT "Calibraz.", INDENT "Calibrazione") #define TR_SET "[Set]" -#define TR_TRAINER TR("Trainer","Maestro/Allievo") +#define TR_TRAINER TR(INDENT"Trainer", INDENT"Maestro/Allievo") #define TR_ANTENNAPROBLEM CENTER "Problemi antenna TX!" -#define TR_MODELIDUSED TR("ID già usato","ID Modello già usato") +#define TR_MODELIDUSED TR(INDENT"ID già usato", INDENT"ID Modello già usato") #define TR_MODULE "Modulo" #define TR_RX_NAME "Nome RX" #define TR_TELEMETRY_TYPE "Tipo Telemetria" @@ -937,7 +938,7 @@ #define TR_VALUE "Valore" #define TR_TOPLCDTIMER "Timer LCD Sup." #define TR_UNIT "Unita" -#define TR_TELEMETRY_NEWSENSOR INDENT "Aggiungi nuovo sensore..." +#define TR_TELEMETRY_NEWSENSOR INDENT "Aggiungi nuovo sensore" #define TR_CHANNELRANGE INDENT "Numero Canali" #define TR_ANTENNACONFIRM1 "EXT. ANTENNA" #if defined(PCBX12S) @@ -947,18 +948,18 @@ #define LEN_ANTENNA_MODES "\011" #define TR_ANTENNA_MODES "Interna\0""Chiedi\0 ""Per modello""Esterna" #endif -#define TR_USE_INTERNAL_ANTENNA TR("Usa antenna int.", "Usa antenna interna") -#define TR_USE_EXTERNAL_ANTENNA TR("Usa antenna est.", "Usa antenna esterna") -#define TR_ANTENNACONFIRM2 TR("Controlla antenna", "Controlla se l'antenna è installata!") +#define TR_USE_INTERNAL_ANTENNA TR(INDENT "Usa ant. int.", INDENT "Usa antenna interna") +#define TR_USE_EXTERNAL_ANTENNA TR(INDENT "Usa ant. est.", INDENT "Usa antenna esterna") +#define TR_ANTENNACONFIRM2 TR(INDENT "Controlla antenna", INDENT "Controlla se l'antenna è installata!") #define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Non richiede" #define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Richiede FCC" #define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Richiede EU" #define TR_MODULE_PROTOCOL_WARN_LINE2 "firmware certificato" #define TR_LOWALARM INDENT "Allarme Basso" #define TR_CRITICALALARM INDENT "Allarme Critico" -#define TR_RSSIALARM_WARN TR("RSSI","TELEMETRY RSSI") -#define TR_NO_RSSIALARM TR(INDENT "Allarmi disabilitati", INDENT "Allarmi telemetrici disabilitati") -#define TR_DISABLE_ALARM TR(INDENT "Allarmi disabilitati", INDENT "Allarmi telemetrici disabilitati") +#define TR_RSSIALARM_WARN TR("Tel. RSSI","TELEMETRY RSSI") +#define TR_NO_RSSIALARM TR(INDENT "Allarmi disab.", INDENT "Allarmi telemetrici disabilitati") +#define TR_DISABLE_ALARM TR(INDENT "Allarmi disab.", INDENT "Allarmi telemetrici disabilitati") #define TR_ENABLE_POPUP "Abilita Popup" #define TR_DISABLE_POPUP "Disabilita Popup" #define TR_POPUP "Popup" @@ -974,8 +975,8 @@ #define TR_PT "pt" #define TR_PTS "pti" #define TR_SMOOTH "Smussa" -#define TR_COPY_STICKS_TO_OFS TR("Cpy stick->subtrim", "Copia Stick su Offset") -#define TR_COPY_TRIMS_TO_OFS TR("Cpy trim->subtrim", "Copia Trim in Subtrim") +#define TR_COPY_STICKS_TO_OFS TR(INDENT "Cp. stick->subtrim", INDENT "Copia Sticks su Subtrim") +#define TR_COPY_TRIMS_TO_OFS TR(INDENT "Cp. trim->subtrim", INDENT "Copia Trims su Subtrim") #define TR_INCDEC "Inc/Decrementa" #define TR_GLOBALVAR "Var Globale" #define TR_MIXSOURCE "Sorgente Mixer" @@ -988,7 +989,7 @@ #define TR_SCRIPT "Script" #define TR_INPUTS "Ingresso" #define TR_OUTPUTS "Uscita" -#define STR_EEBACKUP "Copiare la EEPROM" +#define STR_EEBACKUP "Copiare l'EEPROM" #define STR_FACTORYRESET "Inizializza dati" #define TR_CONFIRMRESET "Resettare TUTTI i dati?" #define TR_TOO_MANY_LUA_SCRIPTS "Troppi Scripts Lua!" @@ -998,12 +999,12 @@ #define TR_PHASES_HEADERS_NAME "Nome" #define TR_PHASES_HEADERS_SW "Inter" #define TR_PHASES_HEADERS_RUD_TRIM "Trim Deriva" -#define TR_PHASES_HEADERS_ELE_TRIM "Trim Elevator" +#define TR_PHASES_HEADERS_ELE_TRIM "Trim Elevatore" #define TR_PHASES_HEADERS_THT_TRIM "Trim Motore" #define TR_PHASES_HEADERS_AIL_TRIM "Trim Alettoni" #define TR_PHASES_HEADERS_CH5_TRIM "Trim 5" #define TR_PHASES_HEADERS_CH6_TRIM "Trim 6" -#define TR_PHASES_HEADERS_FAD_IN "Disolv. In" +#define TR_PHASES_HEADERS_FAD_IN "Dissolv. In" #define TR_PHASES_HEADERS_FAD_OUT "Dissolv. Out" #define TR_LIMITS_HEADERS_NAME "Nome" @@ -1022,16 +1023,16 @@ #define TR_LSW_HEADERS_DURATION "Durata" #define TR_LSW_HEADERS_DELAY "Ritardo" -#define TR_GVAR_HEADERS_NAME "Name" -#define TR_GVAR_HEADERS_FM0 "Value on FM0" -#define TR_GVAR_HEADERS_FM1 "Value on FM1" -#define TR_GVAR_HEADERS_FM2 "Value on FM2" -#define TR_GVAR_HEADERS_FM3 "Value on FM3" -#define TR_GVAR_HEADERS_FM4 "Value on FM4" -#define TR_GVAR_HEADERS_FM5 "Value on FM5" -#define TR_GVAR_HEADERS_FM6 "Value on FM6" -#define TR_GVAR_HEADERS_FM7 "Value on FM7" -#define TR_GVAR_HEADERS_FM8 "Value on FM8" +#define TR_GVAR_HEADERS_NAME "Nome" +#define TR_GVAR_HEADERS_FM0 "Valore su FM0" +#define TR_GVAR_HEADERS_FM1 "Valore su FM1" +#define TR_GVAR_HEADERS_FM2 "Valore su FM2" +#define TR_GVAR_HEADERS_FM3 "Valore su FM3" +#define TR_GVAR_HEADERS_FM4 "Valore su FM4" +#define TR_GVAR_HEADERS_FM5 "Valore su FM5" +#define TR_GVAR_HEADERS_FM6 "Valore su FM6" +#define TR_GVAR_HEADERS_FM7 "Valore su FM7" +#define TR_GVAR_HEADERS_FM8 "Valore su FM8" // Horus footer descriptions #define TR_LSW_DESCRIPTIONS { "Tipo o funzione di confronto", "Prima variabile", "Seconda variabile o costante", "Seconda variabile o costante", "Condizione aggiuntiva da abilitare linea", "Durata minima ON dell'interruttore logico", "Durata minima TRUE affinché l'interruttore si accenda" } @@ -1111,7 +1112,7 @@ #define TR_SCALE "Scala" #define TR_VIEW_CHANNELS "Vedi Canali" #define TR_VIEW_NOTES "Vedi Note" -#define TR_MODEL_SELECT "Model Select" +#define TR_MODEL_SELECT "Seleziona Modello" #define TR_MODS_FORBIDDEN "Modifica proibita!" #define TR_UNLOCKED "Sbloccato" #define TR_ID "ID" @@ -1127,19 +1128,19 @@ #define TR_CELLSENSOR "Sensore Cell" #define TR_GPSSENSOR "Sensore GPS" #define TR_CURRENTSENSOR "Sensore" -#define TR_AUTOOFFSET "Auto Offset" +#define TR_AUTOOFFSET "Offset Auto" #define TR_ONLYPOSITIVE "Positivo" #define TR_FILTER "Filtro" #define TR_TELEMETRYFULL "Tutti gli slot sono pieni!" -#define TR_SERVOS_OK "Servos OK" -#define TR_SERVOS_KO "Servos KO" +#define TR_SERVOS_OK "Servi OK" +#define TR_SERVOS_KO "Servi KO" //TODO: translation -#define TR_INVERTED_SERIAL INDENT "Invert" -#define TR_IGNORE_INSTANCE TR(INDENT "No inst.","Ignora instanza") +#define TR_INVERTED_SERIAL INDENT "Invert." +#define TR_IGNORE_INSTANCE TR(INDENT "No inst.", INDENT "Ignora instanza") #define TR_DISCOVER_SENSORS "Cerca nuovi sensori" -#define TR_STOP_DISCOVER_SENSORS "Ferma ricerca.." +#define TR_STOP_DISCOVER_SENSORS "Ferma ricerca" #define TR_DELETE_ALL_SENSORS "Elimina tutti i sensori" -#define TR_CONFIRMDELETE "Confermi " LCDW_128_480_LINEBREAK "eliminazione ?" +#define TR_CONFIRMDELETE "Confermi " LCDW_128_480_LINEBREAK "eliminazione?" #define TR_SELECT_WIDGET "Seleziona widget" #define TR_REMOVE_WIDGET "Rimuovi widget" #define TR_WIDGET_SETTINGS "Settaggio widget" @@ -1172,7 +1173,7 @@ #define TR_MENU_OTHER "Altro" #define TR_MENU_INVERT "Inverti" #define TR_JITTER_FILTER "Filtro ADC" -#define TR_RTC_CHECK TR("Controllo RTC", "Controllo voltaggio RTC") +#define TR_RTC_CHECK TR(INDENT"Controllo RTC", INDENT"Controllo voltaggio RTC") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/util/tts_it.py b/radio/util/tts_it.py index 8ba62493f..52ba120a8 100755 --- a/radio/util/tts_it.py +++ b/radio/util/tts_it.py @@ -37,7 +37,7 @@ for i, (s, f) in enumerate([("volt", "volt0"), ("radiante", "rad0"), ("radianti", "rad1"), ("millilitro", "m10"), ("millilitri", "m11"), ("oncia fluida", "founce0"), ("once fluide", "founce1"), - ("milliliter per minute", "mlpm0"), ("milliliters per minute", "mlpm1"), + ("millilitro per minuto", "mlpm0"), ("millilitri per minuto", "mlpm1"), ("ora", "hour0"), ("ore", "hour1"), ("minuto", "minute0"), ("minuti", "minute1"), ("secondo", "second0"), ("secondi", "second1"), From 9831a796b7433dab7b0f82faa0b9d2da29c57e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Charpentier?= Date: Thu, 24 Oct 2019 09:02:25 +0200 Subject: [PATCH 220/257] French translation update (#6976) Updated French Translation. --- companion/src/translations/companion_fr.ts | 177 +++++++++++---------- 1 file changed, 91 insertions(+), 86 deletions(-) diff --git a/companion/src/translations/companion_fr.ts b/companion/src/translations/companion_fr.ts index c949823d1..355c77914 100644 --- a/companion/src/translations/companion_fr.ts +++ b/companion/src/translations/companion_fr.ts @@ -1058,37 +1058,37 @@ Manche Droit: Profondeur, Direction <p> Le type de radio sélectionnée dans le profil n'existe pas. Utilisez plutôt le type par défaut. </p> <p><b>Veuillez mettre à jour les paramètres de votre profil!</b></p> - + Select or create a file for exported Settings: Sélectionnez ou créez un fichier pour les paramètres exportés: - + Press the 'Retry' button to choose another file. Appuyez sur le bouton 'Réessayer' pour choisir un autre fichier. - + Simulator for this firmware is not yet available Le simulateur n'est pas encore disponible pour ce firmware - + Uknown error during Simulator startup. Erreur inconnue pendant le démarrage du simulateur. - + Simulator Error Erreur Simulateur - + Data Load Error Erreur de chargement des données - + Error occurred while starting simulator. Une erreur s'est produite lors du démarrage du simulateur. @@ -2833,19 +2833,19 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont - + Disable HELI menu and cyclic mix support Supprimer le menu HELICO et les mixages cycliques - + Disable Global variables Supprimer le support des variables globales - + Enable Lua custom scripts screen Activer l'écran des scripts Lua personnalisés @@ -2910,9 +2910,11 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont + + Support for auto update on boot Prise en charge de la mise à jour automatique au démarrage @@ -2943,47 +2945,42 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont - + Support for ACCESS internal module replacement Prise en charge du module de remplacement interne ACCESS - - FrSky Horus X10 Express - - - - + FrSky Horus X12S - + Use ONLY with first DEV pcb version Exclusivement pour les Horus DEV - + Jumper T12 - + Enable non certified R9M firmwares Activer les firmwares R9M non certifiés - + Jumper T16 / T16+ - + Support for MULTI internal module Prise en charge du module MULTI interne - + Turnigy 9XR-PRO @@ -3028,17 +3025,22 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Ne pas mettre les lignes actives en gras - - Turnigy 9XR with m128 chip - Turnigy 9XR avec une puce m128 - - - - Turnigy 9XR + + FrSky Horus X10 / X10S Express + Turnigy 9XR with m128 chip + Turnigy 9XR avec une puce m128 + + + + Turnigy 9XR + + + + 9X with stock board 9X avec carte mère d'origine @@ -3048,27 +3050,27 @@ Blanc signifie "inclure tous".Les métacaractères ?, * et [...] sont Permet la remise à zéro des valeurs en pressant haut-bas en même temps, valeur min avec gauche/bas, valeur max avec haut/droite, inversion avec gauche/droite - + 9X with stock board and m128 chip Carte 9x avec un chip m128 - + 9X with AR9X board 9X avec carte AR9X - + 9X with Sky9x board 9X avec carte Sky9x - + 9X with Gruvin9x board 9X avec carte Gruvin9x - + DIY MEGA2560 radio Radio DIY à base de MEGA2560 @@ -6990,7 +6992,7 @@ Do you wish to continue? MdiChild - + Unable to find file %1! Fichier %1 introuvable ! @@ -7255,47 +7257,37 @@ Do you wish to continue? Impossible de dupliquer le modèle, aucun emplacement libre n’est disponible. - - WARNING - ATTENTION - - - - <p>Due to the way Jumper have handled their JumperTX fork and firmware releases data integrity for settings from JumperTX cannot be trusted when migrating to OpenTX.</p> <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>En raison de la manière dont Jumper a traité ses versions de firmwares, l'intégrité des données pour les paramètres des radios Jumper n'est pas fiable lors de la migration vers OpenTX.</p> <p>L'importation des données des radios Jumper dans OpenTX 2.3 <b>n'est pas prise en charge et constitue un danger.</b></p> <p>Il ne nous est malheureusement pas possible de différencier les données des radios Jumper par rapport aux données légitimes des radios FrSky X10, mais <b> Vous ne devez continuer ici que si le fichier que vous avez ouvert provient d'une véritable radio FrSky X10.</b></p> <p>Voulez-vous vraiment continuer?</p> - - - + Do you wish to continue with the conversion? Souhaitez-vous vraiment lancer la conversion ? - + Choose <i>Apply</i> to convert the file, or <i>Close</i> to close it without conversion. Choisissez <i>Appliquer</i> pour convertir le fichier ou <i>Annuler</i> pour le fermer sans conversion. - + <b>The conversion generated some important messages, please review them below.</b> <b>La conversion a généré des messages importants, veuillez les consulter ci-dessous.</b> - + Companion :: Conversion Result for %1 Companion :: Résultat de conversion de %1 - + Unable to find Horus radio SD card! Impossible de trouver la carte SD de la Horus ! - + Models and Settings written Modèle et paramètres écrit - + Cannot write temporary file! Ecriture de fichier temporaire impossible ! @@ -7305,14 +7297,14 @@ Do you wish to continue? Édition du modèle %1 : - + Error reading file %1: %2. Fichier %1 corrompu: %2. - + Error opening file %1: %2. Erreur à l'ouverture du fichier %1: @@ -7351,17 +7343,17 @@ Do you wish to continue? Nlle categorie - + <p><b>Currently selected radio type (%1) is not compatible with file %3 (from %2), models and settings need to be converted.</b></p> <p><b>Le type de radio actuellement sélectionné (%1) n'est pas compatible avec le fichier %3 (à partir de %2), les modèles et les paramètres doivent être convertis.</b></p> - + Open backup Models and Settings file Ouvrir la sauvegarde de paramètres et modèles - + Invalid binary backup File %1 Fichier de sauvegarde %1 invalide @@ -8897,85 +8889,85 @@ Mixage actif par défaut si non-renseigné. ModuleData - + Positive - + Negative 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) @@ -8998,22 +8990,22 @@ Mixage actif par défaut si non-renseigné. Pas d'impulsion - + Ask Demander - + Internal Interne - + Internal + External Interne + Externe - + External Externe @@ -9693,6 +9685,19 @@ Mixage actif par défaut si non-renseigné. Voir les détails + + QObject + + + WARNING + ATTENTION + + + + <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>L'importation de données JumperTX dans OpenTX 2.3 est <b> non prise en charge et dangereuse.</b></p> <p>Il n'est malheureusement pas possible pour nous de différencier les données JumperTX des données légitimes FrSky X10, donc <b>Vous devez continuer uniquement si le fichier que vous avez ouvert provient d’une véritable radio FrSky X10.</b></p> <p>Voulez-vous vraiment continuer?</p> + + RadioData @@ -10550,7 +10555,7 @@ E Act - + @@ -10938,22 +10943,22 @@ Si cette option est cochée, la voie des gaz est inversée: le ralenti est &apo SetupPanel - + Timer %1 Chrono %1 - + THR GAZ - + Profile Settings Paramètres du profil - + SD structure path not specified or invalid Chemin de la structure SD non spécifié ou invalide From 1b35f2bd35062a97264645c565982934d8abf445 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 24 Oct 2019 12:03:19 +0200 Subject: [PATCH 221/257] Trainer function can now replace the channels values instead of to the sticks positions (#6561) --- radio/src/functions.cpp | 12 ++++--- .../gui/128x64/model_special_functions.cpp | 8 +++-- .../gui/212x64/model_special_functions.cpp | 8 +++-- .../gui/480x272/model_special_functions.cpp | 8 +++-- radio/src/mixer.cpp | 32 +++++++++++-------- radio/src/opentx.h | 5 +-- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp index bd840fc4a..0f93ca786 100644 --- a/radio/src/functions.cpp +++ b/radio/src/functions.cpp @@ -165,11 +165,13 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext case FUNC_TRAINER: { - uint8_t mask = 0x0f; - if (CFN_CH_INDEX(cfn) > 0) { - mask = (1<<(CFN_CH_INDEX(cfn)-1)); - } - newActiveFunctions |= mask; + uint8_t param = CFN_CH_INDEX(cfn); + if (param == 0) + newActiveFunctions |= 0x0F; + else if (param <= NUM_STICKS) + newActiveFunctions |= (1 << (param-1)); + else if (param == NUM_STICKS + 1) + newActiveFunctions |= (1 << FUNCTION_TRAINER_CHANNELS); break; } diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp index b4f4646a3..a0472d681 100644 --- a/radio/src/gui/128x64/model_special_functions.cpp +++ b/radio/src/gui/128x64/model_special_functions.cpp @@ -222,8 +222,12 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF else #endif if (func == FUNC_TRAINER) { - maxParam = 4; - drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr); + maxParam = NUM_STICKS + 1; + uint8_t param = CFN_CH_INDEX(cfn); + if (param == NUM_STICKS + 1) + lcdDrawText(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, "Chans", attr); + else + drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, CFN_CH_INDEX(cfn) == 0 ? 0 : MIXSRC_Rud + CFN_CH_INDEX(cfn) - 1, attr); } #if defined(GVARS) else if (func == FUNC_ADJUST_GVAR) { diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp index 653e83783..eb1bcb58d 100644 --- a/radio/src/gui/212x64/model_special_functions.cpp +++ b/radio/src/gui/212x64/model_special_functions.cpp @@ -214,8 +214,12 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF else #endif if (func == FUNC_TRAINER) { - maxParam = NUM_STICKS; - drawSource(lcdNextPos, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr); + maxParam = NUM_STICKS + 1; + uint8_t param = CFN_CH_INDEX(cfn); + if (param == NUM_STICKS + 1) + lcdDrawText(lcdNextPos, y, "Chans", attr); + else + drawSource(lcdNextPos, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr); } #if defined(GVARS) else if (func == FUNC_ADJUST_GVAR) { diff --git a/radio/src/gui/480x272/model_special_functions.cpp b/radio/src/gui/480x272/model_special_functions.cpp index 6ae8c4d11..f646b027c 100644 --- a/radio/src/gui/480x272/model_special_functions.cpp +++ b/radio/src/gui/480x272/model_special_functions.cpp @@ -215,8 +215,12 @@ bool menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF else #endif if (func == FUNC_TRAINER) { - maxParam = 4; - drawSource(MODEL_SPECIAL_FUNC_2ND_COLUMN_EXT, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr); + maxParam = NUM_STICKS + 1; + uint8_t param = CFN_CH_INDEX(cfn); + if (param == NUM_STICKS + 1) + lcdDrawText(MODEL_SPECIAL_FUNC_2ND_COLUMN_EXT, y, "Chans", attr); + else + drawSource(MODEL_SPECIAL_FUNC_2ND_COLUMN_EXT, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr); } #if defined(GVARS) else if (func == FUNC_ADJUST_GVAR) { diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 655438d4c..6d9d543cf 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -224,6 +224,17 @@ void applyExpos(int16_t * anas, uint8_t mode, uint8_t ovwrIdx, int16_t ovwrValue // rescaled from -262144 to 262144 int16_t applyLimits(uint8_t channel, int32_t value) { +#if defined(OVERRIDE_CHANNEL_FUNCTION) + if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED) { + // safety channel available for channel check + return calc100toRESX(safetyCh[channel]); + } +#endif + + if (isFunctionActive(FUNCTION_TRAINER_CHANNELS) && IS_TRAINER_INPUT_VALID()) { + return ppmInput[channel]; + } + LimitData * lim = limitAddress(channel); if (lim->curve) { @@ -277,17 +288,12 @@ int16_t applyLimits(uint8_t channel, int32_t value) ofs += tmp; // ofs can to added directly because already recalculated, } - if (ofs > lim_p) ofs = lim_p; - if (ofs < lim_n) ofs = lim_n; - - if (lim->revert) ofs = -ofs; // finally do the reverse. - -#if defined(OVERRIDE_CHANNEL_FUNCTION) - if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED) { - // safety channel available for channel check - ofs = calc100toRESX(safetyCh[channel]); - } -#endif + if (ofs > lim_p) + ofs = lim_p; + if (ofs < lim_n) + ofs = lim_n; + if (lim->revert) + ofs = -ofs; // finally do the reverse. return ofs; } @@ -467,12 +473,12 @@ void evalInputs(uint8_t mode) v = 0; } - if (mode <= e_perout_mode_inactive_flight_mode && isFunctionActive(FUNCTION_TRAINER+ch) && IS_TRAINER_INPUT_VALID()) { + if (mode <= e_perout_mode_inactive_flight_mode && isFunctionActive(FUNCTION_TRAINER_STICK1+ch) && IS_TRAINER_INPUT_VALID()) { // trainer mode TrainerMix* td = &g_eeGeneral.trainer.mix[ch]; if (td->mode) { uint8_t chStud = td->srcChn; - int32_t vStud = (ppmInput[chStud]- g_eeGeneral.trainer.calib[chStud]); + int32_t vStud = (ppmInput[chStud] - g_eeGeneral.trainer.calib[chStud]); vStud *= td->studWeight; vStud /= 50; switch (td->mode) { diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 218a3b9fb..afb35eeb4 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -909,8 +909,9 @@ uint8_t lswFamily(uint8_t func); int16_t lswTimerValue(delayval_t val); enum FunctionsActive { - FUNCTION_TRAINER, - FUNCTION_INSTANT_TRIM = FUNCTION_TRAINER+4, + FUNCTION_TRAINER_STICK1, + FUNCTION_TRAINER_CHANNELS = FUNCTION_TRAINER_STICK1 + NUM_STICKS, + FUNCTION_INSTANT_TRIM, FUNCTION_VARIO, FUNCTION_BACKLIGHT, #if defined(SDCARD) From 2a79cb0a52ea045f467a8873f212a8c534eae960 Mon Sep 17 00:00:00 2001 From: Stefan Hezinger <47187139+SHezinger@users.noreply.github.com> Date: Fri, 25 Oct 2019 14:09:41 +0200 Subject: [PATCH 222/257] German translations (#6999) * Wizard pages reviewed and missing translations added * Changed to SI Units * telemetry.ui updated * customizesplashdialog updated * warnings.h updated * downloaddialog updated * expodialog.cpp updated * generalsetup.cpp updated * mainwindow.cpp updated * modeldata.cpp updated * radionotfound.ui updated * sdcard.cpp updated * helpers_html.cpp translated * Tried to distinguish between the physical "Trimmer" and the value "Trimmung" * Minor changes --- companion/src/translations/companion_de.ts | 322 +++++++++++---------- 1 file changed, 164 insertions(+), 158 deletions(-) diff --git a/companion/src/translations/companion_de.ts b/companion/src/translations/companion_de.ts index ebf605eff..855bfab42 100644 --- a/companion/src/translations/companion_de.ts +++ b/companion/src/translations/companion_de.ts @@ -11,22 +11,22 @@ Yes, controlled by a single channel - Ja, mit einem Kanal + Ja, über einen Kanal gesteuert Yes, controlled by two channels - Ja, mit 2 Kanälen + Ja, über zwei Kanäle gesteuert <br>First Aileron Channel: - <br> Erster, rechter Querruder Kanal: + <br> Erster Querruderkanal: Second Aileron Channel: - Zweiter, linker Querruder Kanal: + Zweiter Querruderkanal: @@ -39,22 +39,22 @@ Yes, controlled by a single channel - Ja, mit 1 Servo + Ja, über einen Kanal gesteuert Yes, controlled by two channels - Ja, mit 2 Servos + Ja, über zwei Kanäle gesteuert <br>First Airbrake Channel: - <br> Erster, rechter Airbrake Kanal: + <br> Erster Störklappenkanal: Second Airbrake Channel: - Zweiter, linker Airbrake Kanal: + Zweiter Störklappenkanal: @@ -86,7 +86,7 @@ Show this message again at next startup? - Diese Nachricht beim nächsten Starten wieder anzeigen? + Diese Nachricht beim nächsten Starten erneut anzeigen? @@ -1242,7 +1242,7 @@ If you have a settings backup file, you may import that instead. OK, I understand. - OK verstanden. + OK, verstanden. @@ -1742,7 +1742,7 @@ If you have a settings backup file, you may import that instead. Value - Wert + Wert @@ -1752,7 +1752,7 @@ If you have a settings backup file, you may import that instead. repeat(%1s) - + wiederholen(%1s) @@ -1876,19 +1876,19 @@ If you have a settings backup file, you may import that instead. Load FW - Lade FW + Bild aus Firmware-File Load Pict - Lade Bild + Bild direkt Load Profile - Lade Profil + Bild aus Profil @@ -1933,7 +1933,7 @@ If you have a settings backup file, you may import that instead. Can not load embedded image from firmware file %1. - + Die Bilddatei konnte nicht aus dem Firmware-File %1 geladen werden. @@ -1948,17 +1948,17 @@ If you have a settings backup file, you may import that instead. Cannot load the image file %1. - + Die Bilddatei %1 konnte nicht geladen werden. Cannot load profile image %1. - + Die Bilddatei %1 konnte nicht aus dem Profil geladen werden. Cannot load the library image %1. - + Die Bilddatei %1 konnte nicht aus der Bibliothek geladen werden. @@ -1968,27 +1968,27 @@ If you have a settings backup file, you may import that instead. The image was saved to the file %1 - + Das Bild wurde als %1 gespeichert Image Refresh Error - + Fehler beim Aktualisieren des Bildes Failed to refresh image from file %1 - + Das Aktualisieren des Bildes durch die Datei %1 ist fehlgeschlagen File Save Error - Datei speichern fehlerhaft + Fehler beim Speichern der Datei Failed to write image to %1 - + Das Speichern des Bildes in die Datei %1 ist fehlgeschlagen @@ -2171,17 +2171,17 @@ To <b>remove a remembered entry</b> from the filter list, first cho Downloading: - Herunterladen: + Herunterladen: Unable to save the file %1: %2. - Kann Datei %1:%2 nicht abspeichern. + Die Datei %1 konnte nicht abgespeichert werden:%2. Download failed: %1. - Herunterladen fehlgeschlagen: %1. + Herunterladen fehlgeschlagen: %1. @@ -2288,12 +2288,12 @@ To <b>remove a remembered entry</b> from the filter list, first cho <br>First Elevon Channel: - <br>Erster Rechter Höhenruder Kanal: + <br>Erster Elevon-Kanal: Second Elevon Channel: - Zweiter Linker Höhenruder Kanal: + Zweiter Elevon-Kanal: @@ -2371,7 +2371,7 @@ To <b>remove a remembered entry</b> from the filter list, first cho Include Trim - Trimmung einschliessen + Trimmung einschließen @@ -2427,7 +2427,7 @@ If blank then the input is considered to be "ON" all the time. Popup menu available - Menü verfügbar + Popup-Menü verfügbar @@ -3102,22 +3102,22 @@ Blank means include all. ?, *, and [...] wildcards accepted. Yes, controlled by a single channel - Ja mit einem Kanal + Ja, über einen Kanal gesteuert Yes, controlled by two channels - Ja, mit 2 Kanälen + Ja, über zwei Kanäle gesteuert <br>First Flap Channel: - <br> Erster, rechter Flap Kanal: + <br> Erster Wölbklappenkanal: Second Flap Channel: - Zweiter, linker Flap Kanal: + Zweiter Wölbklappenkanal: @@ -3562,32 +3562,32 @@ You are currently using: Popup enabled - Anzeige im Popupfenster freigeben + Anzeige im Popup-Fenster freigeben Popup menu available - Menü verfügbar + Popup-Menü verfügbar Trim disabled - Trim ausgeschaltet + Trimmung deaktivieren Own Trim - Eigene Trim + Eigene Trimmung Use Trim from Flight mode %1 - Trim von Flugphase %1 + Trimmung von Flugphase %1 Use Trim from Flight mode %1 + Own Trim as an offset - Trim von Flugphase %1 + Eigene Trim als Offset + Trimmung von Flugphase %1 + Eigenen Trimmung als Offset @@ -3647,12 +3647,12 @@ You are currently using: (%1) - (%1) + (%1) (default) - (normal) + (normal) @@ -3660,7 +3660,7 @@ You are currently using: Has Flybar - Has Flybar + Mit Flybar @@ -4821,7 +4821,7 @@ Warnung stummer Betrieb - Wird angezeigt, wenn der Piepser komplett ausgeschalte Keys + Sticks - Taste+Knüppel + Tasten+ Knüppel @@ -4876,12 +4876,12 @@ Warnung stummer Betrieb - Wird angezeigt, wenn der Piepser komplett ausgeschalte Portuguese - Portogiesisch + Portugiesisch Russian - + Russisch @@ -4906,7 +4906,7 @@ Warnung stummer Betrieb - Wird angezeigt, wenn der Piepser komplett ausgeschalte Rot Enc B - Drehgebeer B + Drehgeber B @@ -4928,8 +4928,8 @@ Warnung stummer Betrieb - Wird angezeigt, wenn der Piepser komplett ausgeschalte If you enable FAI, only RSSI and RxBt sensors will keep working. This function cannot be disabled by the radio. Are you sure ? - Wenn man FAI auswählt gibt es nur noch RSSI und RxBat als Sensorwerte -Diese Funktion kann dann im Sender nicht mehr abgewählt werden + Wenn Sie FAI auswählen, stehen nur noch RSSI und RxBat als Sensorwerte zur Verfügung. +Diese Funktion kann im Sender nicht mehr abgewählt werden. Sind Sie sicher? @@ -5372,22 +5372,22 @@ Sind Sie sicher? Throttle Channel: - Gas Kanal: + Gas-Kanal: Yaw Channel: - Yaw (Heck) Kanal: + Yaw-Kanal: Pitch Channel: - Pitch Kanal: + Pitch-Kanal: Roll Channel: - Roll Kanal: + Roll-Kanal: @@ -6066,12 +6066,12 @@ Die Spalten für Höhe "GAlt" und für Geschwindigkeit "GSpd" The OpenTX Companion project was originally forked from <a href='%1'>eePe</a> - + Das OpenTX Companion Project ist ein Fork von <a href='%1'>eePe</a> Copyright OpenTX Team - + Copyright OpenTX Team @@ -6111,7 +6111,7 @@ Die Spalten für Höhe "GAlt" und für Geschwindigkeit "GSpd" Diskimage (*.dmg) - + Diskimage (*.dmg) @@ -7315,7 +7315,7 @@ Sollen die Änderungen gespeichert werden? Include Trim - Trimmung einschliessen + Trimmung einschließen @@ -7406,7 +7406,9 @@ p, li { white-space: pre-wrap; } Mixer warning. Setting this value will cause a beep to be emmitted when this value is active. - + Ich bin mir nicht sicher ob der + Mixerwarnung. +Diese Einstellung sorgt dafür, dass ein Piepton abgespielt wird, sobald dieser Mixer aktiviert wird. @@ -7454,7 +7456,7 @@ If blank then the mix is considered to be "ON" all the time. Include DR/Expo - DR/Expo einschliessen + DR/Expo einschließen @@ -7464,7 +7466,8 @@ If blank then the mix is considered to be "ON" all the time. Slow - Langsam + Man könnte auch Hemmung sagen + Verlangsamung @@ -7662,12 +7665,12 @@ If blank then the mix is considered to be "ON" all the time. Model: - Model: + Modell: Throttle Source - GasTimer Quelle + Gas-Timer Quelle @@ -8122,7 +8125,7 @@ If blank then the mix is considered to be "ON" all the time. Trim idle only - Nur Leerlauftrimm + Nur Leerlauftrimmung @@ -8523,7 +8526,7 @@ If blank then the mix is considered to be "ON" all the time. Plane - Flugmodell + Flächenmodell @@ -8538,12 +8541,12 @@ If blank then the mix is considered to be "ON" all the time. Model Name: - Model Name: + Modellname: Model Type: - Model Typ: + Modelltyp: @@ -9411,22 +9414,22 @@ If blank then the mix is considered to be "ON" all the time. Throttle Channel: - Gas Kanal: + Gas-Kanal: Yaw Channel: - Yaw (Heck) Kanal: + Yaw-Kanal: Pitch Channel: - Pitch Kanal: + Pitch-Kanal: Roll Channel: - Roll Kanal: + Roll-Kanal: @@ -9439,7 +9442,7 @@ If blank then the mix is considered to be "ON" all the time. ... plus %1 errors - ...plus %1 Fehler + ... plus %1 Fehler @@ -9457,17 +9460,17 @@ If blank then the mix is considered to be "ON" all the time. Throttle Cut - Gas Freigabe Schalter + Gas-Freigabeschalter Throttle Timer - Gas Timer starten + Gas-Timer starten Flight Timer - Flug Timer starten + Flug-Timer starten @@ -9733,7 +9736,7 @@ If blank then the mix is considered to be "ON" all the time. <html><head/><body><p>No Radio was found!</p><p>Make sure that you hold the lower trim buttons towards the center while you turn it on.</p><p>Then connect the USB wire.</p><p><span style=" font-family:'arial,sans-serif'; font-size:13px; font-style:italic; color:#222222; background-color:#ffffff;">Note: if you have a Taranis that has not had the firmware upgraded to 2.0 then this version of Companion will not work.</span></p></body></html> - + <html><head/><body><p>Es wurde kein Sender gefunden!</p><p>Stellen Sie sicher, dass Sie während des Einschaltens, die unteren Trimmer zur Mitte hin gedrückt halten</p><p>Stecken Sie danach das USB-Kabel ein.</p><p><span style=" font-family:'arial,sans-serif'; font-size:13px; font-style:italic; color:#222222; background-color:#ffffff;">Hinweis: Sollten Sie eine Taranis besitzen, die noch nicht auf die Version 2.0 upgegraded wurde, wird sie mit dieser Version von Companion nicht funktionieren.</span></p></body></html> @@ -10307,102 +10310,102 @@ r ↑ - + ↑ ↓ - + ↓ - - + - ! - + ! RudTrim Left - SeiteTrim links + Seitenruder-Trimmer links RudTrim Right - SeiteTrim rechts + Seiteruder-Trimmer rechts EleTrim Down - HöheTrim ab + Höheruder-Trimmer runter EleTrim Up - HöheTrim auf + Höheruder-Trimmer hoch ThrTrim Down - GasTrim ab + Gas-Trimmer runter ThrTrim Up - GasTrim auf + Gas-Trimmer hoch AilTrim Left - QuerTrim links + Querruder-Trimmer links AilTrim Right - QuerTrim rechts + Querruder-Trimmer rechts Trim 5 Down - Trim5 ab + Trimmer 5 runter Trim 5 Up - Trim5 auf + Trimmer 5 hoch Trim 6 Down - Trim6 ab + Trimmer 6 runter Trim 6 Up - Trim6 auf + Trimmer 6 hoch TrmH Left - TrimH links + Trimmer H links TrmH Right - TrimH rechts + Trimmer H rechts TrmV Down - TrimV ab + Trimmer V runter TrmV Up - TrimV auf + Trimmer V hoch @@ -10517,7 +10520,7 @@ r <br>Rudder Channel: - <br> Seite Kanal: + <br> Seitenruderkanal: @@ -10533,7 +10536,8 @@ r Error opening file %1 in write mode: %2. - + Fehler beim Öffnen der Datei %1 im Schreibmodus: +%2. @@ -10695,7 +10699,8 @@ r Throttle Trim Idle Only - Gas Leerlauftrim + Hier bin ich mir nicht sicher + Gas-Leerlaufstrimmung @@ -10708,9 +10713,10 @@ r If this is checked the throttle will be reversed. Idle will be forward, trim will also be reversed and the throttle warning will be reversed as well. - Vollgas hinten? -Wenn das angewählt wird, dann ist Leerlauf vorne. Auch die Gas-Leerlauftrimmung und die Gasstellungs-Warung wird -umgedreht und ist dann vorne. + Umgekehrte Gas-Funktion +Wenn angewählt, befindet sich der Leerlauf vorne. Die Gas-Leerlaufstrimmung sowie die Gasstellungs-Warnung werden dadurch +ebenfalls umgekehrt. + @@ -10781,12 +10787,12 @@ umgedreht und ist dann vorne. Trim Step - Trim Auflösung + Trimmschritte Trims Display - Trimmwerte anzeigen + Trimmungswerte anzeigen @@ -10831,7 +10837,7 @@ umgedreht und ist dann vorne. Extended Trims - Erw. Trim 25%--> 100% + Erw. Trimmung 25% --> 100% @@ -10872,7 +10878,7 @@ umgedreht und ist dann vorne. Elevator Channel: - Höhe Kanal: + Höheruderkanal: @@ -11797,47 +11803,47 @@ Error: %2 Style sheet data read from '%1' - + Die Stylesheet-Daten wurden aus der Datei %1 eingelesen Style sheet data unable to be read from '%1' - + Die Stylesheet-Daten konnten nicht aus der Datei %1 eingelesen werden Cannot create folder '%1' - + Der Ordner %1 konnte nicht erstellt werden Cannot open file for writing '%1': Error: %2 - + Die Datei %1 konnte nicht zum schreiben geöffnet werden. Fehler: %2 Cannot write to file '%1': Error: %2 - + In die Datei %1 konnte nicht geschrieben werden. Fehler: %2 Cannot flush buffer for file '%1': Error: %2 - + Der Pufferinhalt konnte nicht in die Datei %1 übernommen werden: Fehler %2 Style sheet written to '%1' - + Die Stylesheet-Daten wurde in der Datei %1 geschrieben Custom style sheet deleted: '%1' - + Das benutzerdefinierte Stylesheet %1 wurde gelöscht Unable to delete custom style sheet: '%1' - + Das benutzerdefinierte Stylesheet %1 konnte nicht gelöscht werden @@ -12005,22 +12011,22 @@ Too many errors, giving up. Elevator and Rudder - Höhe und Seite + Höhen- und Seiteruder Only Elevator - Nur Höhe + Nur Höheruder V-tail - V Leitwerk + V-Leitwerk Tail Type: - Leitwerk Typ: + Leitwerkstyp: @@ -12152,7 +12158,7 @@ Too many errors, giving up. Source - Quelle + Quelle @@ -12162,12 +12168,12 @@ Too many errors, giving up. Altitude source - Höhe Quelle + Höhenquelle Volts source - Spannung Quelle + Spannungsquelle @@ -12177,12 +12183,12 @@ Too many errors, giving up. mAh - mAh + mAh A - A + A @@ -13015,7 +13021,7 @@ Timestamp Meters - Meter + m @@ -13107,7 +13113,7 @@ hh:mm:ss Amps - Ampere + A @@ -13127,7 +13133,7 @@ hh:mm:ss Volts - Volt + V @@ -13157,7 +13163,7 @@ hh:mm:ss Degrees - Grad + ° @@ -13228,7 +13234,7 @@ hh:mm:ss <br>Throttle Channel: - <br>Gas Kanal: + <br>Gaskanal: @@ -13471,19 +13477,19 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. RX # - + RX # Models Translators do NOT use accent for this, this is the default category name on Horus. - Modelle + Modelle Model %1 Translators: do NOT use accents here, this is a default model name. - + Modell %1 @@ -13491,12 +13497,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. First Tail Channel: - Erster rechter Leitwerk Kanal: + Erster Leitwerkskanal: Second Tail Channel: - Zweiter, linker Leitwerk Kanal: + Zweiter Leitwerkskanal: @@ -13560,12 +13566,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Model Wizard - Modell Wizard + Modell-Wizard Model Type - Model Type + Modelltyp @@ -13575,7 +13581,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Throttle - Gas + Antrieb @@ -13585,7 +13591,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Wing Type - Flächen Typ + Flächentyp @@ -13605,12 +13611,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Flaps - Landeklappen + Wölbklappen Has your model got flaps? - Hat das Modell Landeklappen? + Hat das Modell Wölbklappen? @@ -13682,12 +13688,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Which type of swash control is installed in your helicopter? - Welchen Typ an Taumelscheibe hat der Heli? + Welche Art von Taumelscheibe ist verbaut? Tail Gyro - Heck Kreisel + Heckkreisel @@ -13702,7 +13708,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Has your helicopter got a flybar? - + Hat der Hubschrauber eine Flybar? @@ -13719,7 +13725,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Multirotor - MultiCopter + Multikopter @@ -13739,12 +13745,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Save Changes - Speichere die Kanäle + Änderungen speichern Manually check the direction of each control surface and reverse any channels that make controls move in the wrong direction. Remove the propeller/propellers before you try to control your model for the first time.<br>Please note that continuing removes all old model settings! - + Überprüfe, ob alle Steuerflächen sich in die richtige Richtung bewegen und invertiere diese gegebenenfalls. Entferne den oder die Propeller bevor du das Modell zum ersten mal steuerst.<br>Bitte beachte, dass das Fortfahren alle alten Einstellungen überschreibt! @@ -13754,7 +13760,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Select the receiver channel that is connected to your ESC or throttle servo.<br><br>Throttle - Spektrum: CH1, Futaba: CH3 - + Wähle den Empfängerkanal, an den der ESC oder der Gasservo angeschlossen ist.<br><br>Gas - Spektrum: CH1, Futaba: CH3 @@ -13769,12 +13775,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. This wizard assumes that your flaps are controlled by a switch. If your flaps are controlled by a potentiometer you can change that manually later. - + Der Wizard geht davon aus, dass die Wölbklappen durch einen Schalter gesteuert werden. Sollen die Wölbklappen durch ein Poti gesteuert werden, kann dies später noch geändert werden. Air brakes are used to reduce the speed of advanced sail planes.<br>They are very uncommon on other types of planes. - + Störklappen werden eingesetzt um den Widerstand zu erhöhen und damit den Gleitwinkel bei Seglern zu verschlechtern.<br>Für ander Arten von Flugzeugen sind sie eher ungewöhnlich. @@ -13784,23 +13790,23 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Select the receiver channel that is connected to your rudder.<br><br>Rudder - Spektrum: CH4, Futaba: CH4 - + Wähle den Empfängerkanal, an den das Seitenruderservo angeschlossen ist.<br><br>Seitenruder - Spektrum: CH4, Futaba: CH4 Select the tail type of your plane. - Wählen Sie den Leitwerkstyp Ihres Flugzeugs. + Wähle den Leitwerkstyp des Flugzeugs. Select the Rudder and Elevator channels.<br><br>Rudder - Spektrum: CH4, Futaba: CH4<br>Elevator - Spektrum: CH3, Futaba: CH2 - + Wähle den Empfängerkanal, an den Seiten- und das Höhenruderservo angeschlossen ist.<br><br>Seitenruder - Spektrum: CH4, Futaba: CH4<br>Höhenruder - Spektrum: CH3, Futaba: CH2 Select the Elevator channel.<br><br>Elevator - Spektrum: CH3, Futaba: CH2 - Wählen Sie den Kanal für das Höhenleitwerk.<br><br>Höhenleitwerk - Spektrum: CH3, Futaba: CH2 + Wähle den Kanal für das Höhenleitwerk.<br><br>Höhenleitwerk - Spektrum: CH3, Futaba: CH2 @@ -13816,12 +13822,12 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Select the control channels for your multirotor.<br><br>Throttle - Spektrum: CH1, Futaba: CH3<br>Yaw - Spektrum: CH4, Futaba: CH4<br>Pitch - Spektrum: CH3, Futaba: CH2<br>Roll - Spektrum: CH2, Futaba: CH1 - + Wähle die Steuerkanäle für deinen Multikopter.<br><br>Throttle - Spektrum: CH1, Futaba: CH3<br>Yaw - Spektrum: CH4, Futaba: CH4<br>Pitch - Spektrum: CH3, Futaba: CH2<br>Roll - Spektrum: CH2, Futaba: CH1 There is no help available for the current page. - + Für diese Seite steht keine Hilfe zur Verfügung. @@ -13849,17 +13855,17 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Model Name: - Model Name: + Modelname: Model Type: - Model Typ: + Modelltyp: Options: - Optionen: + Optionen: From d41f453f18187fa304dda388f616367978a786a0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 26 Oct 2019 08:57:52 +0200 Subject: [PATCH 223/257] Symlink t6 --- tools/nightly23/build-sdcard.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/nightly23/build-sdcard.sh b/tools/nightly23/build-sdcard.sh index a294794d1..b26956e9c 100755 --- a/tools/nightly23/build-sdcard.sh +++ b/tools/nightly23/build-sdcard.sh @@ -65,6 +65,7 @@ else ln -s ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip ${output}/sdcard/sdcard-taranis-xlite-${sdcard_version}.zip ln -s ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip ${output}/sdcard/sdcard-taranis-x9lite-${sdcard_version}.zip ln -s ${output}/sdcard/sdcard-taranis-x7-${sdcard_version}.zip ${output}/sdcard/sdcard-jumper-t12-${sdcard_version}.zip + ln -s ${output}/sdcard/sdcard-horus-${sdcard_version}.zip ${output}/sdcard/sdcard-jumper-t16-${sdcard_version}.zip # remove LUA stuff for 9x platform rm -Rf ${workdir}/sdcard/taranis-x7/SCRIPTS From adebf51c79427b8173cb658fa980d88595189f54 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 26 Oct 2019 12:40:43 +0200 Subject: [PATCH 224/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index d2e71d520..26546f9e4 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1617,3 +1617,4 @@ Bruno N Russo Jr Daniel Eikenkötter Guy Poignonec Gérard Falaise +Jacques Loubier From a75b19d223658957df98b19c4f7523ed3af4b5b7 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 26 Oct 2019 12:41:09 +0200 Subject: [PATCH 225/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 26546f9e4..c3b46b341 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1618,3 +1618,4 @@ Daniel Eikenkötter Guy Poignonec Gérard Falaise Jacques Loubier +Kelly Warner From 8716714d06ab725a4510325cb4b4fcf499c42610 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 28 Oct 2019 10:24:55 +0100 Subject: [PATCH 226/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index c3b46b341..87e946d57 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1619,3 +1619,4 @@ Guy Poignonec Gérard Falaise Jacques Loubier Kelly Warner +James Cox From 8d2b294001143a77a2ff0ea3f94d321b3e612f34 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 28 Oct 2019 10:27:38 +0100 Subject: [PATCH 227/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 87e946d57..4dc4b7d7c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1620,3 +1620,4 @@ Gérard Falaise Jacques Loubier Kelly Warner James Cox +Sidney B Harden From fafd68b1eee5165dcfe5e582a193c1f108057444 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 28 Oct 2019 14:57:48 +0100 Subject: [PATCH 228/257] Add handling for JumperRC versions (#7015) --- radio/src/CMakeLists.txt | 4 +++ radio/src/stamp.h.in | 6 ++++ tools/build-jumper.py | 78 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100755 tools/build-jumper.py diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 8a84c983a..dcea22226 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -328,6 +328,10 @@ if(MODULE_PROTOCOL_D8) add_definitions(-DMODULE_PROTOCOL_D8) endif() +if(JUMPER_RELEASE) + add_definitions(-DJUMPER_RELEASE) +endif() + if(FRSKY_RELEASE) add_definitions(-DFRSKY_RELEASE) set(POPUP_LEVEL 3) diff --git a/radio/src/stamp.h.in b/radio/src/stamp.h.in index f360b3a90..a8dd9884e 100644 --- a/radio/src/stamp.h.in +++ b/radio/src/stamp.h.in @@ -1,6 +1,12 @@ #define DATE "@DATE@" #define TIME "@TIME@" +#if defined(FRSKY_RELEASE) +#define VERSION "FrSky" +#elif defined(JUMPER_RELEASE) +#define VERSION "JumperRC" +#else #define VERSION "@VERSION@" +#endif #define VERSION_MAJOR @VERSION_MAJOR@ #define VERSION_MINOR @VERSION_MINOR@ diff --git a/tools/build-jumper.py b/tools/build-jumper.py new file mode 100755 index 000000000..0a2db17f3 --- /dev/null +++ b/tools/build-jumper.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 + +import argparse +import datetime +import os +from builtins import NotADirectoryError +import shutil +import tempfile + + +boards = { + "T12": { + "PCB": "X7", + "PCBREV": "T12", + "DEFAULT_MODE": "2", + }, + "T16": { + "PCB": "X10", + "PCBREV": "T16", + "INTERNAL_MODULE_MULTI": "YES", + "DEFAULT_MODE": "2", + } +} + +translations = [ + "EN", +] + + +def timestamp(): + return datetime.datetime.now().strftime("%y%m%d") + + +def build(board, translation, srcdir): + cmake_options = " ".join(["-D%s=%s" % (key, value) for key, value in boards[board].items()]) + cwd = os.getcwd() + if not os.path.exists("output"): + os.mkdir("output") + path = tempfile.mkdtemp() + os.chdir(path) + command = "cmake %s -DTRANSLATIONS=%s -DJUMPER_RELEASE=YES %s" % (cmake_options, translation, srcdir) + print(command) + os.system(command) + os.system("make firmware -j6") + os.chdir(cwd) + index = 0 + while 1: + suffix = "" if index == 0 else "_%d" % index + filename = "output/firmware_%s_%s_%s%s.bin" % (board.lower(), translation.lower(), timestamp(), suffix) + if not os.path.exists(filename): + shutil.copy("%s/firmware.bin" % path, filename) + break + index += 1 + shutil.rmtree(path) + + +def dir_path(string): + if os.path.isdir(string): + return string + else: + raise NotADirectoryError(string) + + +def main(): + parser = argparse.ArgumentParser(description="Build JumperRC firmware") + parser.add_argument("-b", "--boards", action="append", help="Destination boards", required=True) + parser.add_argument("-t", "--translations", action="append", help="Translations", required=True) + parser.add_argument("srcdir", type=dir_path) + + args = parser.parse_args() + + for board in (boards.keys() if "ALL" in args.boards else args.boards): + for translation in (translations if "ALL" in args.translations else args.translations): + build(board, translation, args.srcdir) + + +if __name__ == "__main__": + main() From 484bbcc0b460cb28a33d61ee717346b6b9615681 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 28 Oct 2019 15:13:17 +0100 Subject: [PATCH 229/257] Switch autobold (#7000) Display switches in bold when active, but not on 128 and 212 main view --- radio/src/gui/128x64/lcd.cpp | 4 +++- radio/src/gui/128x64/lcd.h | 2 +- radio/src/gui/128x64/view_main.cpp | 10 +++++----- radio/src/gui/212x64/lcd.cpp | 4 +++- radio/src/gui/212x64/lcd.h | 2 +- radio/src/gui/212x64/view_main.cpp | 2 +- radio/src/gui/480x272/lcd.cpp | 4 +++- radio/src/gui/480x272/lcd.h | 2 +- radio/src/tests/lcd.cpp | 2 +- 9 files changed, 19 insertions(+), 13 deletions(-) diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp index 4a21dc205..4c671b3ad 100644 --- a/radio/src/gui/128x64/lcd.cpp +++ b/radio/src/gui/128x64/lcd.cpp @@ -788,10 +788,12 @@ void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att) } } -void drawSwitch(coord_t x, coord_t y, swsrc_t idx, LcdFlags flags) +void drawSwitch(coord_t x, coord_t y, swsrc_t idx, LcdFlags flags, bool autoBold) { char s[8]; getSwitchPositionName(s, idx); + if (autoBold && idx != SWSRC_NONE && getSwitch(idx)) + flags |= BOLD; lcdDrawText(x, y, s, flags); } diff --git a/radio/src/gui/128x64/lcd.h b/radio/src/gui/128x64/lcd.h index 4f3da257a..b0e16cbd3 100644 --- a/radio/src/gui/128x64/lcd.h +++ b/radio/src/gui/128x64/lcd.h @@ -124,7 +124,7 @@ void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val); void putsModelName(coord_t x, coord_t y, char * name, uint8_t id, LcdFlags att); #if !defined(BOOT) // TODO not here ... -void drawSwitch(coord_t x, coord_t y, swsrc_t swtch, LcdFlags att=0); +void drawSwitch(coord_t x, coord_t y, swsrc_t swtch, LcdFlags att=0, bool autoBold = true); void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att=0); #endif void drawCurveName(coord_t x, coord_t y, int8_t idx, LcdFlags att=0); diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index 8f95220ae..5cf5e059e 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -509,7 +509,7 @@ void menuMainView(event_t event) if (SWITCH_EXISTS(i)) { getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i); getvalue_t sw = ((val < 0) ? 3 * i + 1 : ((val == 0) ? 3 * i + 2 : 3 * i + 3)); - drawSwitch(x[i], y[i], sw, 0); + drawSwitch(x[i], y[i], sw, 0, false); } } drawSmallSwitch(29, 5*FH+1, 4, SW_SF); @@ -521,7 +521,7 @@ void menuMainView(event_t event) if (SWITCH_EXISTS(i)) { getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i); getvalue_t sw = ((val < 0) ? 3 * i + 1 : ((val == 0) ? 3 * i + 2 : 3 * i + 3)); - drawSwitch(x[i], y[i], sw, 0); + drawSwitch(x[i], y[i], sw, 0, false); } } #elif defined(PCBXLITES) @@ -531,7 +531,7 @@ void menuMainView(event_t event) if (SWITCH_EXISTS(i)) { getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i); getvalue_t sw = ((val < 0) ? 3 * i + 1 : ((val == 0) ? 3 * i + 2 : 3 * i + 3)); - drawSwitch(x[i], y[i], sw, 0); + drawSwitch(x[i], y[i], sw, 0, false); } } #elif defined(PCBTARANIS) @@ -545,7 +545,7 @@ void menuMainView(event_t event) } getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i); getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3)); - drawSwitch(x, y, sw, 0); + drawSwitch(x, y, sw, 0, false); } } #else @@ -557,7 +557,7 @@ void menuMainView(event_t event) x = 17*FW-1; y -= 3*FH; } - drawSwitch(x, y, sw, getSwitch(i) ? INVERS : 0); + drawSwitch(x, y, sw, getSwitch(i) ? INVERS : 0, false); } #endif } diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp index 19bb40098..c523643bb 100644 --- a/radio/src/gui/212x64/lcd.cpp +++ b/radio/src/gui/212x64/lcd.cpp @@ -693,10 +693,12 @@ void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att) } } -void drawSwitch(coord_t x, coord_t y, int32_t idx, LcdFlags flags) +void drawSwitch(coord_t x, coord_t y, int32_t idx, LcdFlags flags, bool autoBold) { char s[8]; getSwitchPositionName(s, idx); + if (autoBold && idx != SWSRC_NONE && getSwitch(idx)) + flags |= BOLD; lcdDrawText(x, y, s, flags); } diff --git a/radio/src/gui/212x64/lcd.h b/radio/src/gui/212x64/lcd.h index 8d5fc785c..5c2e86410 100644 --- a/radio/src/gui/212x64/lcd.h +++ b/radio/src/gui/212x64/lcd.h @@ -118,7 +118,7 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags mode, uint8_t len void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags mode=0); void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att); -void drawSwitch(coord_t x, coord_t y, int32_t swtch, LcdFlags att=0); +void drawSwitch(coord_t x, coord_t y, int32_t swtch, LcdFlags att=0, bool autoBold = true); void putsStickName(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0); void drawSource(coord_t x, coord_t y, uint32_t idx, LcdFlags att=0); void drawCurveName(coord_t x, coord_t y, int8_t idx, LcdFlags att=0); diff --git a/radio/src/gui/212x64/view_main.cpp b/radio/src/gui/212x64/view_main.cpp index eee71f097..56e4c22ae 100644 --- a/radio/src/gui/212x64/view_main.cpp +++ b/radio/src/gui/212x64/view_main.cpp @@ -532,7 +532,7 @@ void menuMainView(event_t event) if (SWITCH_EXISTS(i)) { getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i); getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3)); - drawSwitch((g_model.view == VIEW_INPUTS) ? (index<4 ? 8*FW+1 : 23*FW+2) : (index<4 ? 3*FW+1 : 8*FW-2), (index%4)*FH+3*FH, sw, 0); + drawSwitch((g_model.view == VIEW_INPUTS) ? (index<4 ? 8*FW+1 : 23*FW+2) : (index<4 ? 3*FW+1 : 8*FW-2), (index%4)*FH+3*FH, sw, 0, false); index++; } } diff --git a/radio/src/gui/480x272/lcd.cpp b/radio/src/gui/480x272/lcd.cpp index 3623aa955..eed5ed6d8 100644 --- a/radio/src/gui/480x272/lcd.cpp +++ b/radio/src/gui/480x272/lcd.cpp @@ -283,10 +283,12 @@ void putsModelName(coord_t x, coord_t y, char * name, uint8_t id, LcdFlags att) } } -void drawSwitch(coord_t x, coord_t y, swsrc_t idx, LcdFlags flags) +void drawSwitch(coord_t x, coord_t y, swsrc_t idx, LcdFlags flags, bool autoBold) { char s[8]; getSwitchPositionName(s, idx); + if (autoBold && idx != SWSRC_NONE && getSwitch(idx)) + flags |= BOLD; lcdDrawText(x, y, s, flags); } diff --git a/radio/src/gui/480x272/lcd.h b/radio/src/gui/480x272/lcd.h index adce60fbb..455eca8d2 100644 --- a/radio/src/gui/480x272/lcd.h +++ b/radio/src/gui/480x272/lcd.h @@ -147,7 +147,7 @@ void drawTimer(coord_t x, coord_t y, int32_t tme, LcdFlags att=0); void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att); void putsStickName(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0); -void drawSwitch(coord_t x, coord_t y, swsrc_t swtch, LcdFlags flags=0); +void drawSwitch(coord_t x, coord_t y, swsrc_t swtch, LcdFlags flags=0, bool autoBold = true); void drawSource(coord_t x, coord_t y, mixsrc_t idx, LcdFlags att=0); void drawCurveName(coord_t x, coord_t y, int8_t idx, LcdFlags att=0); void drawTimerMode(coord_t x, coord_t y, swsrc_t mode, LcdFlags att=0); diff --git a/radio/src/tests/lcd.cpp b/radio/src/tests/lcd.cpp index 8375c6f63..5bce5d535 100644 --- a/radio/src/tests/lcd.cpp +++ b/radio/src/tests/lcd.cpp @@ -259,7 +259,7 @@ TEST(Lcd, Dblsize) TEST(Lcd, DrawSwitch) { lcdClear(); - drawSwitch(0, 10, SWSRC_SA0, 0); + drawSwitch(0, 10, SWSRC_SA0, 0, false); drawSwitch(30, 10, SWSRC_SA0, SMLSIZE); // drawSwitch(60, 10, SWSRC_SA0, MIDSIZE); missing arrows in this font drawSwitch(90, 10, SWSRC_SA0, DBLSIZE); From ff84c8511e1297d319e0cac6d2acd772f975b35a Mon Sep 17 00:00:00 2001 From: Marco Robustini Date: Mon, 28 Oct 2019 15:15:14 +0100 Subject: [PATCH 230/257] Update it.h.txt (#7013) * Update it.h.txt 1) Better global alignment with the EN version 2) Fixed some items * Update it.h.txt Other fixes --- radio/src/translations/it.h.txt | 210 ++++++++++++++++---------------- 1 file changed, 105 insertions(+), 105 deletions(-) diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 5359c97fc..f72256b25 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -433,25 +433,25 @@ #define TR_MENUWHENDONE CENTER "\007" TR_ENTER " Conferma" #define TR_FREE "Disp." -#define TR_DELETEMODEL "Elimina modello?" +#define TR_DELETEMODEL "CANCELLA" BREAKSPACE "MODELLO" #define TR_COPYINGMODEL "Copia in corso.." #define TR_MOVINGMODEL "Spostamento..." #define TR_LOADINGMODEL "Caricamento..." #define TR_NAME "Nome" -#define TR_MODELNAME TR(INDENT"Nome Mode.", INDENT"Nome Modello") +#define TR_MODELNAME TR("Nome Mode.", "Nome Modello") #define TR_PHASENAME "Nome fase" #define TR_MIXNAME "Nome mix" #define TR_INPUTNAME "Nome Ingr." #define TR_EXPONAME "Nome expo" #define TR_BITMAP "Immagine" -#define TR_TIMER TR(INDENT"Timer", INDENT"Timer ") -#define TR_ELIMITS TR(INDENT"Limiti.E", INDENT"Limiti Estesi") -#define TR_ETRIMS TR(INDENT"Trim Ext", INDENT"Trim Estesi") +#define TR_TIMER TR("Timer", "Timer ") +#define TR_ELIMITS TR("Limiti.E", "Limiti Estesi") +#define TR_ETRIMS TR("Trim Ext", "Trim Estesi") #define TR_TRIMINC "Passo Trim" -#define TR_DISPLAY_TRIMS TR(INDENT "Mos. Trims", INDENT "Mostra Trims") -#define TR_TTRACE TR(INDENT "So. motore", INDENT "Sorgente Motore") -#define TR_TTRIM TR(INDENT "Trim Mot.", INDENT "Trim Motore") -#define TR_BEEPCTR TR(INDENT "Beep al c.", INDENT "Beep al centro") +#define TR_DISPLAY_TRIMS TR("Mos. Trims", "Mostra Trims") +#define TR_TTRACE TR("So. motore", INDENT "Sorgente Motore") +#define TR_TTRIM TR("Trim Mot.", INDENT "Trim Motore") +#define TR_BEEPCTR TR("Beep al c.", "Beep al centro") #define TR_USE_GLOBAL_FUNCS "Usa Funz. Globali" #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Uscita" @@ -470,13 +470,13 @@ #define TR_CHECKTRIMS CENTER "\006Contr.\012Trims" #define OFS_CHECKTRIMS CENTER_OFS+(9*FW) #define TR_SWASHTYPE "Tipo Ciclico" -#define TR_COLLECTIVE TR(INDENT"Collettivo", INDENT"Origine Collettivo") -#define TR_AILERON TR(INDENT"Cic. later.", INDENT"Sorg. cic. later.") -#define TR_ELEVATOR TR(INDENT"Cic. long.", INDENT"Sorg. cic. long.") +#define TR_COLLECTIVE TR("Collettivo", "Origine Collettivo") +#define TR_AILERON TR("Cic. later.", "Sorg. cic. later.") +#define TR_ELEVATOR TR("Cic. long.", "Sorg. cic. long.") #define TR_SWASHRING "Anello Ciclico" -#define TR_ELEDIRECTION TR(INDENT"Direzione ELE", INDENT"Direzione cic. long.") -#define TR_AILDIRECTION TR(INDENT"Direzione AIL", INDENT"Direzione cic. lat.") -#define TR_COLDIRECTION TR(INDENT"Direzione PIT", INDENT"Direzione passo coll.") +#define TR_ELEDIRECTION TR("Direzione ELE", "Direzione cic. long.") +#define TR_AILDIRECTION TR("Direzione AIL", "Direzione cic. lat.") +#define TR_COLDIRECTION TR("Direzione PIT", "Direzione passo coll.") #define TR_MODE "Modo" #define TR_SUBTYPE INDENT "Sottotipo" #define TR_NOFREEEXPO "Expo pieni!" @@ -491,11 +491,11 @@ #define TR_DREX "DRex" #define DREX_CHBOX_OFFSET 30 #define TR_CURVE "Curva" -#define TR_FLMODE "Fase" +#define TR_FLMODE TR("Fase", "Fasi") #define TR_MIXWARNING "Avviso" #define TR_OFF "OFF" -#define TR_ANTENNA "Antenna" -#define TR_NO_INFORMATION TR(INDENT"No info", INDENT"No informazione") +#define TR_ANTENNA "Antenna" +#define TR_NO_INFORMATION TR("No info", "No informazione") #define TR_MULTPX "MultPx" #define TR_DELAYDOWN "Post.Giù " #define TR_DELAYUP "Post.Su" @@ -505,46 +505,46 @@ #define TR_CV "CV" #define TR_GV TR("G", "GV") #define TR_ACHANNEL "A\002ingresso" -#define TR_RANGE TR(INDENT"Inter.", INDENT"Intervallo") +#define TR_RANGE TR(INDENT "Inter.", INDENT "Intervallo") #define TR_CENTER INDENT "Centro" #define TR_BAR "Barra" -#define TR_ALARM TR(INDENT"Allar.", INDENT"Allarme") +#define TR_ALARM TR(INDENT "Allar.", INDENT "Allarme") #define TR_USRDATA "Dati" -#define TR_BLADES INDENT"Pale" -#define TR_SCREEN TR(INDENT"Scher. ", INDENT"Schermo ") +#define TR_BLADES INDENT "Pale" +#define TR_SCREEN "Schermo\001" #define TR_SOUND_LABEL "Suono" -#define TR_LENGTH INDENT"Durata" +#define TR_LENGTH INDENT "Durata" #define TR_BEEP_LENGTH INDENT "Lung. Beep" -#define TR_SPKRPITCH INDENT"Tono" +#define TR_SPKRPITCH INDENT "Tono" #define TR_HAPTIC_LABEL "Vibrazione" -#define TR_HAPTICSTRENGTH INDENT"Forza" +#define TR_HAPTICSTRENGTH INDENT "Forza" #define TR_GYRO_LABEL "Gyro" #define TR_GYRO_OFFSET "Offset" #define TR_GYRO_MAX "Max" #define TR_CONTRAST "Contrasto" #define TR_ALARMS_LABEL "Allarmi" -#define TR_BATTERY_RANGE TR(INDENT "Int. Batt.", INDENT "Intervallo batteria") +#define TR_BATTERY_RANGE TR("Int. Batt.", "Intervallo batteria") #define TR_BATTERYWARNING TR(INDENT "Avv. Batt.", INDENT "Avviso Batteria") -#define TR_INACTIVITYALARM INDENT"Inattività" +#define TR_INACTIVITYALARM INDENT "Inattività" #define TR_MEMORYWARNING TR(INDENT "Avv. Mem.", INDENT "Avviso Memoria") -#define TR_ALARMWARNING INDENT"Spegni suono" +#define TR_ALARMWARNING INDENT "Spegni suono" #define TR_RSSISHUTDOWNALARM TR(INDENT "RSSI Shut.", INDENT "Control. RSSI al Shutdown") #define TR_MODEL_STILL_POWERED "Modello ancora acceso" #define TR_MODEL_SHUTDOWN "Shutdown?" #define TR_PRESS_ENTER_TO_CONFIRM "Premi [ENT] per confermare" #define TR_THROTTLE_LABEL "Motore" -#define TR_THROTTLEREVERSE TR(INDENT "Mot inv.", INDENT "Motore Inverso") +#define TR_THROTTLEREVERSE TR("Mot inv.", "Motore Inverso") #define TR_MINUTEBEEP "Minuto" -#define TR_BEEPCOUNTDOWN TR(INDENT"Conto rov", INDENT"Conto rovescia") -#define TR_PERSISTENT TR(INDENT"Persist.", INDENT"Persistente") -#define TR_BACKLIGHT_LABEL TR(INDENT "Retroillu.", INDENT "Retroilluminazione") -#define TR_BLDELAY INDENT"Durata" -#define TR_BLONBRIGHTNESS TR(INDENT"Lumin. ON", INDENT"Luminosità ON") -#define TR_BLOFFBRIGHTNESS TR(INDENT"Lumin. OFF", INDENT"Luminosità OFF") +#define TR_BEEPCOUNTDOWN TR(INDENT "Conto rov", INDENT "Conto rovescia") +#define TR_PERSISTENT TR(INDENT "Persist.", INDENT "Persistente") +#define TR_BACKLIGHT_LABEL TR("Retroillu.", "Retroilluminazione") +#define TR_BLDELAY INDENT "Durata" +#define TR_BLONBRIGHTNESS TR(INDENT "Lumin. ON", INDENT "Luminosità ON") +#define TR_BLOFFBRIGHTNESS TR(INDENT "Lumin. OFF", INDENT "Luminosità OFF") #define TR_BLCOLOR INDENT "Colore" -#define TR_SPLASHSCREEN TR(INDENT "Sch. avvio", INDENT "Schermata d'avvio") -#define TR_PWR_ON_DELAY "Rit. PWR ON" -#define TR_PWR_OFF_DELAY "Rit. PWR OFF" +#define TR_SPLASHSCREEN TR("Sch. avvio", "Schermata d'avvio") +#define TR_PWR_ON_DELAY "Rit. accens." +#define TR_PWR_OFF_DELAY "Rit. spegni." #define TR_THROTTLEWARNING TR(INDENT "All. Mot.", INDENT "Allarme Motore") #define TR_SWITCHWARNING TR(INDENT "Avv. Int.", INDENT "Avviso Interr.") #define TR_POTWARNINGSTATE TR(INDENT "Pot&Slid.", INDENT "Pots & sliders") @@ -557,7 +557,7 @@ #define TR_STICKS "Sticks" #define TR_POTS "Pot." #define TR_SWITCHES "Interutt." -#define TR_SWITCHES_DELAY TR(INDENT "Rit. V. FV", INDENT "Ritardo Voce FV") +#define TR_SWITCHES_DELAY TR("Rit. V. FV", "Ritardo Voce FV") #define TR_SLAVE "Allievo" #define TR_MODESRC "Modo\006% Origine" #define TR_MULTIPLIER "Moltiplica" @@ -594,7 +594,7 @@ #define TR_EEPROMLOWMEM "EEPROM quasi piena!" #define TR_ALERT "\016ALERT" #define TR_PRESSANYKEYTOSKIP "\010Premi un tasto" -#define TR_THROTTLENOTIDLE TR(INDENT"Motore non in posiz.", INDENT"Motore non in posizione") +#define TR_THROTTLENOTIDLE TR("Motore non in posiz.", "Motore non in posizione") #define TR_ALARMSDISABLED "Avvisi Disattivati!" #define TR_PRESSANYKEY "\010Premi un tasto" #define TR_BADEEPROMDATA "Dati corrotti!" @@ -629,8 +629,8 @@ #define TR_MENUCURVES "CURVE" #define TR_MENUCURVE "CURVA" #define TR_MENULOGICALSWITCH "INTER. PERSON." -#define TR_MENULOGICALSWITCHES TR(INDENT"INTER. LOGICI", INDENT"INTERRUTTORI LOGICI") -#define TR_MENUCUSTOMFUNC TR(INDENT"FUNZ. SPECIALI", INDENT"FUNZIONI SPECIALI") +#define TR_MENULOGICALSWITCHES TR("INTER. LOGICI", "INTERRUTTORI LOGICI") +#define TR_MENUCUSTOMFUNC TR("FUNZ. SPECIALI", "FUNZIONI SPECIALI") #define TR_MENUCUSTOMSCRIPTS "SCRIPTS UTENTE" #define TR_MENUTELEMETRY "TELEMETRIA" #define TR_MENUTEMPLATES "ESEMPI GUIDA" @@ -643,22 +643,22 @@ #define TR_MONITOR_CHANNELS4 "MONITOR CANALI 25/32" #define TR_MONITOR_OUTPUT_DESC "Uscite" #define TR_MONITOR_MIXER_DESC "Mixers" -#define TR_RECEIVER_NUM TR(INDENT"RxNum", INDENT"Ricevente N.") +#define TR_RECEIVER_NUM TR("RxNum", "Ricevente N.") #define TR_RECEIVER "Ricevente" -#define TR_MULTI_RFTUNE TR(INDENT"Tune RF", INDENT"Tune fine Freq. RF") +#define TR_MULTI_RFTUNE TR("Tune RF", "Tune fine Freq. RF") #define TR_MULTI_TELEMETRY "Telemetria" -#define TR_MULTI_VIDFREQ TR(INDENT"Freq. video", INDENT"Frequenza video") +#define TR_MULTI_VIDFREQ TR("Freq. video", "Frequenza video") #define TR_RFPOWER "Potenza RF" -#define TR_MULTI_FIXEDID TR(INDENT"FixedID", INDENT"Fixed ID") -#define TR_MULTI_OPTION TR(INDENT"Opzione", INDENT"Opzione valore") +#define TR_MULTI_FIXEDID TR("FixedID", "Fixed ID") +#define TR_MULTI_OPTION TR("Opzione", "Opzione valore") #define TR_MULTI_AUTOBIND TR(INDENT "Autoassoc.",INDENT "Associa automat.") #define TR_MULTI_DSM_AUTODTECT TR(INDENT "Trova autom.", INDENT "Autoril. il formato") #define TR_MULTI_LOWPOWER TR(INDENT "Bassa pot.", INDENT "Modo bassa potenza") #define TR_MODULE_TELEMETRY TR(INDENT "S.Port", INDENT "Link S.Port") -#define TR_MODULE_TELEM_ON TR(INDENT"ON", INDENT"Abilitato") -#define TR_DISABLE_INTERNAL TR(INDENT"Disatt. RF int.", INDENT"Disattiva RF interna") -#define TR_MODULE_NO_SERIAL_MODE TR(INDENT"!modo seriale", INDENT"Non in modo seriale") -#define TR_MODULE_NO_INPUT TR(INDENT"Nessun input", INDENT"Nessun input seriale") +#define TR_MODULE_TELEM_ON TR("ON", "Abilitato") +#define TR_DISABLE_INTERNAL TR("Disatt. RF int.", "Disattiva RF interna") +#define TR_MODULE_NO_SERIAL_MODE TR("!modo seriale", "Non in modo seriale") +#define TR_MODULE_NO_INPUT TR("Nessun input", "Nessun input seriale") #define TR_MODULE_NO_TELEMETRY TR3("No telemetria", "MULTI_TELEMETRY disattivato", "Nessuna telem. (abilita MULTI_TELEMETRY)") #define TR_MODULE_WAITFORBIND "Associa per caricare il protocollo" #define TR_MODULE_BINDING "Associa" @@ -669,23 +669,23 @@ #define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF" #define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON" #define TR_BINDING_CH9_16_TELEM_OFF "Ch9-16 Telem OFF" -#define TR_PROTOCOL_INVALID TR(INDENT"Prot. invalido", INDENT"Protocollo invalido") +#define TR_PROTOCOL_INVALID TR("Prot. invalido", "Protocollo invalido") #define TR_MODULE_STATUS TR(INDENT "Stato", INDENT "Stato del modulo") #define TR_MODULE_SYNC TR(INDENT "Sinc.", INDENT "Sinc. del modulo") -#define TR_MULTI_SERVOFREQ TR(INDENT"Servo rate", INDENT"Aggiorna servo rate") +#define TR_MULTI_SERVOFREQ TR("Servo rate", "Aggiorna servo rate") #define TR_SYNCMENU "[Sync]" #define TR_LIMIT INDENT "Limiti" #define TR_MINRSSI "Min. RSSI" #define TR_LATITUDE "Latitud." #define TR_LONGITUDE "Longitud." -#define TR_GPSCOORD TR(INDENT"GPS Coords", INDENT "Formato Coordinate") -#define TR_VARIO TR(INDENT"Vario", INDENT"Variometro") +#define TR_GPSCOORD TR("GPS Coords", INDENT "Formato Coordinate") +#define TR_VARIO TR("Vario", "Variometro") #define TR_PITCH_AT_ZERO INDENT "Tono a Zero" #define TR_PITCH_AT_MAX INDENT "Tono al Max" #define TR_REPEAT_AT_ZERO INDENT "Ripeti a Zero" #define TR_SHUTDOWN "ARRESTO.." #define TR_SAVEMODEL "Salvataggio dati modello" -#define TR_BATT_CALIB "Calibra batt." +#define TR_BATT_CALIB TR("Calibra batt.", "Calibr. batteria") #define TR_CURRENT_CALIB "Calibra corr." #define TR_VOLTAGE TR(INDENT "Voltagg.",INDENT "Voltaggio") #define TR_CURRENT TR(INDENT "Corrente",INDENT "Corrente") @@ -698,12 +698,12 @@ #define TR_COPY_MODEL "Copia Modello" #define TR_MOVE_MODEL "Sposta Modello" #define TR_BACKUP_MODEL "Salva Modello" -#define TR_DELETE_MODEL TR(INDENT"Elim. Modello",INDENT"Elimina Modello") // TODO merged into DELETEMODEL? -#define TR_RESTORE_MODEL TR(INDENT"Ripr. Modello",INDENT"Ripristina Modello") +#define TR_DELETE_MODEL TR("Elim. Modello", "Elimina Modello") +#define TR_RESTORE_MODEL TR("Ripr. Modello", "Ripristina Modello") #define TR_DELETE_ERROR "Errore cancell." #define TR_CAT_NOT_EMPTY "Categoria non vuota" -#define TR_SDCARD_ERROR "Errore SD" -#define TR_NO_SDCARD "No SDCARD" +#define TR_SDCARD_ERROR TR("Errore SD", "Errore SDCard") +#define TR_NO_SDCARD "No SDCard" #define TR_WAITING_FOR_RX "Attendo la RX..." #define TR_WAITING_FOR_TX "Attendo la TX..." #define TR_NO_TOOLS "Tools non disp." @@ -713,9 +713,9 @@ #define TR_CONNECTED "Connesso" #define TR_FLEX_915 "Flex 915MHz" #define TR_FLEX_868 "Flex 868MHz" -#define TR_16CH_WITHOUT_TELEMETRY TR(INDENT"16CH senza telem.", INDENT"16CH senza telemetria") -#define TR_16CH_WITH_TELEMETRY TR(INDENT"16CH con telem.", INDENT"16CH con telemetria") -#define TR_8CH_WITH_TELEMETRY TR(INDENT"8CH con telem.", INDENT"8CH con telemetria") +#define TR_16CH_WITHOUT_TELEMETRY TR("16CH senza telem.", "16CH senza telemetria") +#define TR_16CH_WITH_TELEMETRY TR("16CH con telem.", "16CH con telemetria") +#define TR_8CH_WITH_TELEMETRY TR("8CH con telem.", "8CH con telemetria") #define TR_EXT_ANTENNA "Antenna Ext." #define TR_PIN "Pin" #define TR_UPDATE_RX_OPTIONS "Agg. opzioni RX?" @@ -748,19 +748,19 @@ #define TR_ALARMSWARN "ALLARMI" #define TR_SWITCHWARN "CONTROLLI" #define TR_FAILSAFEWARN "FAILSAFE" -#define TR_NIGHTLY_WARNING TR(INDENT"NIGHTLY", INDENT"NIGHTLY BUILD") +#define TR_NIGHTLY_WARNING TR("NIGHTLY", "NIGHTLY BUILD") #define TR_NIGHTLY_NOTSAFE "Versione non sicura per volare" -#define TR_WRONG_SDCARDVERSION TR(INDENT"Richiede ver: ", INDENT"Richiede versione: ") +#define TR_WRONG_SDCARDVERSION TR("Richiede ver: ", "Richiede versione: ") #define TR_WARN_RTC_BATTERY_LOW "Batteria RTC scarica" #define TR_WARN_MULTI_LOWPOWER "Modalità bassa pot." #define TR_BATTERY "BATTERIA" #define TR_WRONG_PCBREV "PCB sbagliato" #define TR_EMERGENCY_MODE "MODALITA' EMERGENZA" #define TR_PCBREV_ERROR "Errore PCB" -#define TR_NO_FAILSAFE "Failsafe non settato" +#define TR_NO_FAILSAFE "Failsafe" BREAKSPACE "non settato" #define TR_KEYSTUCK "Tasto bloccato" #define TR_INVERT_THR "Inverti Mot?" -#define TR_SPEAKER_VOLUME "Volume Audio" +#define TR_SPEAKER_VOLUME INDENT "Volume Audio" #define TR_LCD "LCD" #define TR_BRIGHTNESS INDENT "Luminosità" #define TR_CPU_TEMP "Temp CPU \016>" @@ -777,10 +777,10 @@ #define TR_DELAY "Ritardo" #define TR_SD_CARD "SD Card" #define TR_SDHC_CARD "SD-HC Card" -#define TR_NO_SOUNDS_ON_SD "No Suoni su SD" -#define TR_NO_MODELS_ON_SD "No Model. su SD" -#define TR_NO_BITMAPS_ON_SD "No Immag. su SD" -#define TR_NO_SCRIPTS_ON_SD "No Scripts su SD" +#define TR_NO_SOUNDS_ON_SD "No Suoni" BREAKSPACE "su SD" +#define TR_NO_MODELS_ON_SD "No Model." BREAKSPACE "su SD" +#define TR_NO_BITMAPS_ON_SD "No Immag." BREAKSPACE "su SD" +#define TR_NO_SCRIPTS_ON_SD "No Scripts" BREAKSPACE "su SD" #define TR_SCRIPT_SYNTAX_ERROR "Script errore sintassi" #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script fermato" @@ -788,8 +788,8 @@ #define TR_PLAY_FILE "Suona" #define TR_DELETE_FILE "Elimina" #define TR_COPY_FILE "Copia" -#define TR_RENAME_FILE "Rinomomina" -#define TR_ASSIGN_BITMAP "Assegna Immagine" +#define TR_RENAME_FILE "Rinomina" +#define TR_ASSIGN_BITMAP "Assegna immagine" #define TR_ASSIGN_SPLASH "Splash screen" #define TR_EXECUTE_FILE "Esegui" #define TR_REMOVED " rimosso" @@ -797,8 +797,8 @@ #define TR_SD_FORMAT "Format" #define TR_NA "N/A" #define TR_HARDWARE "HARDWARE" -#define TR_FORMATTING "Formattazione." -#define TR_TEMP_CALIB "Temp. Calib" +#define TR_FORMATTING "Formattazione" +#define TR_TEMP_CALIB "Temp. Calib." #define TR_TIME "Ora" #define TR_MAXBAUDRATE "Bauds Max" @@ -808,7 +808,7 @@ #define TR_BLUETOOTH_DIST_ADDR "Ind. Dist." #define TR_BLUETOOTH_LOCAL_ADDR "Ind. Loc." #define TR_BLUETOOTH_PIN_CODE "Codice PIN" -#define TR_BAUDRATE "BT Baudrate" +#define TR_BAUDRATE "Baudrate BT" #define LEN_BLUETOOTH_MODES "\011" #if defined(PCBX9E) #define TR_BLUETOOTH_MODES "---\0 ""Attivo\0 " @@ -835,28 +835,28 @@ #define TR_VIEW_TEXT "Vedi testo" #define TR_FLASH_BOOTLOADER "Prog. bootloader" #define TR_FLASH_EXTERNAL_DEVICE "Progr. dispositivo Esterno" -#define TR_FLASH_RECEIVER_OTA "Prog. ricevente OTA" -#define TR_FLASH_BLUETOOTH_MODULE TR(INDENT"Prog modulo BT", INDENT"Prog. modulo Bluetooth") -#define TR_FLASH_POWER_MANAGEMENT_UNIT "Programmazione PMU" -#define TR_CURRENT_VERSION TR(INDENT"Vers. currente ", INDENT"Versione corrente: ") -#define TR_FLASH_INTERNAL_MODULE "Progr. Modulo Interno" -#define TR_FLASH_INTERNAL_MULTI TR(INDENT"Prog. Multi int.", INDENT"Prog. Multi interno") -#define TR_FLASH_EXTERNAL_MODULE "Prog. modulo esterno" -#define TR_FLASH_EXTERNAL_MULTI TR(INDENT"Prog. Multi est.", INDENT"Prog. Multi esterno") -#define TR_FIRMWARE_UPDATE_ERROR TR(INDENT"Errore agg. FW",INDENT"Errore aggiornamento firmware") -#define TR_FIRMWARE_UPDATE_SUCCESS "Agg. riuscito" -#define TR_WRITING "\032Scrivendo..." +#define TR_FLASH_RECEIVER_OTA TR("Prog. RX OTA", INDENT "Prog. ricevente OTA") +#define TR_FLASH_BLUETOOTH_MODULE TR("Prog. mod. BT", INDENT "Prog. modulo Bluetooth") +#define TR_FLASH_POWER_MANAGEMENT_UNIT TR("Prog. PMU", "Program. PMU") +#define TR_CURRENT_VERSION TR("Vers. currente ", "Versione corrente: ") +#define TR_FLASH_INTERNAL_MODULE "Progr. modulo int." +#define TR_FLASH_EXTERNAL_MODULE "Progr. modulo est." +#define TR_FLASH_INTERNAL_MULTI "Prog. Multi int." +#define TR_FLASH_EXTERNAL_MULTI "Prog. Multi est." +#define TR_FIRMWARE_UPDATE_ERROR TR(INDENT "Errore agg. FW",INDENT "Errore aggiornamento firmware") +#define TR_FIRMWARE_UPDATE_SUCCESS "Aggiornamento" BREAKSPACE "riuscito" +#define TR_WRITING "Scrittura..." #define TR_CONFIRM_FORMAT "Confermi Formattazione?" #define TR_INTERNALRF "Modulo Interno" -#define TR_INTERNAL_MODULE TR(INDENT"Modulo int.",INDENT"Modulo interno") -#define TR_EXTERNAL_MODULE TR(INDENT"Modulo est.", INDENT"Modulo esterno") +#define TR_INTERNAL_MODULE TR("Modulo int.", "Modulo interno") +#define TR_EXTERNAL_MODULE TR("Modulo est.", "Modulo esterno") #define TR_OPENTX_UPGRADE_REQUIRED "OpenTX richiede aggiornamento" #define TR_TELEMETRY_DISABLED "Telem. disabilitata" #define TR_MORE_OPTIONS_AVAILABLE "Altre opzioni assenti" #define TR_NO_MODULE_INFORMATION "Nessuna info del modulo" #define TR_EXTERNALRF "Modulo esterno" #define TR_FAILSAFE "Modo failsafe" -#define TR_FAILSAFESET TR(INDENT"FAILSAFE", INDENT"IMPOSTAZIONI FAILSAFE") +#define TR_FAILSAFESET TR(INDENT "FAILSAFE", INDENT "IMPOSTAZIONI FAILSAFE") #define TR_REG_ID "Reg. ID" #define TR_OWNER_ID "Owner ID" #define TR_PINMAPSET "PINMAP" @@ -875,9 +875,9 @@ #define TR_MENU_SPECTRUM_ANALYSER "ANALIZZATORE SPETTRO" #define TR_MENU_POWER_METER "MISURATORE POTENZA" #define TR_SENSOR "SENSORE" -#define TR_COUNTRYCODE TR(INDENT"Cod. Paese", INDENT"Codice del Paese") +#define TR_COUNTRYCODE TR("Cod. Paese", "Codice del Paese") #define TR_USBMODE "Modo USB" -#define TR_JACKMODE "Modo JACK" +#define TR_JACKMODE "Modo JACK" #define TR_VOICELANG "Lingua Voce" #define TR_UNITSSYSTEM "Unità" #define TR_EDIT "Modifica" @@ -903,8 +903,8 @@ #define TR_AND_SWITCH "Inter. AND" #define TR_SF "CF" #define TR_GF "GF" -#define TR_SPEAKER INDENT"Speaker" -#define TR_BUZZER INDENT"Buzzer" +#define TR_SPEAKER INDENT "Speaker" +#define TR_BUZZER INDENT "Buzzer" #define TR_BYTES "Bytes" #define TR_MODULE_BIND "[Bind]" #define TR_POWERMETER_ATTN_NEEDED "Attenuatore necessario" @@ -918,19 +918,19 @@ #define TR_RECEIVER_RESET "Resetto RX?" #define TR_SHARE "Condividere" #define TR_BIND "Bind" -#define TR_REGISTER TR(INDENT"Reg", INDENT"Registrare") +#define TR_REGISTER TR("Reg", "Registrare") #define TR_MODULE_RANGE "[Range]" -#define TR_RECEIVER_OPTIONS TR(INDENT"OPZIONI RX", INDENT"OPZIONI RICEVENTE") +#define TR_RECEIVER_OPTIONS TR("OPZIONI RX", "OPZIONI RICEVENTE") #define TR_DEL_BUTTON BUTTON(TR("Canc.", "Cancella")) #define TR_RESET_BTN "[Reset]" #define TR_DEBUG "Debug" #define TR_KEYS_BTN BUTTON(TR("SW","Interruttori")) #define TR_ANALOGS_BTN BUTTON(TR("Analogico","Analogici")) -#define TR_CALIBRATION TR(INDENT "Calibraz.", INDENT "Calibrazione") +#define TR_CALIBRATION TR("Calibraz.", "Calibrazione") #define TR_SET "[Set]" -#define TR_TRAINER TR(INDENT"Trainer", INDENT"Maestro/Allievo") +#define TR_TRAINER TR("Trainer", "Maestro/Allievo") #define TR_ANTENNAPROBLEM CENTER "Problemi antenna TX!" -#define TR_MODELIDUSED TR(INDENT"ID già usato", INDENT"ID Modello già usato") +#define TR_MODELIDUSED TR("ID già usato", "ID Modello già usato") #define TR_MODULE "Modulo" #define TR_RX_NAME "Nome RX" #define TR_TELEMETRY_TYPE "Tipo Telemetria" @@ -948,17 +948,17 @@ #define LEN_ANTENNA_MODES "\011" #define TR_ANTENNA_MODES "Interna\0""Chiedi\0 ""Per modello""Esterna" #endif -#define TR_USE_INTERNAL_ANTENNA TR(INDENT "Usa ant. int.", INDENT "Usa antenna interna") -#define TR_USE_EXTERNAL_ANTENNA TR(INDENT "Usa ant. est.", INDENT "Usa antenna esterna") -#define TR_ANTENNACONFIRM2 TR(INDENT "Controlla antenna", INDENT "Controlla se l'antenna è installata!") +#define TR_USE_INTERNAL_ANTENNA TR("Usa ant. int.", "Usa antenna interna") +#define TR_USE_EXTERNAL_ANTENNA TR("Usa ant. est.", "Usa antenna esterna") +#define TR_ANTENNACONFIRM2 TR("Controlla antenna", "Controlla se l'antenna è installata!") #define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Non richiede" #define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Richiede FCC" #define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Richiede EU" #define TR_MODULE_PROTOCOL_WARN_LINE2 "firmware certificato" #define TR_LOWALARM INDENT "Allarme Basso" #define TR_CRITICALALARM INDENT "Allarme Critico" -#define TR_RSSIALARM_WARN TR("Tel. RSSI","TELEMETRY RSSI") -#define TR_NO_RSSIALARM TR(INDENT "Allarmi disab.", INDENT "Allarmi telemetrici disabilitati") +#define TR_RSSIALARM_WARN TR(INDENT "Tel. RSSI", "TELEMETRIA RSSI") +#define TR_NO_RSSIALARM TR("Allarmi disab.", "Allarmi telemetrici disabilitati") #define TR_DISABLE_ALARM TR(INDENT "Allarmi disab.", INDENT "Allarmi telemetrici disabilitati") #define TR_ENABLE_POPUP "Abilita Popup" #define TR_DISABLE_POPUP "Disabilita Popup" @@ -1173,7 +1173,7 @@ #define TR_MENU_OTHER "Altro" #define TR_MENU_INVERT "Inverti" #define TR_JITTER_FILTER "Filtro ADC" -#define TR_RTC_CHECK TR(INDENT"Controllo RTC", INDENT"Controllo voltaggio RTC") +#define TR_RTC_CHECK TR("Controllo RTC", "Controllo voltaggio RTC") #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" From f37daba71c6dc950c8a33e323901dba223767567 Mon Sep 17 00:00:00 2001 From: Eldenroot <778890+Eldenroot@users.noreply.github.com> Date: Mon, 28 Oct 2019 15:16:46 +0100 Subject: [PATCH 231/257] Few translations fixes (CZE) (#6917) I would like to ask somebody else (native Czech speaker) to check it out... this is only the first part, I will create another PR when I will have more time. --- companion/src/translations/companion_cs.ts | 109 +++++++++++---------- 1 file changed, 55 insertions(+), 54 deletions(-) diff --git a/companion/src/translations/companion_cs.ts b/companion/src/translations/companion_cs.ts index d309f5076..f2a6ac6e7 100644 --- a/companion/src/translations/companion_cs.ts +++ b/companion/src/translations/companion_cs.ts @@ -68,17 +68,17 @@ Could not save Application Settings to file "%1" - + Nelze uložit nastavení aplikace do souboru "%1" because the file could not be saved (check access permissions). - + protože soubor nemůže být uložen (zkontrolujte přístupová práva) for unknown reasons. - + z neznámého důvodu. @@ -86,7 +86,7 @@ Show this message again at next startup? - Chcete zobrazit toto upozornění i příště ? + Zobrazit toto upozornění i při příštím spuštění? @@ -356,7 +356,7 @@ Mode 4: Release channel - + Kanál vydání @@ -391,12 +391,12 @@ Mode 4: Append version number to FW file name - Přidat číslo verze do názvu souboru staženého firmwaru + Přidat číslo verze do názvu souboru staženého firmwaru Offer to write FW to Tx after download - Po stažení firmwaru nabídnout okamžité zapsání do rádia + Po stažení firmwaru nabídnout okamžité zapsání do rádia @@ -502,22 +502,22 @@ Mode 4: most recently used files - + naposledny použité soubory Startup Settings - + Nastavení zapnutí Remember - + Zapamatovat Output Logs Folder - + Výstupní složka pro záznamy @@ -537,12 +537,12 @@ Mode 4: Just create the model - Jen vytvořit model + Pouze vytvořit model Debug Output Logging - + Záznam pro režim ladění @@ -552,7 +552,7 @@ Mode 4: Application (Companion/Simulator) - + Použití (Companion/Simulátor) @@ -562,7 +562,7 @@ Mode 4: Radio Firmware (in Simulator) - + Firmware vysílače (v simulátoru) @@ -592,12 +592,12 @@ Mode 4: Screenshot capture folder - + Složka pro snímky obrazovky Joystick - + Joystick @@ -627,7 +627,7 @@ Mode 4: Select your snapshot folder - Vyberat složku pro snímky obrazovky simulátoru + Vybrat složku pro snímky obrazovky simulátoru @@ -669,7 +669,7 @@ Mode 4: Select a folder for application logs - + Vybrat složku pro záznamy aplikace @@ -679,7 +679,7 @@ Mode 4: Select the folder replicating your SD structure - Vyberat složku která představuje obsah SD karty rádia + Vybrat složku, která představuje obsah SD karty rádia @@ -697,30 +697,31 @@ Mode 4: Error reading %1: %2 - + Chyba čtení %1: %2 Cannot save EEPROM - + Nelze uložit do EEPROM Cannot open file %1: %2. - + Nelze otevřít soubor %1: +%2 Error writing file %1: %2. - Chyba při zápisu souboru %1: + Chyba při zápisu souboru %1: %2. Invalid binary EEPROM file %1 - + Neplatný binární EEPROM soubor %1 @@ -728,22 +729,22 @@ Mode 4: Left Horizontal - Levá horizontální + Levá horizontální Left Vertical - Levá vertikální + Levá vertikální Right Vertical - Pravá vertikální + Pravá vertikální Right Horizontal - Pravá horizontální + Pravá horizontální @@ -759,27 +760,27 @@ Mode 4: Unknown - Neznámý + Neznámý Rud - Směrovka + Směrovka Ele - Výškovka + Výškovka Thr - Plyn + Plyn Ail - Křidélka + Křidélka @@ -787,17 +788,17 @@ Mode 4: Negative span - Negativní + Záporný rozsah Mid value - Střed + Střední hodnota Positive span - Pozitivní + Kladný rozsah @@ -805,22 +806,22 @@ Mode 4: Can't extract RADIO/radio.bin - + Nelze rozbalit RADIO/radio.bin Can't extract RADIO/models.txt - + Nelze rozbalit RADIO/models.txt Can't extract %1 - + Nelze rozbalit %1 Error loading models - + Chyba při načítání modelů @@ -833,17 +834,17 @@ Mode 4: Min - + Min Max - + Max Subtrim - + Subtrim @@ -1602,27 +1603,27 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe) Play Track - Hrát stopu + Přehrát stopu Play Both - Přehrát pár + Přehrát oboje Play Value - Přehrát hodnotu + Přehrát hodnotu Play Script - Spustit skript + Spustit skript SD Logs - SD logy + SD záznamy @@ -1632,27 +1633,27 @@ Thomasi Hustererovi (th9x) a také Erazovi Ravivovi(er9x a eePe) Backlight - Podsvětlení + Podsvětlení Screenshot - Snímek LCD + Snímek obrazovky Background Music - Hudba na pozadí + Hudba na pozadí Background Music Pause - Hudba na pozadí -pozastavit + Hudba na pozadí -pozastavit Adjust %1 - + Upravit %1 From 491487c81bfb816577c4bae78db83afc10503162 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 30 Oct 2019 10:15:52 +0100 Subject: [PATCH 232/257] Fix CRSF lua path --- radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua | 2 +- radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua | 2 +- radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua index de0ec06dc..0f9b1a20f 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua @@ -30,7 +30,7 @@ local function run(event) return 2 end - chdir("CROSSFIRE") + chdir("/SCRIPTS/TOOLS/CROSSFIRE") return "crossfire.lua" end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua index 62ca776d7..debf9056d 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua @@ -30,7 +30,7 @@ local function run(event) return 2 end - chdir("CROSSFIRE") + chdir("/SCRIPTS/TOOLS/CROSSFIRE") return "crossfire.lua" end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua index de0ec06dc..0f9b1a20f 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua @@ -30,7 +30,7 @@ local function run(event) return 2 end - chdir("CROSSFIRE") + chdir("/SCRIPTS/TOOLS/CROSSFIRE") return "crossfire.lua" end From aef1bc4f9d4e0585ebdedb17d16711a225f6a5d3 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 3 Nov 2019 09:37:43 +0100 Subject: [PATCH 233/257] Update CREDITS.txt --- CREDITS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 4dc4b7d7c..cfa4c7477 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1621,3 +1621,6 @@ Jacques Loubier Kelly Warner James Cox Sidney B Harden +CG Tech Inc. +Richard Gopstein +Francesco Ziche From 1a4aff22cf1306aee7de2624a4f056a9c1e936f6 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 4 Nov 2019 08:49:27 +0100 Subject: [PATCH 234/257] Delete LICENSE --- LICENSE | 674 -------------------------------------------------------- 1 file changed, 674 deletions(-) delete mode 100644 LICENSE diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - 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. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. From f0e66c07f2b02a8c68d803540241d2a5b86ec7a2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 4 Nov 2019 08:50:13 +0100 Subject: [PATCH 235/257] Create LICENSE (#7043) --- LICENSE | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..d159169d1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. From bad45f7334e593e696bc67b15b7f975abe3bcccd Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 4 Nov 2019 08:53:56 +0100 Subject: [PATCH 236/257] Update CREDITS.txt --- CREDITS.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index cfa4c7477..a4015163a 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1624,3 +1624,6 @@ Sidney B Harden CG Tech Inc. Richard Gopstein Francesco Ziche +Jean Paul Duroch +Romane Oughlissi +Alexander Maciol From 1f7c0979975cbf20966b1ba0086591ec82b41492 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 4 Nov 2019 11:00:50 +0100 Subject: [PATCH 237/257] Review center beep choices (#7044) Review center beep choices --- radio/src/gui/480x272/model_setup.cpp | 4 ++++ 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 +- 10 files changed, 13 insertions(+), 9 deletions(-) diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index 989242b32..752874832 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -964,6 +964,10 @@ bool menuModelSetup(event_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_BEEPCTR); lcdNextPos = MODEL_SETUP_2ND_COLUMN - 3; for (int i=0; i= NUM_STICKS && (!IS_POT_SLIDER_AVAILABLE(i) || IS_POT_MULTIPOS(i))) { + if (attr && menuHorizontalPosition == i) REPEAT_LAST_CURSOR_MOVE(NUM_STICKS+NUM_POTS+NUM_SLIDERS, true); + continue; + } LcdFlags flags = ((menuHorizontalPosition==i && attr) ? INVERS : 0); flags |= (g_model.beepANACenter & ((BeepANACenter)1< Date: Mon, 4 Nov 2019 11:02:30 +0100 Subject: [PATCH 238/257] Improve FlySky telemetry. (#7042) * Improve FlySky telemetry. * Cosmetics --- radio/src/telemetry/flysky_ibus.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/telemetry/flysky_ibus.cpp b/radio/src/telemetry/flysky_ibus.cpp index dbc590f5b..9074daa21 100644 --- a/radio/src/telemetry/flysky_ibus.cpp +++ b/radio/src/telemetry/flysky_ibus.cpp @@ -80,7 +80,7 @@ enum AFHDS2A_ID_S89 = 0x89, AFHDS2A_ID_S8a = 0x8A, - AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX + AFHDS2A_ID_ALT_FLYSKY = 0xF9, // Altitude 2 bytes signed in m - used in FlySky native TX - SIGNED value AFHDS2A_ID_RX_SNR = 0xFA, // SNR AFHDS2A_ID_RX_NOISE = 0xFB, // Noise AFHDS2A_ID_RX_RSSI = 0xFC, // RSSI @@ -156,7 +156,7 @@ static void processFlySkySensor(const uint8_t * packet, uint8_t type) if (id == 0) id = 0x100; // Some part of OpenTX does not like sensor with id and instance 0, remap to 0x100 if (id == AFHDS2A_ID_RX_NOISE || id == AFHDS2A_ID_RX_RSSI) { - value = 135 - value; + value = -value; } else if (id == AFHDS2A_ID_RX_ERR_RATE) { value = 100 - value; @@ -170,7 +170,7 @@ static void processFlySkySensor(const uint8_t * packet, uint8_t type) setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_IBUS, AFHDS2A_ID_ALT, 0, instance, getALT(value), UNIT_METERS, 2); value &= PRESSURE_MASK; } - else if ((id >= AFHDS2A_ID_ACC_X && id <= AFHDS2A_ID_VERTICAL_SPEED) || id == AFHDS2A_ID_CLIMB_RATE) { + else if ((id >= AFHDS2A_ID_ACC_X && id <= AFHDS2A_ID_VERTICAL_SPEED) || id == AFHDS2A_ID_CLIMB_RATE || id == AFHDS2A_ID_ALT_FLYSKY) { value = (int16_t) value; // Signed value } else if (id == AFHDS2A_ID_GPS_STATUS) { From 64a1d80c6327cdeddee35e0f4013176f3a82a933 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 4 Nov 2019 11:11:10 +0100 Subject: [PATCH 239/257] Rework 128 timer to better leverage tiny space (#7022) Rework 128 timer to better leverage tiny space --- radio/src/gui/128x64/view_main.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index 5cf5e059e..d7c24a555 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -180,11 +180,31 @@ void displayTrims(uint8_t phase) void drawTimerWithMode(coord_t x, coord_t y, uint8_t index) { const TimerData & timer = g_model.timers[index]; + if (timer.mode) { const TimerState & timerState = timersStates[index]; const uint8_t negative = (timerState.val<0 ? BLINK | INVERS : 0); - LcdFlags att = RIGHT | DBLSIZE | negative; - drawTimer(x, y, timerState.val, att, att); + LcdFlags att = RIGHT | DBLSIZE; + if (timerState.val < 60 * 60) { // display MM:SS + div_t qr = div(abs(timerState.val), 60); + lcdDrawNumber(x - 5, y, qr.rem, att | LEADING0 | negative, 2); + lcdDrawText(lcdLastLeftPos, y, ":", att|BLINK | negative); + lcdDrawNumber(lcdLastLeftPos, y, qr.quot, att | negative); + if (negative) + lcdDrawText(lcdLastLeftPos, y, "-", att | negative); + } + else if (timerState.val < (99 * 60 * 60) + (59 * 60) { // display HHhMM + div_t qr = div(abs(timerState.val) / 60, 60); + lcdDrawNumber(x - 5, y, qr.rem, att | LEADING0, 2); + lcdDrawText(lcdLastLeftPos, y, "h", att); + lcdDrawNumber(lcdLastLeftPos, y, qr.quot, att); + if (negative) + lcdDrawText(lcdLastLeftPos, y, "-", att); + } + else { //display HHHH for crazy large persistent timers + lcdDrawText(x - 5, y, "h", att); + lcdDrawNumber(lcdLastLeftPos, y, timerState.val / 3600, att); + } uint8_t xLabel = (negative ? x-56 : x-49); uint8_t len = zlen(timer.name, LEN_TIMER_NAME); if (len > 0) { From 53579157d8379f7dc7adc372129cb61871bfbb0f Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 4 Nov 2019 11:11:41 +0100 Subject: [PATCH 240/257] Add support for BT compilation on T16 (#7020) --- companion/src/firmwares/opentx/opentxinterface.cpp | 1 + radio/src/targets/horus/CMakeLists.txt | 1 + radio/util/fwoptions.py | 1 + 3 files changed, 3 insertions(+) diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index e1902f73e..3b4413a3c 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -1302,6 +1302,7 @@ void registerOpenTxFirmwares() firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+"), BOARD_JUMPER_T16); addOpenTxFrskyOptions(firmware); firmware->addOption("internalmulti", Firmware::tr("Support for MULTI internal module")); + firmware->addOption("bluetooth", Firmware::tr("Support for bluetooth module")); registerOpenTxFirmware(firmware); /* 9XR-Pro */ diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 1673dff08..cacff84fe 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -52,6 +52,7 @@ if (PCB STREQUAL X10) set(LUA_EXPORT lua_export_t16) add_definitions(-DRADIO_T16) option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" OFF) + option(BLUETOOTH "Support for bluetooth module" OFF) else() set(FLAVOUR x10) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) diff --git a/radio/util/fwoptions.py b/radio/util/fwoptions.py index 035cd7f2a..104452561 100755 --- a/radio/util/fwoptions.py +++ b/radio/util/fwoptions.py @@ -210,4 +210,5 @@ options_jumper_t16 = { "eu": ("MODULE_PROTOCOL_D8", "NO", "YES"), "flexr9m": ("MODULE_PROTOCOL_FLEX", "YES", None), "internalmulti": ("INTERNAL_MODULE_MULTI", "YES", "NO"), + "bluetooth": ("BLUETOOTH", "YES", "NO"), } \ No newline at end of file From 77ef237f0aa47388f9e582d0ac564b540d1261e9 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 4 Nov 2019 11:12:57 +0100 Subject: [PATCH 241/257] Only change R9M chancount when exceeds max allowed (#7021) This fixes #6983 --- radio/src/gui/128x64/model_setup.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 00cc5d85b..f0e8f9bce 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -1499,7 +1499,7 @@ void menuModelSetup(event_t event) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9M_FCC_POWER_VALUES, module.pxx.power, LEFT | attr); if (attr) { CHECK_INCDEC_MODELVAR_ZERO(event, module.pxx.power, R9M_FCC_POWER_MAX); - if (s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != module.pxx.power) { + if (s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != module.pxx.power && module.channelsCount > maxModuleChannels_M8(moduleIdx)) { module.channelsStart = 0; module.channelsCount = maxModuleChannels_M8(moduleIdx); } @@ -1516,7 +1516,8 @@ void menuModelSetup(event_t event) CHECK_INCDEC_MODELVAR_ZERO(event, module.pxx.power, R9M_LITE_LBT_POWER_MAX); if (s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != module.pxx.power) { module.channelsStart = 0; - module.channelsCount = maxModuleChannels_M8(moduleIdx); + if (module.channelsCount > maxModuleChannels_M8(moduleIdx)) + module.channelsCount = maxModuleChannels_M8(moduleIdx); if (reusableBuffer.moduleSetup.r9mPower + module.pxx.power < 5) { // switching between mode 2 and 3 does not require rebind POPUP_WARNING(STR_REBIND); } @@ -1532,7 +1533,8 @@ void menuModelSetup(event_t event) CHECK_INCDEC_MODELVAR_ZERO(event, module.pxx.power, R9M_LBT_POWER_MAX); if (s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != module.pxx.power) { module.channelsStart = 0; - module.channelsCount = maxModuleChannels_M8(moduleIdx); + if (module.channelsCount > maxModuleChannels_M8(moduleIdx)) + module.channelsCount = maxModuleChannels_M8(moduleIdx); if (reusableBuffer.moduleSetup.r9mPower + module.pxx.power < 5) { //switching between mode 2 and 3 does not require rebind POPUP_WARNING(STR_REBIND); } From c553cb25cb72f1c908e5bc9fe0e12601eccd8d06 Mon Sep 17 00:00:00 2001 From: Stefan Hezinger <47187139+SHezinger@users.noreply.github.com> Date: Mon, 4 Nov 2019 11:14:43 +0100 Subject: [PATCH 242/257] German translations (#7018) * Wizard pages reviewed and missing translations added * Changed to SI Units * telemetry.ui updated * customizesplashdialog updated * warnings.h updated * downloaddialog updated * expodialog.cpp updated * generalsetup.cpp updated * mainwindow.cpp updated * modeldata.cpp updated * radionotfound.ui updated * sdcard.cpp updated * helpers_html.cpp translated * Tried to distinguish between the physical "Trimmer" and the value "Trimmung" * Minor changes * Curve menu updated * Typo in flightmodes.cpp fixed * Update in customfunctions.cpp * translations for appdata.cpp added * hardware.ui updated * mixerdialog.ui translation added * creditsdialog.cpp updated * customfunctiondata.cpp translations added * fwpreferencesdialog updated * process_flash.cpp translation added * process_flash.cpp translation added * modeldata.cpp changed * printdialog.ui updated * rawsource.cpp translations added * sensordata.cpp translation added * setup.ui updated * wizarddialog.cpp updated --- companion/src/translations/companion_de.ts | 113 ++++++++++++--------- 1 file changed, 64 insertions(+), 49 deletions(-) diff --git a/companion/src/translations/companion_de.ts b/companion/src/translations/companion_de.ts index 855bfab42..6915d258f 100644 --- a/companion/src/translations/companion_de.ts +++ b/companion/src/translations/companion_de.ts @@ -63,22 +63,26 @@ Application Settings have been saved to %1 - + Die Anwendungseinstellungen wurden unter +%1 +gespeichert Could not save Application Settings to file "%1" - + Die Anwendungseinstellungen konnten nicht unter +%1 +gespeichert werden because the file could not be saved (check access permissions). - + , da auf die Datei nicht zugegriffen werden konnte (Überprüfen Sie die Zugriffsrechte). for unknown reasons. - + . Der Grund hierfür ist unbekannt. @@ -1279,7 +1283,7 @@ If you have a settings backup file, you may import that instead. OpenTX Blacklist - + OpenTX Blacklist @@ -1392,7 +1396,7 @@ If you have a settings backup file, you may import that instead. Curve type - Kurven Typ + Kurventyp @@ -1407,7 +1411,7 @@ If you have a settings backup file, you may import that instead. Point size - + Punktgröße @@ -1437,7 +1441,7 @@ If you have a settings backup file, you may import that instead. Side - Seite + Bereich @@ -1452,7 +1456,7 @@ If you have a settings backup file, you may import that instead. Curve name - Kurven Name + Kurvenname @@ -1462,7 +1466,7 @@ If you have a settings backup file, you may import that instead. Popup menu available - Menü verfügbar + Popoup-Menü verfügbar @@ -1502,22 +1506,22 @@ If you have a settings backup file, you may import that instead. Clear - Löschen + Zurücksetzen Clear all curves - Lösche alle Kurven + Alle Kurven zurücksetzen Are you sure you want to reset curve %1? - Die Kurve %1 wirklich löschen? + Die Kurve %1 wirklich zurücksetzen? Are you sure you want to reset all curves? - Wirklich alle Kurven löschen? + Wirklich alle Kurven zurücksetzen? @@ -1527,7 +1531,7 @@ If you have a settings backup file, you may import that instead. Not enough free points in EEPROM to store the curve. - Nicht genug freie Stützstellen im EEPROM um die Kurve zu speichern. + Es sind nicht genügend freie Stützstellen im EEPROM vorhanden, um diese Kurve zu abzuspeichern. @@ -1655,37 +1659,37 @@ If you have a settings backup file, you may import that instead. Adjust %1 - + Verstelle %1 SetFailsafe Int. Module - + SetFailsafe Int. Modul SetFailsafe Ext. Module - + SetFailsafe Ext. Modul RangeCheck Int. Module - + RangeCheck Int. Modul RangeCheck Ext. Module - + RangeCheck Ext. Modul Bind Int. Module - + Binden Int. Modul Bind Ext. Module - + Binden Ext. Modul @@ -1737,7 +1741,7 @@ If you have a settings backup file, you may import that instead. <font color=red><b>Inconsistent parameter</b></font> - + <font color=red><b>Widersprüchliche Parameter</b></font> @@ -1762,7 +1766,7 @@ If you have a settings backup file, you may import that instead. CFN - + CFN @@ -1790,7 +1794,7 @@ If you have a settings backup file, you may import that instead. Popup menu available - Menü verfügbar + Popup-Menü verfügbar @@ -1810,13 +1814,13 @@ If you have a settings backup file, you may import that instead. Error occurred while trying to play sound, possibly the file is already opened. (Err: %1 [%2]) - + Beim Abspielen der Audio-Datei kam es zu einem Fehler, möglicherweise ist sie bereits geöffnet. (Err: %1 [%2]) Unable to find or open sound file: %1 - + Diese Audio-Datei %1 konnte nicht gefunden bzw. geöffnet werden: @@ -3089,7 +3093,7 @@ Blank means include all. ?, *, and [...] wildcards accepted. Unknown - Unbekannt + Unbekannt @@ -3417,7 +3421,7 @@ Blank means include all. ?, *, and [...] wildcards accepted. Executable %1 not found - + Die ausführbare Datei %1 wurde nicht gefunden @@ -3477,13 +3481,14 @@ Bitte dazu eine passende Firmware zum Programmieren auswählen. You are currently using: %1 - Sie verwenden gerade: + +Sie verwenden gerade: %1 Your radio does not seem connected to USB or the driver is not initialized!!!. - + Der Sender scheint entweder nicht per USB angeschlossen zu sein, oder der entsprechende Treiber wurde nicht installiert. @@ -3587,7 +3592,7 @@ You are currently using: Use Trim from Flight mode %1 + Own Trim as an offset - Trimmung von Flugphase %1 + Eigenen Trimmung als Offset + Trimmung von Flugphase %1 + Eigene Trimmung als Offset @@ -5096,12 +5101,12 @@ Sind Sie sicher? Antenna - Antenne + Antenne S5 - S5 + S5 @@ -7400,7 +7405,17 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Delay is not zero the actuation of the mix will be delayed by the specified amount of seconds.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Slow is not zero then the speed of the mix will be set by the value specified -&gt; the value states the number of seconds it takes to transit from -100 to 100.</p></body></html> - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; text-decoration: underline;">Verzögerung und Verlangsamung</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600; text-decoration: underline;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Diese Werte beeinflussen die Verzögerung und die Geschwindigkeit des Ausgangs des Mixers</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wenn die Verzögerung nicht 0 ist, wird die Ausführung um diesen Wert in Sekunden verzögert.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Wenn die Verlangsamung nicht 0 ist, wird der Ausgang des Mixers um den gegebenen Wert verlangsamt -&gt; Der Wert stellt die Zeit in Sekunden dar, die der Ausgangswert des Mischers benötigt, um sich von -100 auf 100 zu ändern.</p></body></html> @@ -7665,12 +7680,12 @@ If blank then the mix is considered to be "ON" all the time. Model: - Modell: + Modell: Throttle Source - Gas-Timer Quelle + Gas-Quelle @@ -9526,7 +9541,7 @@ If blank then the mix is considered to be "ON" all the time. Style - + Style @@ -9969,12 +9984,12 @@ r Trm5 - + Trm5 Trm6 - + Trm6 @@ -9984,7 +9999,7 @@ r TrmV - + TrmV @@ -10596,7 +10611,7 @@ r °F - + °F @@ -10616,7 +10631,7 @@ r mW - + mW @@ -10641,7 +10656,7 @@ r Rad - + rad @@ -10666,12 +10681,12 @@ r Internal - Interne + Interne External - + Externe @@ -10782,7 +10797,7 @@ ebenfalls umgekehrt. Throttle Source - GasTimer Quelle + Gas-Timer-Quelle @@ -10842,7 +10857,7 @@ ebenfalls umgekehrt. Throttle Warning - Gas Warnung + Gas-Warnung @@ -13840,7 +13855,7 @@ CTRL + scroll or PAGE UP/DOWN keys to change time in larger steps. Plane - Flugmodell + Flächenmodell From bd08b398aa506ce5c6e36c27596980aba0f30f1d Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 4 Nov 2019 16:43:32 +0100 Subject: [PATCH 243/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index a4015163a..d8e04b6b6 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1627,3 +1627,4 @@ Francesco Ziche Jean Paul Duroch Romane Oughlissi Alexander Maciol +Udo Kastenholz From fe78cfc90f2346b872c1e68d3e30c0099eee78ea Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 5 Nov 2019 14:17:25 +0100 Subject: [PATCH 244/257] Compile fix --- radio/src/gui/128x64/view_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index d7c24a555..74d649a3a 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -193,7 +193,7 @@ void drawTimerWithMode(coord_t x, coord_t y, uint8_t index) if (negative) lcdDrawText(lcdLastLeftPos, y, "-", att | negative); } - else if (timerState.val < (99 * 60 * 60) + (59 * 60) { // display HHhMM + else if (timerState.val < (99 * 60 * 60) + (59 * 60)) { // display HHhMM div_t qr = div(abs(timerState.val) / 60, 60); lcdDrawNumber(x - 5, y, qr.rem, att | LEADING0, 2); lcdDrawText(lcdLastLeftPos, y, "h", att); From 0750568deaaf5e63d98a87d2e478cc0fd0f8609c Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Tue, 5 Nov 2019 20:45:26 +0100 Subject: [PATCH 245/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index d8e04b6b6..044389a5c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1628,3 +1628,4 @@ Jean Paul Duroch Romane Oughlissi Alexander Maciol Udo Kastenholz +Jacek Wielogórski From b86658acfbec753c0f48c5fb54c07174c39d99ce Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 6 Nov 2019 10:23:02 +0100 Subject: [PATCH 246/257] Update CREDITS.txt --- CREDITS.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.txt b/CREDITS.txt index 044389a5c..0d9844b77 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1629,3 +1629,5 @@ Romane Oughlissi Alexander Maciol Udo Kastenholz Jacek Wielogórski +Siegfried Preißler +Bernard Mohamedaly From 0cce9097eaf6e810c2d5945d2847c0ae33d70a0d Mon Sep 17 00:00:00 2001 From: WismyYao Date: Wed, 6 Nov 2019 23:23:21 +0800 Subject: [PATCH 247/257] Wismy/x10(s) upgrade kit (#7049) Add a popup for auth-failure --- radio/src/pulses/pxx2.h | 2 ++ radio/src/telemetry/frsky_pxx2.cpp | 5 +++++ radio/src/translations.cpp | 2 ++ radio/src/translations.h | 2 ++ radio/src/translations/cz.h.txt | 1 + radio/src/translations/de.h.txt | 2 ++ 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 + 15 files changed, 23 insertions(+) diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h index 23eae9934..6e3274278 100644 --- a/radio/src/pulses/pxx2.h +++ b/radio/src/pulses/pxx2.h @@ -65,6 +65,8 @@ #define SPECTRUM_ANALYSER_POWER_FLOOR -120 /*dBm*/ #endif +#define PXX2_AUTH_REFUSED_FLAG 0xA5 + enum PXX2ModuleModelID { PXX2_MODULE_NONE, PXX2_MODULE_XJT, diff --git a/radio/src/telemetry/frsky_pxx2.cpp b/radio/src/telemetry/frsky_pxx2.cpp index 582e098a4..bff29c315 100644 --- a/radio/src/telemetry/frsky_pxx2.cpp +++ b/radio/src/telemetry/frsky_pxx2.cpp @@ -227,6 +227,11 @@ void processAuthenticationFrame(uint8_t module, uint8_t * frame) uint8_t cryptoType = frame[3]; uint8_t messageDigest[16] = {0}; + if (frame[0] == 4 && PXX2_AUTH_REFUSED_FLAG == frame[4]) { + POPUP_INFORMATION(STR_AUTH_FAILURE); + return; + } + if (INTERNAL_MODULE == module && accessCRL(cryptoType, frame+4, messageDigest)) { moduleState[module].mode = MODULE_MODE_AUTHENTICATION; Pxx2Pulses & pxx2 = intmodulePulsesData.pxx2; diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 9f7f8247e..8dcd039c1 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -770,3 +770,5 @@ const char STR_ABOUT_PARENTS_1[] = TR_ABOUT_PARENTS_1; const char STR_ABOUT_PARENTS_2[] = TR_ABOUT_PARENTS_2; const char STR_ABOUT_PARENTS_3[] = TR_ABOUT_PARENTS_3; const char STR_ABOUT_PARENTS_4[] = TR_ABOUT_PARENTS_4; + +const char STR_AUTH_FAILURE[] = TR_AUTH_FAILURE; diff --git a/radio/src/translations.h b/radio/src/translations.h index 038c4eea1..b0abe876f 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -910,6 +910,8 @@ extern const char STR_ABOUT_PARENTS_2[]; extern const char STR_ABOUT_PARENTS_3[]; extern const char STR_ABOUT_PARENTS_4[]; +extern const char STR_AUTH_FAILURE[]; + #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 2f0f094f6..556fb876c 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -1152,6 +1152,7 @@ #define TR_MENU_INVERT "Invertovat" #define TR_JITTER_FILTER "ADC Filtr" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index d59842fe6..eca2ec9ec 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -1157,6 +1157,8 @@ #define TR_MENU_INVERT "Invertieren" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" + // ---------------------------------------------------------------- #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 0b52f513f..c02d67a91 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -1156,6 +1156,7 @@ #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 07b1d66da..c9afe0d62 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -1177,6 +1177,7 @@ #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 6a80bbb14..92e7d99d2 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -1165,6 +1165,7 @@ #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 48bdf8114..97f095b43 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -1180,6 +1180,7 @@ #define TR_MENU_INVERT "Inverser" #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 ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index a0e9cdd93..101c81c74 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -1174,6 +1174,7 @@ #define TR_MENU_INVERT "Inverti" #define TR_JITTER_FILTER "Filtro ADC" #define TR_RTC_CHECK TR("Controllo RTC", "Controllo voltaggio RTC") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index a4ecfb51e..32d79b6c7 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -1166,6 +1166,7 @@ #define TR_MENU_INVERT "Inverteer" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 66e88737f..ec6e0b655 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -1173,6 +1173,7 @@ #define TR_MENU_INVERT "Odwróć" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 669c4c4c4..4bfcf0b89 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -1162,6 +1162,7 @@ #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #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 7164ba97c..a05e6902e 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -1173,6 +1173,7 @@ #define TR_MENU_INVERT "Invertera" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_RSSI "RSSI" #define ZSTR_R9PW "R9PW" From e473a7e89780f1ed7d11737468f4cb8efb11331a Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 6 Nov 2019 17:49:15 +0100 Subject: [PATCH 248/257] x9d 2019 simu (#7054) Introduce X9D 2019 simu --- companion/src/companion.qrc | 8 + .../src/images/simulator/X9D2019/Readme.md | 28 +++ .../X9D2019/X9DP2019_Companion_image.png | Bin 0 -> 52775 bytes .../src/images/simulator/X9D2019/bottom.png | Bin 0 -> 10440 bytes .../simulator/X9D2019/bottom_scrnshot.png | Bin 0 -> 10745 bytes .../images/simulator/X9D2019/center_LCD.png | Bin 0 -> 557 bytes .../src/images/simulator/X9D2019/left.png | Bin 0 -> 15843 bytes .../images/simulator/X9D2019/left_exit.png | Bin 0 -> 17815 bytes .../images/simulator/X9D2019/left_menu.png | Bin 0 -> 18013 bytes .../images/simulator/X9D2019/left_page.png | Bin 0 -> 18035 bytes .../src/images/simulator/X9D2019/right.png | Bin 0 -> 13735 bytes .../images/simulator/X9D2019/right_enter.png | Bin 0 -> 15596 bytes .../src/images/simulator/X9D2019/top.png | Bin 0 -> 8162 bytes companion/src/simulation/CMakeLists.txt | 2 + companion/src/simulation/simulateduiwidget.h | 13 ++ .../simulation/simulateduiwidgetX9D2019.cpp | 83 +++++++++ .../simulation/simulateduiwidgetX9D2019.ui | 166 ++++++++++++++++++ companion/src/simulation/simulatorwidget.cpp | 4 +- 18 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 companion/src/images/simulator/X9D2019/Readme.md create mode 100644 companion/src/images/simulator/X9D2019/X9DP2019_Companion_image.png create mode 100644 companion/src/images/simulator/X9D2019/bottom.png create mode 100644 companion/src/images/simulator/X9D2019/bottom_scrnshot.png create mode 100644 companion/src/images/simulator/X9D2019/center_LCD.png create mode 100644 companion/src/images/simulator/X9D2019/left.png create mode 100644 companion/src/images/simulator/X9D2019/left_exit.png create mode 100644 companion/src/images/simulator/X9D2019/left_menu.png create mode 100644 companion/src/images/simulator/X9D2019/left_page.png create mode 100644 companion/src/images/simulator/X9D2019/right.png create mode 100644 companion/src/images/simulator/X9D2019/right_enter.png create mode 100644 companion/src/images/simulator/X9D2019/top.png create mode 100644 companion/src/simulation/simulateduiwidgetX9D2019.cpp create mode 100644 companion/src/simulation/simulateduiwidgetX9D2019.ui diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index 567b52637..32ace6a12 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -136,6 +136,14 @@ images/simulator/X9E/right.png images/simulator/X9E/right_enter.png images/simulator/X9E/top.png + images/simulator/X9D2019/bottom.png + images/simulator/X9D2019/left.png + images/simulator/X9D2019/left_exit.png + images/simulator/X9D2019/left_menu.png + images/simulator/X9D2019/left_page.png + images/simulator/X9D2019/right.png + images/simulator/X9D2019/right_enter.png + images/simulator/X9D2019/top.png images/simulator/X9LITE/bottom.png images/simulator/X9LITE/left.png images/simulator/X9LITE/left_exit.png diff --git a/companion/src/images/simulator/X9D2019/Readme.md b/companion/src/images/simulator/X9D2019/Readme.md new file mode 100644 index 000000000..75a11a3ad --- /dev/null +++ b/companion/src/images/simulator/X9D2019/Readme.md @@ -0,0 +1,28 @@ + +# "Taranis X9D+ 2019" dark blue skin for the Companion simulator +![X9D+ 2019 Image for Companion](X9DP2019_Companion_image.png "Taranis X9D+ 2019") + +## The different parts of the image + +The image is divided into 4 pieces: top, bottom, left and right. +For the images concerned, there is the version with the activated element and the version without the activated element (such as a button, a rotary encoder, clicking on the rotary encoder). + +| File name | What is this image ? | +|:---------------------|:----------------------------------------------| +| `bottom.png` | central lower band | +| `center_LCD.png` | central LCD 424x128px (useless for simulator) | +| `left.png` | left part with inactive elements | +| `left_exit.png` | left part with the EXIT button activated | +| `left_menu.png` | left part with the MENU button activated | +| `left_page.png` | left part with the PAGE button activated | +| `bottom_scrnshot.png`| central lower band with the SCREENSHOT button activated| +| `right_ent.png` | right part with the ENTER button activated | +| `right.png` | right part with inactive elements | +| `top.png` | central upper band | + +`X9DP2019_Companion_image.png` is the image displayed here. + + +## Software used : +- **Inkscape** : vector drawing software (http://www.inkscape.org/) +- **Gimp** : image editor (http://www.gimp.org/) \ No newline at end of file diff --git a/companion/src/images/simulator/X9D2019/X9DP2019_Companion_image.png b/companion/src/images/simulator/X9D2019/X9DP2019_Companion_image.png new file mode 100644 index 0000000000000000000000000000000000000000..9f28d54a853660a1d2933fe0bc366ca889b235cd GIT binary patch literal 52775 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

*h9sdEW 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 literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9D2019/bottom_scrnshot.png b/companion/src/images/simulator/X9D2019/bottom_scrnshot.png new file mode 100644 index 0000000000000000000000000000000000000000..b46eaa9ec4525c2181483a0e46a6638adfee8115 GIT binary patch literal 10745 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 literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9D2019/left.png b/companion/src/images/simulator/X9D2019/left.png new file mode 100644 index 0000000000000000000000000000000000000000..113cd16118942ad6c54ccdba18e09caef42e40d3 GIT binary patch literal 15843 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 LR*|ZeFbn-3P9jlT literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9D2019/left_exit.png b/companion/src/images/simulator/X9D2019/left_exit.png new file mode 100644 index 0000000000000000000000000000000000000000..4b6376c0fdd6dc9ee29fc49401825ef67501b3fe GIT binary patch literal 17815 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 z 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 P00000NkvXXu0mjfl9lcY literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9D2019/left_menu.png b/companion/src/images/simulator/X9D2019/left_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..9e2a74ecc8e21630c338bb0711dfb6efa5087895 GIT binary patch literal 18013 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 RLMs3O002ovPDHLkV1ix)cj*8C literal 0 HcmV?d00001 diff --git a/companion/src/images/simulator/X9D2019/right_enter.png b/companion/src/images/simulator/X9D2019/right_enter.png new file mode 100644 index 0000000000000000000000000000000000000000..8f9c5f1cb6c742c597434da26a4c397a257bc6e1 GIT binary patch literal 15596 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 + + // add actions in order of appearance on the help menu + + QPoint ctr(70, 100); + + act = new RadioUiAction(0, QList() << Qt::Key_Up << Qt::Key_PageUp, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU); + addRadioWidget(ui->leftbuttons->addArea(QRect(25, 40, 80, 35), "X9D2019/left_menu.png", act)); + + act = new RadioUiAction(3, QList() << Qt::Key_Down << Qt::Key_PageDown, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE); + addRadioWidget(ui->leftbuttons->addArea(QRect(25, 85, 80, 35), "X9D2019/left_page.png", act)); + + act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT); + addRadioWidget(ui->leftbuttons->addArea(QRect(25, 140, 80, 35), "X9D2019/left_exit.png", act)); + + m_scrollUpAction = addRadioAction(new RadioUiAction(-1, QList() << Qt::Key_Minus << Qt::Key_Left, SIMU_STR_HLP_KEYS_GO_LFT, SIMU_STR_HLP_ACT_ROT_LFT)); + m_scrollDnAction = addRadioAction(new RadioUiAction(-1, QList() << Qt::Key_Plus << Qt::Key_Equal << Qt::Key_Right, SIMU_STR_HLP_KEYS_GO_RGT, SIMU_STR_HLP_ACT_ROT_RGT)); + connectScrollActions(); + + m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(40, 30, 80, 130), "X9D2019/right_enter.png", m_mouseMidClickAction)); + + addRadioWidget(ui->leftbuttons->addArea(QRect(10, 170, 30, 30), "X9D2019/left_scrnshot.png", m_screenshotAction)); + + m_backlightColors << QColor(47, 123, 227); // Taranis Blue + m_backlightColors << QColor(166,247,159); + m_backlightColors << QColor(247,159,166); + m_backlightColors << QColor(255,195,151); + m_backlightColors << QColor(247,242,159); + + setLcd(ui->lcd); + + QString css = "#radioUiWidget {" + "background-color: qlineargradient(spread:pad, x1:1, y1:0.9, x2:0, y2:0," + "stop:0 rgba(255, 255, 255, 255)," + "stop:0.35 rgba(250, 250, 250, 255), stop:0.5 rgba(242, 241, 241, 255)," + "stop:0.61 rgba(241, 241, 241, 255), stop:1.0 rgba(251, 251, 251, 255));" + "}"; + + QTimer * tim = new QTimer(this); + tim->setSingleShot(true); + connect(tim, &QTimer::timeout, [this, css]() { + emit customStyleRequest(css); + }); + tim->start(100); +} + +SimulatedUIWidgetX9D2019::~SimulatedUIWidgetX9D2019() +{ + delete ui; +} + diff --git a/companion/src/simulation/simulateduiwidgetX9D2019.ui b/companion/src/simulation/simulateduiwidgetX9D2019.ui new file mode 100644 index 000000000..4333f50ca --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetX9D2019.ui @@ -0,0 +1,166 @@ + + + SimulatedUIWidgetX9D2019 + + + + 0 + 0 + 756 + 258 + + + + + 0 + 0 + + + + + 756 + 258 + + + + + 756 + 258 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 166 + 258 + + + + true + + + background:url(:/images/simulator/X9D2019/left.png); + + + + + + + + 0 + 0 + + + + + 424 + 50 + + + + background:url(:/images/simulator/X9D2019/top.png) + + + + + + + + 0 + 0 + + + + + 166 + 258 + + + + background:url(:/images/simulator/X9D2019/right.png) + + + + + + + + 0 + 0 + + + + + 424 + 128 + + + + + 424 + 128 + + + + + + + + + 0 + 0 + + + + + 424 + 80 + + + + background:url(:/images/simulator/X9D2019/bottom.png) + + + + + + + + LcdWidget + QWidget +

lcdwidget.h
+ 1 + + + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+ + + + diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index f823769aa..c96cd480e 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -68,9 +68,11 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato break; case Board::BOARD_TARANIS_X9D: case Board::BOARD_TARANIS_X9DP: - case Board::BOARD_TARANIS_X9DP_2019: radioUiWidget = new SimulatedUIWidgetX9(simulator, this); break; + case Board::BOARD_TARANIS_X9DP_2019: + radioUiWidget = new SimulatedUIWidgetX9D2019(simulator, this); + break; case Board::BOARD_TARANIS_XLITE: case Board::BOARD_TARANIS_XLITES: radioUiWidget = new SimulatedUIWidgetXLITE(simulator, this); From 82470f3ca0a2c146caec833fe4e4a145f4f7aa92 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 6 Nov 2019 17:51:20 +0100 Subject: [PATCH 249/257] Fix stamps handling (#7055) --- radio/src/stamp.cpp | 18 +++++++++++++----- radio/src/stamp.h.in | 6 ------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/radio/src/stamp.cpp b/radio/src/stamp.cpp index 85d5106a2..842020a8c 100644 --- a/radio/src/stamp.cpp +++ b/radio/src/stamp.cpp @@ -32,15 +32,23 @@ #define TAB "\037\033" #endif +#if defined(FRSKY_RELEASE) +#define DISPLAY_VERSION "FrSky" +#elif defined(JUMPER_RELEASE) +#define DISPLAY_VERSION "JumperRC" +#else +#define DISPLAY_VERSION VERSION +#endif + #if defined(COLORLCD) - const char vers_stamp[] = "VERS" TAB ": " "opentx-" FLAVOUR "-" VERSION " (" GIT_STR ")"; + const char vers_stamp[] = "VERS" TAB ": " "opentx-" FLAVOUR "-" DISPLAY_VERSION " (" GIT_STR ")"; const char date_stamp[] = "DATE" TAB ": " DATE; const char time_stamp[] = "TIME" TAB ": " TIME; const char eeprom_stamp[] = "EEPR" TAB ": " EEPROM_STR; #elif defined(BOARD_NAME) - const char vers_stamp[] = "FW" TAB ": opentx-" BOARD_NAME "\036VERS" TAB ": " VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR; + const char vers_stamp[] = "FW" TAB ": opentx-" BOARD_NAME "\036VERS" TAB ": " DISPLAY_VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR; #else - const char vers_stamp[] = "FW" TAB ": opentx-" FLAVOUR "\036VERS" TAB ": " VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR; + const char vers_stamp[] = "FW" TAB ": opentx-" FLAVOUR "\036VERS" TAB ": " DISPLAY_VERSION " (" GIT_STR ")" "\036DATE" TAB ": " DATE " " TIME "\036EEPR" TAB ": " EEPROM_STR; #endif /** @@ -49,8 +57,8 @@ */ #if defined(STM32) && !defined(SIMU) -__SECTION_USED(".fwversiondata") const char firmware_version[] = "opentx-" FLAVOUR "-" VERSION " (" GIT_STR ")"; -__SECTION_USED(".bootversiondata") const char boot_version[] = "opentx-" FLAVOUR "-" VERSION " (" GIT_STR ")"; +__SECTION_USED(".fwversiondata") const char firmware_version[] = "opentx-" FLAVOUR "-" DISPLAY_VERSION " (" GIT_STR ")"; +__SECTION_USED(".bootversiondata") const char boot_version[] = "opentx-" FLAVOUR "-" DISPLAY_VERSION " (" GIT_STR ")"; /** * Tries to find opentx version in the first 1024 byte of either firmware/bootloader (the one not running) or the buffer diff --git a/radio/src/stamp.h.in b/radio/src/stamp.h.in index a8dd9884e..f360b3a90 100644 --- a/radio/src/stamp.h.in +++ b/radio/src/stamp.h.in @@ -1,12 +1,6 @@ #define DATE "@DATE@" #define TIME "@TIME@" -#if defined(FRSKY_RELEASE) -#define VERSION "FrSky" -#elif defined(JUMPER_RELEASE) -#define VERSION "JumperRC" -#else #define VERSION "@VERSION@" -#endif #define VERSION_MAJOR @VERSION_MAJOR@ #define VERSION_MINOR @VERSION_MINOR@ From ea7345255ba468f62e38e496a0529593d5e590be Mon Sep 17 00:00:00 2001 From: Marco Robustini Date: Wed, 6 Nov 2019 17:52:15 +0100 Subject: [PATCH 250/257] IT: graphic alignments (#7053) 1) Correct bad graphic alignments detected on X12S 2) Other fix --- radio/src/translations/it.h.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 101c81c74..7f6feb27e 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -88,7 +88,7 @@ #define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europa\0") #define LEN_USBMODES TR("\006", "\010") -#define TR_USBMODES TR("Chiedi\0 ""Joyst\0""Storage""Seriale", "Chiedi\0 ""Joystick""Storage\0""Seriale\0 ") +#define TR_USBMODES TR("Chied\0""Joyst\0""SDCard""Serial", "Chiedi\0 ""Joystick""Storage\0""Seriale\0 ") #define LEN_JACKMODES "\007" #define TR_JACKMODES "Chiedi\0 ""Audio\0 ""Trainer" @@ -459,7 +459,7 @@ #define TR_PROTO TR(INDENT "Protoc.", INDENT "Protocollo") #define TR_PPMFRAME INDENT "Frame PPM" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") -#define STR_WARN_BATTVOLTAGE TR(INDENT "Uscita è VBAT: ", INDENT "Att.: livel. uscita è VBAT: ") +#define STR_WARN_BATTVOLTAGE TR(INDENT "Uscita VBAT: ", INDENT "Att.: livel. uscita VBAT: ") #define TR_MS "ms" #define TR_FREQUENCY INDENT "Frequenza" #define TR_SWITCH "Inter." @@ -529,7 +529,7 @@ #define TR_MEMORYWARNING TR(INDENT "Avv. Mem.", INDENT "Avviso Memoria") #define TR_ALARMWARNING INDENT "Spegni suono" #define TR_RSSISHUTDOWNALARM TR(INDENT "RSSI Shut.", INDENT "Control. RSSI al Shutdown") -#define TR_MODEL_STILL_POWERED "Modello ancora acceso" +#define TR_MODEL_STILL_POWERED "Ricevente ancora connessa" #define TR_MODEL_SHUTDOWN "Shutdown?" #define TR_PRESS_ENTER_TO_CONFIRM "Premi [ENT] per confermare" #define TR_THROTTLE_LABEL "Motore" @@ -689,7 +689,7 @@ #define TR_CURRENT_CALIB "Calibra corr." #define TR_VOLTAGE TR(INDENT "Voltagg.",INDENT "Voltaggio") #define TR_CURRENT TR(INDENT "Corrente",INDENT "Corrente") -#define TR_SELECT_MODEL "Scegli Memo." +#define TR_SELECT_MODEL TR("Scegli mod.", "Scegli Modello") #define TR_CREATE_CATEGORY "Crea Categoria" #define TR_RENAME_CATEGORY "Rinomina Categoria" #define TR_DELETE_CATEGORY "Cancella Categoria" @@ -940,17 +940,17 @@ #define TR_UNIT "Unita" #define TR_TELEMETRY_NEWSENSOR INDENT "Aggiungi nuovo sensore" #define TR_CHANNELRANGE INDENT "Numero Canali" -#define TR_ANTENNACONFIRM1 "EXT. ANTENNA" +#define TR_ANTENNACONFIRM1 "ANTENNA EST." #if defined(PCBX12S) #define LEN_ANTENNA_MODES "\023" -#define TR_ANTENNA_MODES "Interna\0 ""Chiedi\0 ""Per modello\0 ""Interna + esterna" +#define TR_ANTENNA_MODES "Interna\0 ""Chiedi\0 ""Per modello\0 ""Interna + esterna" #else #define LEN_ANTENNA_MODES "\011" -#define TR_ANTENNA_MODES "Interna\0""Chiedi\0 ""Per modello""Esterna" +#define TR_ANTENNA_MODES "Interna\0 ""Chiedi\0 ""Per model""Esterna" #endif #define TR_USE_INTERNAL_ANTENNA TR("Usa ant. int.", "Usa antenna interna") #define TR_USE_EXTERNAL_ANTENNA TR("Usa ant. est.", "Usa antenna esterna") -#define TR_ANTENNACONFIRM2 TR("Controlla antenna", "Controlla se l'antenna è installata!") +#define TR_ANTENNACONFIRM2 TR("Controlla instal.", "Controlla prima se installata!") #define TR_MODULE_PROTOCOL_FLEX_WARN_LINE1 "Non richiede" #define TR_MODULE_PROTOCOL_FCC_WARN_LINE1 "Richiede FCC" #define TR_MODULE_PROTOCOL_EU_WARN_LINE1 "Richiede EU" From c99e3d4b8d471796d0233e7e533a4bd3b65ca8f2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 08:40:00 +0100 Subject: [PATCH 251/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 0d9844b77..385b03bf6 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1631,3 +1631,4 @@ Udo Kastenholz Jacek Wielogórski Siegfried Preißler Bernard Mohamedaly +John North From fecbfc74a1dfd0abbf1d988d972759c808c1988f Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 09:27:39 +0100 Subject: [PATCH 252/257] There is a PMU chip on X10 Exprress. SD Manager dynamic menu updated. --- radio/src/gui/480x272/radio_sdmanager.cpp | 7 +++++++ radio/src/targets/horus/CMakeLists.txt | 1 + 2 files changed, 8 insertions(+) diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp index e375a1a21..a4a66e519 100644 --- a/radio/src/gui/480x272/radio_sdmanager.cpp +++ b/radio/src/gui/480x272/radio_sdmanager.cpp @@ -180,6 +180,13 @@ void onSdManagerMenu(const char * result) bluetooth.flashFirmware(lfn); } #endif +#if defined(HARDWARE_POWER_MANAGEMENT_UNIT) + else if (result == STR_FLASH_POWER_MANAGEMENT_UNIT) { + getSelectionFullPath(lfn); + FrskyChipFirmwareUpdate device; + device.flashFirmware(lfn); + } +#endif #if defined(MULTIMODULE) #if defined(INTERNAL_MODULE_MULTI) else if (result == STR_FLASH_INTERNAL_MULTI) { diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index cacff84fe..2a9af5ed1 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -47,6 +47,7 @@ if (PCB STREQUAL X10) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) set(BLUETOOTH ON) + add_definitions(-DHARDWARE_POWER_MANAGEMENT_UNIT) elseif (PCBREV STREQUAL T16) set(FLAVOUR t16) set(LUA_EXPORT lua_export_t16) From 5c495be5ce6e7f3735beb6e7d06ff6d85b1e9dd4 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 10:08:29 +0100 Subject: [PATCH 253/257] Update CREDITS.txt --- CREDITS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CREDITS.txt b/CREDITS.txt index 385b03bf6..62e673034 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1632,3 +1632,4 @@ Jacek Wielogórski Siegfried Preißler Bernard Mohamedaly John North +Thomas Wormsley From d0579f26a67647417ab7503aefd854e8ce08d55b Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 11:58:38 +0100 Subject: [PATCH 254/257] Cosmetics --- radio/src/lua/api_general.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 14cc82187..514f0cc2f 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -488,13 +488,7 @@ static int luaSportTelemetryPush(lua_State * L) outputTelemetryBuffer.pushSportPacketWithBytestuffing(packet); #if defined(PXX2) uint8_t destination = (IS_INTERNAL_MODULE_ON() ? INTERNAL_MODULE : EXTERNAL_MODULE); - - if (isModulePXX2(destination)) { - outputTelemetryBuffer.setDestination(destination << 2); - } - else { - outputTelemetryBuffer.setDestination(TELEMETRY_ENDPOINT_SPORT); - } + outputTelemetryBuffer.setDestination(isModulePXX2(destination) ? (destination << 2) : TELEMETRY_ENDPOINT_SPORT); #else outputTelemetryBuffer.setDestination(TELEMETRY_ENDPOINT_SPORT); #endif From 9b05060a1a398302cfd093f343963ba6f512fff2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 12:22:35 +0100 Subject: [PATCH 255/257] Fixes #7036 --- radio/src/gui/128x64/model_input_edit.cpp | 2 +- radio/src/gui/212x64/model_input_edit.cpp | 2 +- radio/src/gui/480x272/model_inputs.cpp | 2 +- radio/src/gui/common/stdlcd/draw_functions.cpp | 2 +- radio/src/gui/gui_common.cpp | 9 ++------- radio/src/gui/gui_common.h | 2 +- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/radio/src/gui/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp index c2e27f738..29889e0ca 100644 --- a/radio/src/gui/128x64/model_input_edit.cpp +++ b/radio/src/gui/128x64/model_input_edit.cpp @@ -102,7 +102,7 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr); - if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); + if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); break; case EXPO_FIELD_SCALE: diff --git a/radio/src/gui/212x64/model_input_edit.cpp b/radio/src/gui/212x64/model_input_edit.cpp index 715393cc4..64b7b81db 100644 --- a/radio/src/gui/212x64/model_input_edit.cpp +++ b/radio/src/gui/212x64/model_input_edit.cpp @@ -109,7 +109,7 @@ void menuModelExpoOne(event_t event) case EXPO_FIELD_SOURCE: lcdDrawTextAlignedLeft(y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr); - if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); + if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); break; case EXPO_FIELD_SCALE: diff --git a/radio/src/gui/480x272/model_inputs.cpp b/radio/src/gui/480x272/model_inputs.cpp index 00ea22caa..c6a868df6 100644 --- a/radio/src/gui/480x272/model_inputs.cpp +++ b/radio/src/gui/480x272/model_inputs.cpp @@ -241,7 +241,7 @@ bool menuModelExpoOne(event_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SOURCE); drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, menuHorizontalPosition==0 ? attr : 0); if (attr && menuHorizontalPosition==0) - ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); + ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailableInInputs); if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { drawSensorCustomValue(EXPO_ONE_2ND_COLUMN+75, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|(menuHorizontalPosition==1?attr:0)); if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); diff --git a/radio/src/gui/common/stdlcd/draw_functions.cpp b/radio/src/gui/common/stdlcd/draw_functions.cpp index 06eb7137a..3608abc62 100644 --- a/radio/src/gui/common/stdlcd/draw_functions.cpp +++ b/radio/src/gui/common/stdlcd/draw_functions.cpp @@ -25,7 +25,7 @@ void drawStringWithIndex(coord_t x, coord_t y, const char * str, uint8_t idx, Lc { if (flags & RIGHT) { lcdDrawNumber(x, y, idx, flags); - lcdDrawText(x-FWNUM, y, str, flags & ~LEADING0); + lcdDrawText(lcdNextPos, y, str, flags & ~LEADING0); } else { lcdDrawText(x, y, str, flags & ~LEADING0); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index daee811e6..9b95c68dc 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -240,22 +240,17 @@ bool isSourceAvailableInCustomSwitches(int source) return result; } -bool isInputSourceAvailable(int source) +bool isSourceAvailableInInputs(int source) { if (source >= MIXSRC_FIRST_POT && source <= MIXSRC_LAST_POT) return IS_POT_SLIDER_AVAILABLE(POT1+source - MIXSRC_FIRST_POT); -#if defined(GYRO) - if (source >= MIXSRC_GYRO1 && source <= MIXSRC_GYRO2) - return true; -#endif - #if defined(PCBX10) if (source >= MIXSRC_MOUSE1 && source <= MIXSRC_MOUSE2) return false; #endif - if (source >= MIXSRC_Rud && source < MIXSRC_MAX) + if (source >= MIXSRC_Rud && source <= MIXSRC_MAX) return true; if (source >= MIXSRC_FIRST_TRIM && source <= MIXSRC_LAST_TRIM) diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 43dc8df80..d846f0567 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -60,7 +60,7 @@ int getFirstAvailable(int min, int max, IsValueAvailable isValueAvailable); bool isTrimModeAvailable(int mode); bool isInputAvailable(int input); -bool isInputSourceAvailable(int source); +bool isSourceAvailableInInputs(int source); bool isThrottleSourceAvailable(int source); bool isLogicalSwitchFunctionAvailable(int function); bool isLogicalSwitchAvailable(int index); From 3f0ce109ad96630097c9fbbc6d17100c9ebda117 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 13:39:38 +0100 Subject: [PATCH 256/257] Fixes #7027 --- radio/src/gui/212x64/menus.h | 2 +- radio/src/gui/gui_common.cpp | 3 +++ radio/src/myeeprom.h | 2 +- radio/src/telemetry/multi.cpp | 5 ++--- radio/src/trainer.cpp | 11 +++++------ 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/radio/src/gui/212x64/menus.h b/radio/src/gui/212x64/menus.h index cbbd43fd1..24da83e0f 100644 --- a/radio/src/gui/212x64/menus.h +++ b/radio/src/gui/212x64/menus.h @@ -54,7 +54,7 @@ void menuTraceBuffer(event_t event); enum MenuRadioIndexes { MENU_RADIO_SETUP, MENU_RADIO_SD_MANAGER, -#if defined(LUA) || defined(PXX2) +#if defined(LUA) || defined(PXX2) || defined(MULTIMODULE) MENU_RADIO_TOOLS, #endif MENU_RADIO_SPECIAL_FUNCTIONS, diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 9b95c68dc..497bd5880 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -727,6 +727,9 @@ bool isTrainerModeAvailable(int mode) #if defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT) if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) return false; +#elif defined(PCBTARANIS) + if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) + return g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER; #endif #if defined(PCBX9E) diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index dcd7e20d9..952e94770 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -38,7 +38,7 @@ #define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.auxSerialMode==UART_MODE_SBUS_TRAINER) #elif defined(PCBTARANIS) #define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerData.mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerData.mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE) - #define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.auxSerialMode==UART_MODE_SBUS_TRAINER) + #define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) #else #define IS_TRAINER_EXTERNAL_MODULE() false #endif diff --git a/radio/src/telemetry/multi.cpp b/radio/src/telemetry/multi.cpp index ec6bdef8d..c07a98494 100644 --- a/radio/src/telemetry/multi.cpp +++ b/radio/src/telemetry/multi.cpp @@ -257,9 +257,8 @@ static void processMultiRxChannels(const uint8_t * data, uint8_t len) uint8_t bitsavailable = 0; uint8_t byteIdx = 4; - while(ch < maxCh) { - - while((bitsavailable < MULTI_CHAN_BITS) && byteIdx < len) { + while (ch < maxCh) { + while (bitsavailable < MULTI_CHAN_BITS && byteIdx < len) { bits |= (uint32_t)(data[byteIdx++]) << (uint32_t)bitsavailable; bitsavailable += 8; } diff --git a/radio/src/trainer.cpp b/radio/src/trainer.cpp index 7761645ba..0af1901b7 100644 --- a/radio/src/trainer.cpp +++ b/radio/src/trainer.cpp @@ -115,15 +115,14 @@ void checkTrainerSettings() #if defined(TRAINER_BATTERY_COMPARTMENT) case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: - if (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) { + if (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) auxSerialSbusInit(); - break; - } - // no break + else + init_trainer_capture(); + break; #endif - default: - // master is default + case TRAINER_MODE_MASTER_TRAINER_JACK: init_trainer_capture(); break; } From 50a07dc8d82c9323cb056864e7c9df55ae92cdff Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Thu, 7 Nov 2019 13:58:56 +0100 Subject: [PATCH 257/257] Cosmetics --- radio/src/audio.cpp | 2 +- radio/src/targets/common/arm/stm32/audio_dac_driver.cpp | 3 +-- radio/src/targets/horus/audio_spi_driver.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index 2737592cb..c8417568d 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -755,7 +755,7 @@ void AudioQueue::wakeup() DEBUG_TIMER_STOP(debugTimerAudioConsume); AudioBuffer * buffer; - while ((buffer = buffersFifo.getEmptyBuffer()) != 0) { + while ((buffer = buffersFifo.getEmptyBuffer()) != nullptr) { int result; unsigned int fade = 0; int size = 0; diff --git a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp index 2962731b7..d050382a2 100644 --- a/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp +++ b/radio/src/targets/common/arm/stm32/audio_dac_driver.cpp @@ -90,8 +90,7 @@ void dacInit() void audioConsumeCurrentBuffer() { - if (nextBuffer == 0) { - + if (!nextBuffer) { nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer(); if (nextBuffer) { #if defined(AUDIO_MUTE_GPIO_PIN) diff --git a/radio/src/targets/horus/audio_spi_driver.cpp b/radio/src/targets/horus/audio_spi_driver.cpp index dc05ef06d..32ef0f906 100644 --- a/radio/src/targets/horus/audio_spi_driver.cpp +++ b/radio/src/targets/horus/audio_spi_driver.cpp @@ -374,7 +374,7 @@ void audioInit() audioHardReset(); audioSoftReset(); audioSpiSetSpeed(SPI_SPEED_8); - delay_01us(10000); // 1ms + delay_ms(1); // 1ms audioSendRiffHeader(); }