From 499092b479bb760a5c5523fe1b697241534ced82 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sun, 22 Dec 2013 18:17:24 +0100 Subject: [PATCH 01/43] Fixes #155 --- src/targets/sky9x/adc_driver.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/targets/sky9x/adc_driver.cpp b/src/targets/sky9x/adc_driver.cpp index 1d09ef988..e3adf33a3 100644 --- a/src/targets/sky9x/adc_driver.cpp +++ b/src/targets/sky9x/adc_driver.cpp @@ -45,12 +45,12 @@ const char ana_direction[NUMBER_ANALOG] = {1, 1, 0, 1 ,0 ,1 ,0, 0, 0}; // Settings for mode register ADC_MR // USEQ off - silicon problem, doesn't work -// TRANSFER = 1 -// TRACKTIM = 4 (5 clock periods) -// ANACH = 0 -// SETTLING = 1 (not used if ANACH = 0) -// STARTUP = 1 (8 clock periods) -// PRESCAL = 3.6 MHz clock (between 1 and 20MHz) +// TRANSFER = 3 +// TRACKTIM = 15 (16 clock periods) +// ANACH = 1 +// SETTLING = 6 (not used if ANACH = 0) +// STARTUP = 6 (96 clock periods) +// PRESCAL = 9.0 MHz clock (between 1 and 20MHz) // FREERUN = 0 // FWUP = 0 // SLEEP = 0 @@ -66,7 +66,7 @@ void adcInit() // Enable peripheral clock ADC = bit 29 PMC->PMC_PCER0 |= 0x20000000L ; // Enable peripheral clock to ADC padc = ADC ; - padc->ADC_MR = 0x14110000 | timer ; // 0001 0100 0001 0001 xxxx xxxx 0000 0000 + padc->ADC_MR = 0x3FB60000 | timer ; // 0011 1111 1011 0110 xxxx xxxx 0000 0000 padc->ADC_ACR = ADC_ACR_TSON ; // Turn on temp sensor #if defined(REVA) padc->ADC_CHER = 0x0000E23E ; // channels 1,2,3,4,5,9,13,14,15 From 0f242f556569ada998da490300711740ae6e23b2 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 23 Dec 2013 10:42:57 +0100 Subject: [PATCH 02/43] [Taranis] No more audio freeze! --- src/audio_arm.cpp | 3 ++- src/targets/taranis/audio_driver.cpp | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/audio_arm.cpp b/src/audio_arm.cpp index 8b6bf9b44..428e75856 100644 --- a/src/audio_arm.cpp +++ b/src/audio_arm.cpp @@ -325,8 +325,9 @@ void AudioQueue::pushBuffer(AudioBuffer *buffer) { buffer->state = AUDIO_BUFFER_FILLED; - if (dacQueue(buffer)) + if (dacQueue(buffer)) { buffer->state = AUDIO_BUFFER_PLAYING; + } bufferWIdx = nextBufferIdx(bufferWIdx); } diff --git a/src/targets/taranis/audio_driver.cpp b/src/targets/taranis/audio_driver.cpp index d0b0508aa..5dc714fd5 100644 --- a/src/targets/taranis/audio_driver.cpp +++ b/src/targets/taranis/audio_driver.cpp @@ -95,8 +95,10 @@ void dacInit() bool dacQueue(AudioBuffer *buffer) { + __disable_irq(); if (dacIdle) { dacIdle = false; + __enable_irq(); DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits DMA1_Stream5->M0AR = CONVERT_PTR(buffer->data); @@ -107,6 +109,7 @@ bool dacQueue(AudioBuffer *buffer) return true; } else { + __enable_irq(); return false; } } From 132aa15ab6a86d0b750edc675e41c34dd2333b67 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 23 Dec 2013 15:18:00 +0100 Subject: [PATCH 03/43] [Taranis] Best fix for the audio freeze by Mike, thanks! --- src/audio_arm.cpp | 6 +++++- src/targets/taranis/audio_driver.cpp | 3 --- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/audio_arm.cpp b/src/audio_arm.cpp index 428e75856..c3d311514 100644 --- a/src/audio_arm.cpp +++ b/src/audio_arm.cpp @@ -325,11 +325,15 @@ void AudioQueue::pushBuffer(AudioBuffer *buffer) { buffer->state = AUDIO_BUFFER_FILLED; + __disable_irq(); + + bufferWIdx = nextBufferIdx(bufferWIdx); + if (dacQueue(buffer)) { buffer->state = AUDIO_BUFFER_PLAYING; } - bufferWIdx = nextBufferIdx(bufferWIdx); + __enable_irq(); } void mix(uint16_t * result, int sample, unsigned int fade) diff --git a/src/targets/taranis/audio_driver.cpp b/src/targets/taranis/audio_driver.cpp index 5dc714fd5..d0b0508aa 100644 --- a/src/targets/taranis/audio_driver.cpp +++ b/src/targets/taranis/audio_driver.cpp @@ -95,10 +95,8 @@ void dacInit() bool dacQueue(AudioBuffer *buffer) { - __disable_irq(); if (dacIdle) { dacIdle = false; - __enable_irq(); DMA1_Stream5->CR &= ~DMA_SxCR_EN ; // Disable DMA channel DMA1->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5 | DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5 ; // Write ones to clear bits DMA1_Stream5->M0AR = CONVERT_PTR(buffer->data); @@ -109,7 +107,6 @@ bool dacQueue(AudioBuffer *buffer) return true; } else { - __enable_irq(); return false; } } From b185cc7fd89983a2a52babe7566e809475d1c81a Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 27 Dec 2013 10:33:45 +0100 Subject: [PATCH 04/43] Fix for #197 (non audio chunks > 256 bytes) --- src/audio_arm.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/audio_arm.cpp b/src/audio_arm.cpp index c3d311514..8864bdf4e 100644 --- a/src/audio_arm.cpp +++ b/src/audio_arm.cpp @@ -373,10 +373,13 @@ int AudioQueue::mixWav(AudioContext &context, AudioBuffer *buffer, int volume, u result = FR_DENIED; } while (result == FR_OK && memcmp(wavSamplesPtr, "data", 4) != 0) { - result = (size < 256 ? f_read(&context.state.wav.file, wavBuffer, size+8, &read) : FR_DENIED); - if (read != size+8) result = FR_DENIED; - wavSamplesPtr = (uint32_t *)(wavBuffer + size); - size = wavSamplesPtr[1]; + result = f_lseek(&context.state.wav.file, f_tell(&context.state.wav.file)+size); + if (result == FR_OK) { + result = f_read(&context.state.wav.file, wavBuffer, 8, &read); + if (read != 8) result = FR_DENIED; + wavSamplesPtr = (uint32_t *)wavBuffer; + size = wavSamplesPtr[1]; + } } context.state.wav.size = size; } From c1778246016c5e07226f076a1a6115279e2bfdd8 Mon Sep 17 00:00:00 2001 From: Andre Bernet Date: Sat, 4 Jan 2014 18:21:08 +0100 Subject: [PATCH 05/43] Reinstate A2 alarms in D16 mode for the 3rd party adapter --- src/telemetry/frsky_sport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/telemetry/frsky_sport.cpp b/src/telemetry/frsky_sport.cpp index 5ea7a2846..4b8c68a5f 100644 --- a/src/telemetry/frsky_sport.cpp +++ b/src/telemetry/frsky_sport.cpp @@ -576,11 +576,11 @@ void telemetryWakeup() } } else if (alarmsCheckStep == 2) { - if (alarmRaised(1, 1) && g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_D8) { + if (alarmRaised(1, 1)) { AUDIO_A2_RED(); alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3seconds */ } - else if (alarmRaised(1, 0) && g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_D8) { + else if (alarmRaised(1, 0)) { AUDIO_A2_ORANGE(); alarmsCheckTime = get_tmr10ms() + 300; /* next check in 3seconds */ } From 4ffe49ef01fc2db191e5dfca1a6c15ac30b898d9 Mon Sep 17 00:00:00 2001 From: Andre Bernet Date: Sat, 4 Jan 2014 20:41:19 +0100 Subject: [PATCH 06/43] A2 was also disabled in custom switches in D16 mode --- src/opentx.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/opentx.cpp b/src/opentx.cpp index 6f02ebd2f..574da915f 100644 --- a/src/opentx.cpp +++ b/src/opentx.cpp @@ -1013,11 +1013,6 @@ bool getSwitch(int8_t swtch) if (cs->v1 >= MIXSRC_FIRST_TELEM) { if ((!TELEMETRY_STREAMING() && cs->v1 >= MIXSRC_FIRST_TELEM+TELEM_FIRST_STREAMED_VALUE-1) || IS_FAI_FORBIDDEN(cs->v1-1)) return swtch > 0 ? false : true; - -#if defined (PCBTARANIS) - if (cs->v1 == MIXSRC_FIRST_TELEM+TELEM_A2-1 && g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_X16) - return swtch > 0 ? false : true; -#endif y = convertCswTelemValue(cs); From 300d6af0860fa366b54fafe908200a35a03f5b87 Mon Sep 17 00:00:00 2001 From: Andre Bernet Date: Sat, 4 Jan 2014 18:11:33 +0100 Subject: [PATCH 07/43] Avoid Telemetry Lost / Telemetry Recovered voice alerts playing back to back when using the Reset Telemetry / Flight functions --- src/telemetry/frsky_sport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/telemetry/frsky_sport.cpp b/src/telemetry/frsky_sport.cpp index 4b8c68a5f..c5ef5c309 100644 --- a/src/telemetry/frsky_sport.cpp +++ b/src/telemetry/frsky_sport.cpp @@ -639,6 +639,7 @@ void FrskyValueWithMinMax::set(uint8_t value) void resetTelemetry() { memclear(&frskyData, sizeof(frskyData)); + telemetryState = TELEMETRY_INIT; #if defined(FRSKY_HUB) frskyData.hub.gpsLatitude_bp = 2; From 1edd98f50175fd4627c4fe7231d94cf7dfe4ddc5 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 19:42:48 -0500 Subject: [PATCH 08/43] Update README.txt --- README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 8f6415cbd..345e6aef7 100644 --- a/README.txt +++ b/README.txt @@ -1 +1 @@ -[to be written] +Test From 01c2413a0c833dd3a75f80f7a95686a9baf50667 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 17:10:04 -0800 Subject: [PATCH 09/43] Added RPM calculation based on Spur and Pinion Gear --- radio/src/gui/menu_model.cpp | 25 +- radio/src/gui/menu_model.cpp~ | 5643 ++++++++++++++++++++++++++++++++ radio/src/myeeprom.h | 8 +- radio/src/myeeprom.h~ | 1469 +++++++++ radio/src/simu.cpp | 8 + radio/src/simu.cpp~ | 425 +++ radio/src/telemetry/frsky.cpp | 10 +- radio/src/telemetry/frsky.cpp~ | 926 ++++++ radio/src/translations.cpp | 2 + radio/src/translations.cpp~ | 672 ++++ radio/src/translations.h | 2 + radio/src/translations.h~ | 754 +++++ radio/src/translations/en.h | 2 + radio/src/translations/en.h~ | 765 +++++ 14 files changed, 10705 insertions(+), 6 deletions(-) create mode 100644 radio/src/gui/menu_model.cpp~ create mode 100644 radio/src/myeeprom.h~ create mode 100644 radio/src/simu.cpp~ create mode 100644 radio/src/telemetry/frsky.cpp~ create mode 100644 radio/src/translations.cpp~ create mode 100644 radio/src/translations.h~ create mode 100644 radio/src/translations/en.h~ diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index d1f9889fb..681aaa22f 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -5164,6 +5164,8 @@ enum menuModelTelemetryItems { ITEM_TELEMETRY_USR_PROTO, #endif ITEM_TELEMETRY_USR_BLADES, + ITEM_TELEMETRY_USR_SPUR_GEAR, // T.Foley + ITEM_TELEMETRY_USR_PINION_GEAR, // T.Foley #endif ITEM_TELEMETRY_USR_VOLTAGE_SOURCE, ITEM_TELEMETRY_USR_CURRENT_SOURCE, @@ -5200,7 +5202,8 @@ enum menuModelTelemetryItems { }; #if defined(PCBTARANIS) - #define USRDATA_LINES (uint8_t)-1, 0, + //#define USRDATA_LINES (uint8_t)-1, 0, + #define USRDATA_LINES (uint8_t)-1, 0, 0, 0, // T.Foley - Add room for two new gearing options #elif defined(FRSKY_HUB) || defined(WS_HOW_HIGH) #define USRDATA_LINES (uint8_t)-1, 0, 0, #else @@ -5403,8 +5406,24 @@ void menuModelTelemetry(uint8_t event) case ITEM_TELEMETRY_USR_BLADES: lcd_putsLeft(y, STR_BLADES); - lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 3); + //lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); + lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.blades, LEFT|attr); // T.Foley + //if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 3); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 254); // T.Foley + break; + + case ITEM_TELEMETRY_USR_SPUR_GEAR: // T.Foley + lcd_putsLeft(y, STR_SPURGEAR); + lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.spur_gear, LEFT|attr); + // Spur gear must be greater than or equal to pinion to prevent floating point error + if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.spur_gear, g_model.frsky.pinion_gear, 254); + break; + + case ITEM_TELEMETRY_USR_PINION_GEAR: // T.Foley + lcd_putsLeft(y, STR_PINIONGEAR); + lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.pinion_gear, LEFT|attr); + // Pinion gear ,ust be less than or equal to spur gear to prevent floating point error + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.pinion_gear, g_model.frsky.spur_gear); break; #endif diff --git a/radio/src/gui/menu_model.cpp~ b/radio/src/gui/menu_model.cpp~ new file mode 100644 index 000000000..d1f9889fb --- /dev/null +++ b/radio/src/gui/menu_model.cpp~ @@ -0,0 +1,5643 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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" +#ifdef MAVLINK +#include "gui/view_mavlink.h" +#endif + +#define WCHART 32 +#define X0 (LCD_W-WCHART-2) +#define Y0 32 + +enum EnumTabModel { + e_ModelSelect, + e_ModelSetup, + IF_HELI(e_Heli) + IF_FLIGHT_MODES(e_FlightModesAll) + e_InputsAll, + e_MixAll, + e_Limits, + IF_CURVES(e_CurvesAll) +#if LCD_W >= 212 + IF_GVARS(e_GVars) +#endif + e_CustomSwitches, + e_CustomFunctions, +#if defined(LUA_MODEL_SCRIPTS) + e_CustomScripts, +#endif + IF_FRSKY(e_Telemetry) + IF_MAVLINK(e_MavSetup) + IF_TEMPLATES(e_Templates) +}; + +void menuModelSelect(uint8_t event); +void menuModelSetup(uint8_t event); +void menuModelHeli(uint8_t event); +void menuModelFlightModesAll(uint8_t event); +void menuModelExposAll(uint8_t event); +void menuModelMixAll(uint8_t event); +void menuModelLimits(uint8_t event); +void menuModelCurvesAll(uint8_t event); +void menuModelGVars(uint8_t event); +void menuModelCustomSwitches(uint8_t event); +void menuModelCustomFunctions(uint8_t event); +void menuModelCustomScripts(uint8_t event); +void menuModelTelemetry(uint8_t event); +void menuModelTemplates(uint8_t event); +void menuModelExpoOne(uint8_t event); + +const MenuFuncP_PROGMEM menuTabModel[] PROGMEM = { + menuModelSelect, + menuModelSetup, + IF_HELI(menuModelHeli) + IF_FLIGHT_MODES(menuModelFlightModesAll) + menuModelExposAll, + menuModelMixAll, + menuModelLimits, + IF_CURVES(menuModelCurvesAll) +#if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) + IF_GVARS(menuModelGVars) +#endif + menuModelCustomSwitches, + menuModelCustomFunctions, +#if defined(LUA_MODEL_SCRIPTS) + menuModelCustomScripts, +#endif + IF_FRSKY(menuModelTelemetry) + IF_MAVLINK(menuTelemetryMavlinkSetup) + IF_TEMPLATES(menuModelTemplates) +}; + +#define COPY_MODE 1 +#define MOVE_MODE 2 +static uint8_t s_copyMode = 0; +static int8_t s_copySrcRow; +static int8_t s_copyTgtOfs; + +uint8_t eeFindEmptyModel(uint8_t id, bool down) +{ + uint8_t i = id; + for (;;) { + i = (MAX_MODELS + (down ? i+1 : i-1)) % MAX_MODELS; + if (!eeModelExists(i)) break; + if (i == id) return 0xff; // no free space in directory left + } + return i; +} + +void selectModel(uint8_t sub) +{ + displayPopup(STR_LOADINGMODEL); + saveTimers(); + eeCheck(true); // force writing of current model data before this is changed + g_eeGeneral.currModel = sub; + eeDirty(EE_GENERAL); + eeLoadModel(sub); +} + +#if defined(SDCARD) +#define LIST_NONE_SD_FILE 1 +bool listSdFiles(const char *path, const char *extension, const uint8_t maxlen, const char *selection, uint8_t flags=0) +{ + FILINFO fno; + DIR dir; + char *fn; /* This function is assuming non-Unicode cfg. */ +#if _USE_LFN + TCHAR lfn[_MAX_LFN + 1]; + fno.lfname = lfn; + fno.lfsize = sizeof(lfn); +#endif + + static uint16_t s_last_menu_offset = 0; + +#if defined(CPUARM) + static uint8_t s_last_flags; + + if (selection) { + s_last_flags = flags; + memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); + strcpy(reusableBuffer.modelsel.menu_bss[0], path); + strcat(reusableBuffer.modelsel.menu_bss[0], "/"); + strncat(reusableBuffer.modelsel.menu_bss[0], selection, maxlen); + strcat(reusableBuffer.modelsel.menu_bss[0], extension); + if (f_stat(reusableBuffer.modelsel.menu_bss[0], &fno) != FR_OK) { + selection = NULL; + } + } + else { + flags = s_last_flags; + } +#endif + + if (s_menu_offset == 0) { + s_last_menu_offset = 0; + memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); + } + else if (s_menu_offset == s_menu_count - MENU_MAX_LINES) { + s_last_menu_offset = 0xffff; + memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); + } + else if (s_menu_offset == s_last_menu_offset) { + // should not happen, only there because of Murphy's law + return true; + } + else if (s_menu_offset > s_last_menu_offset) { + memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], (MENU_MAX_LINES-1)*MENU_LINE_LENGTH); + memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], 0xff, MENU_LINE_LENGTH); + } + else { + memmove(reusableBuffer.modelsel.menu_bss[1], reusableBuffer.modelsel.menu_bss[0], (MENU_MAX_LINES-1)*MENU_LINE_LENGTH); + memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH); + } + + s_menu_count = 0; + s_menu_flags = BSS; + + FRESULT res = f_opendir(&dir, path); /* Open the directory */ + if (res == FR_OK) { + + if (flags & LIST_NONE_SD_FILE) { + s_menu_count++; + if (selection) { + s_last_menu_offset++; + } + else if (s_menu_offset==0 || s_menu_offset < s_last_menu_offset) { + char *line = reusableBuffer.modelsel.menu_bss[0]; + memset(line, 0, MENU_LINE_LENGTH); + strcpy(line, "---"); + s_menu[0] = line; + } + } + + for (;;) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + +#if _USE_LFN + fn = *fno.lfname ? fno.lfname : fno.fname; +#else + fn = fno.fname; +#endif + + uint8_t len = strlen(fn); + if (len < 5 || len > maxlen+4 || strcasecmp(fn+len-4, extension) || (fno.fattrib & AM_DIR)) continue; + + s_menu_count++; + fn[len-4] = '\0'; + + if (s_menu_offset == 0) { + if (selection && strncasecmp(fn, selection, maxlen) < 0) { + s_last_menu_offset++; + } + else { + for (uint8_t i=0; i=0; i--) { + char *line = reusableBuffer.modelsel.menu_bss[i]; + if (line[0] == '\0' || strcasecmp(fn, line) > 0) { + if (i > 0) memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], sizeof(reusableBuffer.modelsel.menu_bss[i]) * i); + memset(line, 0, MENU_LINE_LENGTH); + strcpy(line, fn); + break; + } + } + for (uint8_t i=0; i s_last_menu_offset) { + if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-2]) > 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1]) < 0) { + memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], 0, MENU_LINE_LENGTH); + strcpy(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], fn); + } + } + else { + if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[1]) < 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[0]) > 0) { + memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH); + strcpy(reusableBuffer.modelsel.menu_bss[0], fn); + } + } + } + } + + if (s_menu_offset > 0) + s_last_menu_offset = s_menu_offset; + else + s_menu_offset = s_last_menu_offset; + + return s_menu_count; +} +#endif + +#if defined(PCBTARANIS) + static int8_t modelselBitmapIdx; + static uint8_t modelselBitmap[MODEL_BITMAP_SIZE]; + #define MODELSEL_W 133 + #define BMP_DIRTY() modelselBitmapIdx = -1 +#else + #define MODELSEL_W LCD_W + #define BMP_DIRTY() +#endif + +#if defined(NAVIGATION_MENUS) +void onModelSelectMenu(const char *result) +{ + int8_t sub = m_posVert; + + if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) { + selectModel(sub); + } + else if (result == STR_COPY_MODEL) { + s_copyMode = COPY_MODE; + s_copyTgtOfs = 0; + s_copySrcRow = -1; + } + else if (result == STR_MOVE_MODEL) { + s_copyMode = MOVE_MODE; + s_copyTgtOfs = 0; + s_copySrcRow = -1; + } +#if defined(SDCARD) + else if (result == STR_BACKUP_MODEL) { + eeCheck(true); // force writing of current model data before this is changed + POPUP_WARNING(eeBackupModel(sub)); + } + else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) { + if (!listSdFiles(MODELS_PATH, MODELS_EXT, sizeof(g_model.header.name), NULL)) { + POPUP_WARNING(STR_NO_MODELS_ON_SD); + s_menu_flags = 0; + } + } +#endif + else if (result == STR_DELETE_MODEL) { + POPUP_CONFIRMATION(STR_DELETEMODEL); +#if defined(CPUARM) + s_warning_info = modelHeaders[sub].name; +#else + char * name = reusableBuffer.modelsel.mainname; + eeLoadModelName(sub, name); + s_warning_info = name; +#endif + s_warning_info_len = sizeof(g_model.header.name); + } +#if defined(SDCARD) + else { + // The user choosed a file on SD to restore + POPUP_WARNING(eeRestoreModel(sub, (char *)result)); + BMP_DIRTY(); + if (!s_warning && g_eeGeneral.currModel == sub) + eeLoadModel(sub); + } +#endif +} +#endif + +void menuModelSelect(uint8_t event) +{ + if (s_warning_result) { + s_warning_result = 0; + eeDeleteModel(m_posVert); // delete file + s_copyMode = 0; + event = EVT_ENTRY_UP; + BMP_DIRTY(); + } + + uint8_t _event_ = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event); + +#if defined(PCBTARANIS) + if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) + _event_ -= KEY_EXIT; +#else + if (s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) + _event_ -= KEY_EXIT; +#endif + + int8_t oldSub = m_posVert; + + if (!check_submenu_simple(_event_, MAX_MODELS-1)) return; + +#if defined(NAVIGATION_POT2) + if (event==0 && p2valdiff<0) { + event = EVT_KEY_FIRST(KEY_RIGHT); + } +#endif + + if (s_editMode > 0) s_editMode = 0; + +#if !defined(CPUARM) + if (event) { + eeFlush(); // flush eeprom write + } +#endif + + int8_t sub = m_posVert; + + switch (event) + { + case EVT_ENTRY: + m_posVert = sub = g_eeGeneral.currModel; + if (sub >= LCD_LINES-1) s_pgOfs = sub-LCD_LINES+2; + s_copyMode = 0; + s_editMode = EDIT_MODE_INIT; + BMP_DIRTY(); + eeCheck(true); + break; + case EVT_KEY_LONG(KEY_EXIT): + if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) { + POPUP_CONFIRMATION(STR_DELETEMODEL); +#if defined(CPUARM) + s_warning_info = modelHeaders[sub].name; +#else + char * name = reusableBuffer.modelsel.mainname; + eeLoadModelName(sub, name); + s_warning_info = name; +#endif + s_warning_info_len = sizeof(g_model.header.name); + killEvents(event); + break; + } + // no break +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LONG: + killEvents(event); + if (s_editMode < 0) { + popMenu(); + return; + } + else if (!s_copyMode) { + m_posVert = sub = g_eeGeneral.currModel; + s_copyMode = 0; + s_editMode = EDIT_MODE_INIT; + } + // no break +#endif + case EVT_KEY_BREAK(KEY_EXIT): + if (s_copyMode) { + sub = m_posVert = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (MAX_MODELS+sub+s_copyTgtOfs) % MAX_MODELS : s_copySrcRow; + s_copyMode = 0; + } +#if defined(PCBTARANIS) + else { + if (m_posVert != g_eeGeneral.currModel) { + m_posVert = g_eeGeneral.currModel; + s_pgOfs = 0; + } + else { + popMenu(); + return; + } + } +#endif + break; +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_BREAK: + if (s_editMode == -1) { + s_editMode = 0; + break; + } + // no break; +#endif + case EVT_KEY_LONG(KEY_ENTER): + case EVT_KEY_BREAK(KEY_ENTER): + s_editMode = 0; + if (READ_ONLY()) { + if (g_eeGeneral.currModel != sub && eeModelExists(sub)) { + selectModel(sub); + } + } + else if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) { + displayPopup(s_copyMode==COPY_MODE ? STR_COPYINGMODEL : STR_MOVINGMODEL); + eeCheck(true); // force writing of current model data before this is changed + + uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS; + + if (s_copyMode == COPY_MODE) { + if (eeCopyModel(cur, s_copySrcRow)) + BMP_DIRTY(); + else + cur = sub; + } + + s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value + while (sub != cur) { + uint8_t src = cur; + cur = (s_copyTgtOfs > 0 ? cur+MAX_MODELS-1 : cur+1) % MAX_MODELS; + eeSwapModels(src, cur); + BMP_DIRTY(); + if (src == s_copySrcRow) + s_copySrcRow = cur; + else if (cur == s_copySrcRow) + s_copySrcRow = src; + } + + if (s_copySrcRow != g_eeGeneral.currModel) { + g_eeGeneral.currModel = s_copySrcRow; + eeDirty(EE_GENERAL); + } + + s_copyMode = 0; + event = EVT_ENTRY_UP; + } + else if (event == EVT_KEY_LONG(KEY_ENTER) +#if !defined(PCBTARANIS) + || IS_ROTARY_BREAK(event) +#endif + ) { + s_copyMode = 0; + killEvents(event); +#if defined(NAVIGATION_MENUS) + if (g_eeGeneral.currModel != sub) { + if (eeModelExists(sub)) { + MENU_ADD_ITEM(STR_SELECT_MODEL); + MENU_ADD_SD_ITEM(STR_BACKUP_MODEL); + MENU_ADD_ITEM(STR_COPY_MODEL); + MENU_ADD_ITEM(STR_MOVE_MODEL); + MENU_ADD_ITEM(STR_DELETE_MODEL); + } + else { +#if defined(SDCARD) + MENU_ADD_ITEM(STR_CREATE_MODEL); + MENU_ADD_ITEM(STR_RESTORE_MODEL); +#else + selectModel(sub); +#endif + } + } + else { + MENU_ADD_SD_ITEM(STR_BACKUP_MODEL); + MENU_ADD_ITEM(STR_COPY_MODEL); + MENU_ADD_ITEM(STR_MOVE_MODEL); + } + menuHandler = onModelSelectMenu; +#else + if (g_eeGeneral.currModel != sub) { + selectModel(sub); + } +#endif + } + else if (eeModelExists(sub)) { + s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); + s_copyTgtOfs = 0; + s_copySrcRow = -1; + } + break; + +#if defined(PCBTARANIS) + case EVT_KEY_BREAK(KEY_PAGE): + case EVT_KEY_LONG(KEY_PAGE): + chainMenu(event == EVT_KEY_BREAK(KEY_PAGE) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]); + killEvents(event); + return; +#else +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LEFT: + case EVT_ROTARY_RIGHT: +#endif + case EVT_KEY_FIRST(KEY_LEFT): + case EVT_KEY_FIRST(KEY_RIGHT): +#if defined(ROTARY_ENCODER_NAVIGATION) + if ((!IS_ROTARY_RIGHT(event) && !IS_ROTARY_LEFT(event)) || s_editMode < 0) { +#endif + if (sub == g_eeGeneral.currModel) { + chainMenu((IS_ROTARY_RIGHT(event) || event == EVT_KEY_FIRST(KEY_RIGHT)) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]); + return; + } + AUDIO_WARNING2(); + break; +#if defined(ROTARY_ENCODER_NAVIGATION) + } + // no break +#endif +#endif + + case EVT_KEY_FIRST(KEY_MOVE_UP): + case EVT_KEY_REPT(KEY_MOVE_UP): + case EVT_KEY_FIRST(KEY_MOVE_DOWN): + case EVT_KEY_REPT(KEY_MOVE_DOWN): + if (s_copyMode) { + int8_t next_ofs = s_copyTgtOfs + oldSub - m_posVert; + if (next_ofs == MAX_MODELS || next_ofs == -MAX_MODELS) + next_ofs = 0; + + if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) { + s_copySrcRow = oldSub; + // find a hole (in the first empty slot above / below) + sub = eeFindEmptyModel(s_copySrcRow, IS_ROTARY_DOWN(event) || event==EVT_KEY_FIRST(KEY_MOVE_DOWN)); + if (sub < 0) { + // no free room for duplicating the model + AUDIO_ERROR(); + sub = oldSub; + s_copyMode = 0; + } + next_ofs = 0; + m_posVert = sub; + } + s_copyTgtOfs = next_ofs; + } + break; + } + +#if defined(PCBTARANIS) + lcd_puts(27*FW-(LEN_FREE-4)*FW, 0, STR_FREE); + if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree(); + lcd_outdezAtt(20*FW, 0, reusableBuffer.modelsel.eepromfree, 0); + lcd_puts(21*FW, 0, STR_BYTES); +#elif !defined(PCBSKY9X) + lcd_puts(9*FW-(LEN_FREE-4)*FW, 0, STR_FREE); + if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree(); + lcd_outdezAtt(17*FW, 0, reusableBuffer.modelsel.eepromfree, 0); +#endif + +#if defined(ROTARY_ENCODER_NAVIGATION) + displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? ((IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) ? INVERS|BLINK : INVERS) : 0); +#elif defined(PCBTARANIS) + displayScreenIndex(e_ModelSelect, DIM(menuTabModel), 0); + lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); +#else + displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? INVERS : 0); +#endif + + TITLE(STR_MENUMODELSEL); + + for (uint8_t i=0; i= 0)) { + if (k == sub) { + if (s_copyMode == COPY_MODE) { + k = s_copySrcRow; + lcd_putc(MODELSEL_W-FW, y, '+'); + } + else { + k = sub + s_copyTgtOfs; + } + } + else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-MAX_MODELS < sub && k-MAX_MODELS >= sub+s_copyTgtOfs))) + k += 1; + else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+MAX_MODELS > sub && k+MAX_MODELS <= sub+s_copyTgtOfs))) + k += MAX_MODELS-1; + } + + k %= MAX_MODELS; + + if (eeModelExists(k)) { +#if defined(PCBSKY9X) + putsModelName(4*FW, y, modelHeaders[k].name, k, 0); +#elif defined(CPUARM) + putsModelName(4*FW, y, modelHeaders[k].name, k, 0); + lcd_outdezAtt(20*FW, y, eeModelSize(k), 0); +#else + char * name = reusableBuffer.modelsel.listnames[i]; + if (event) eeLoadModelName(k, name); + putsModelName(4*FW, y, name, k, 0); + lcd_outdezAtt(20*FW, y, eeModelSize(k), 0); +#endif + if (k==g_eeGeneral.currModel && (s_copyMode!=COPY_MODE || s_copySrcRow<0 || i+s_pgOfs!=(vertpos_t)sub)) lcd_putc(1, y, '*'); + } + + if (s_copyMode && (vertpos_t)sub==i+s_pgOfs) { + lcd_filled_rect(9, y, MODELSEL_W-1-9, 7); + lcd_rect(8, y-1, MODELSEL_W-1-7, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); + } + } + +#if defined(PCBTARANIS) + if (modelselBitmapIdx != m_posVert) { + modelselBitmapIdx = m_posVert; + if (modelselBitmapIdx == g_eeGeneral.currModel) + memcpy(modelselBitmap, modelBitmap, MODEL_BITMAP_SIZE); + else + loadModelBitmap(modelHeaders[sub].bitmap, modelselBitmap); + } + lcd_bmp(22*FW+2, 2*FH+FH/2, modelselBitmap); +#endif +} + +#if defined(PCBTARANIS) +uint8_t g_moduleIdx; +void menuModelFailsafe(uint8_t event) +{ + static bool longNames = false; + bool newLongNames = false; + uint8_t ch; + + if (event == EVT_KEY_BREAK(KEY_ENTER) && s_editMode) { + g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert]; + eeDirty(EE_MODEL); + AUDIO_WARNING1(); + SEND_FAILSAFE_NOW(g_moduleIdx); + } + + SIMPLE_SUBMENU_NOTITLE(32); + + SET_SCROLLBAR_X(0); + + if (m_posVert >= 16) + ch = 16; + else + ch = 0; + + lcd_putsCenter(0*FH, FAILSAFESET); + lcd_invert_line(0); + + // Column separator + lcd_vline(LCD_W/2, FH, LCD_H-FH); + + for (uint8_t col=0; col<2; col++) { + + uint8_t x = col*LCD_W/2+1; + + // Channels + for (uint8_t line=0; line<8; line++) { + uint8_t y = 9+line*7; + int32_t val; + uint8_t ofs = (col ? 0 : 1); + + if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) + val = 0; + else if (s_editMode && m_posVert == ch) + val = channelOutputs[ch]; + else + val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; + + // Channel name if present, number if not + uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); + if (lenLabel > 4) { + newLongNames = longNames = true; + } + + if (lenLabel > 0) + lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE); + else + putsChn(x+1-ofs, y, ch+1, SMLSIZE); + + // Value + LcdFlags flags = TINSIZE; + if (m_posVert == ch) { + flags |= INVERS; + if (s_editMode) + flags |= BLINK; + } +#if defined(PPM_UNIT_US) + uint8_t wbar = (longNames ? 54 : 64); + lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags); +#elif defined(PPM_UNIT_PERCENT_PREC1) + uint8_t wbar = (longNames ? 48 : 58); + lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags); +#else + uint8_t wbar = (longNames ? 54 : 64); + lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, calcRESXto1000(val)/10, flags); +#endif + + // Gauge + lcd_rect(x+LCD_W/2-3-wbar-ofs, y, wbar+1, 6); + uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2; + uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); + uint8_t x0 = (val>0) ? x+LCD_W/2-ofs-3-wbar/2 : x+LCD_W/2-ofs-2-wbar/2-len; + lcd_hline(x0, y+1, len); + lcd_hline(x0, y+2, len); + lcd_hline(x0, y+3, len); + lcd_hline(x0, y+4, len); + + ch++; + } + } + + longNames = newLongNames; +} +#endif + +#if defined(CPUM64) + #define editNameCursorPos m_posHorz +#else + static uint8_t editNameCursorPos = 0; +#endif + +void editName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, uint8_t active) +{ +#if defined(CPUM64) + // in order to save flash + lcd_putsLeft(y, STR_NAME); +#endif + + lcd_putsnAtt(x, y, name, size, ZCHAR | ((active && s_editMode <= 0) ? INVERS : 0)); + + if (active) { + uint8_t cur = editNameCursorPos; + if (s_editMode > 0) { + int8_t c = name[cur]; + int8_t v = c; + + if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) + || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { + v = checkIncDec(event, abs(v), 0, LEN_STD_CHARS, 0); + if (c <= 0) v = -v; + } + + switch (event) { +#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) + case EVT_ROTARY_BREAK: + if (s_editMode == EDIT_MODIFY_FIELD) { + s_editMode = EDIT_MODIFY_STRING; + cur = 0; + } + else if (cur0) cur--; + break; + case EVT_KEY_BREAK(KEY_RIGHT): + if (cur=-26 && v<=26) { + v = -v; // toggle case + if (event==EVT_KEY_LONG(KEY_LEFT)) + killEvents(KEY_LEFT); + } + break; + } + + if (c != v) { + name[cur] = v; + eeDirty(EE_MODEL); + } + lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), INVERS); + } + else { + cur = 0; + } + editNameCursorPos = cur; + } +} + +#if defined(CPUM64) +#define editSingleName(x, y, label, name, size, event, active) editName(x, y, name, size, event, active) +#else +void editSingleName(uint8_t x, uint8_t y, const pm_char *label, char *name, uint8_t size, uint8_t event, uint8_t active) +{ + lcd_putsLeft(y, label); + editName(x, y, name, size, event, active); +} +#endif + +enum menuModelSetupItems { + ITEM_MODEL_NAME, + CASE_PCBTARANIS(ITEM_MODEL_BITMAP) + ITEM_MODEL_TIMER1, + IF_PERSISTENT_TIMERS(ITEM_MODEL_TIMER1_PERSISTENT) + ITEM_MODEL_TIMER1_MINUTE_BEEP, + ITEM_MODEL_TIMER1_COUNTDOWN_BEEP, + ITEM_MODEL_TIMER2, + IF_PERSISTENT_TIMERS(ITEM_MODEL_TIMER2_PERSISTENT) + ITEM_MODEL_TIMER2_MINUTE_BEEP, + ITEM_MODEL_TIMER2_COUNTDOWN_BEEP, + ITEM_MODEL_EXTENDED_LIMITS, + ITEM_MODEL_EXTENDED_TRIMS, + ITEM_MODEL_TRIM_INC, + ITEM_MODEL_THROTTLE_REVERSED, + ITEM_MODEL_THROTTLE_TRACE, + ITEM_MODEL_THROTTLE_TRIM, + ITEM_MODEL_THROTTLE_WARNING, + ITEM_MODEL_SWITCHES_WARNING, + ITEM_MODEL_BEEP_CENTER, +#if defined(PCBTARANIS) + ITEM_MODEL_INTERNAL_MODULE_LABEL, + ITEM_MODEL_INTERNAL_MODULE_MODE, + ITEM_MODEL_INTERNAL_MODULE_CHANNELS, + ITEM_MODEL_INTERNAL_MODULE_BIND, + ITEM_MODEL_INTERNAL_MODULE_FAILSAFE, + ITEM_MODEL_EXTERNAL_MODULE_LABEL, + ITEM_MODEL_EXTERNAL_MODULE_MODE, + ITEM_MODEL_EXTERNAL_MODULE_CHANNELS, + ITEM_MODEL_EXTERNAL_MODULE_BIND, + ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE, + ITEM_MODEL_TRAINER_LABEL, + ITEM_MODEL_TRAINER_MODE, + ITEM_MODEL_TRAINER_CHANNELS, + ITEM_MODEL_TRAINER_SETTINGS, +#elif defined(PCBSKY9X) + ITEM_MODEL_PPM1_PROTOCOL, + ITEM_MODEL_PPM1_PARAMS, + ITEM_MODEL_PPM2_PROTOCOL, + ITEM_MODEL_PPM2_PARAMS, +#else + ITEM_MODEL_PPM1_PROTOCOL, + ITEM_MODEL_PPM1_PARAMS, +#endif + ITEM_MODEL_SETUP_MAX +}; + +#if defined(PCBSKY9X) + #define FIELD_PROTOCOL_MAX 2 +#else + #define FIELD_PROTOCOL_MAX 1 +#endif + +#if LCD_W >= 212 +#define MODEL_SETUP_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH) +#else +#define MODEL_SETUP_2ND_COLUMN (LCD_W-11*FW-MENUS_SCROLLBAR_WIDTH) +#endif + +#if defined(PCBTARANIS) && defined(SDCARD) +void copySelection(char *dst, const char *src, uint8_t size) +{ + if (memcmp(src, "---", 3) == 0) + memset(dst, 0, size); + else + memcpy(dst, src, size); +} + +void onModelSetupBitmapMenu(const char *result) +{ + if (result == STR_UPDATE_LIST) { + if (!listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), NULL)) { + POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + s_menu_flags = 0; + } + } + else { + // The user choosed a bmp file in the list + copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap)); + LOAD_MODEL_BITMAP(); + memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); + eeDirty(EE_MODEL); + } +} +#endif + +void menuModelSetup(uint8_t event) +{ +#if defined(PCBTARANIS) + #define IF_PORT1_ON(x) (g_model.moduleData[0].rfProtocol == RF_PROTO_OFF ? HIDDEN_ROW : (uint8_t)(x)) + #define IF_PORT2_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x)) + #define IF_TRAINER_ON(x) (g_model.trainerMode ? (uint8_t)(x) : HIDDEN_ROW) + #define IF_PORT_ON(idx, x) (idx==0 ? IS_PORT1_ON(x) : (idx==1 ? IS_PORT2_ON(x) : IS_TRAINER_ON())) + #define IF_PORT2_XJT(x) (IS_MODULE_XJT(1) ? (uint8_t)x : HIDDEN_ROW) + #define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) + #define PORT1_CHANNELS_ROWS() IF_PORT1_ON(1) + #define PORT2_CHANNELS_ROWS() IF_PORT2_ON(IS_MODULE_DSM2(1) ? (uint8_t)0 : (uint8_t)1) + #define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) + #define PORT_CHANNELS_ROWS(x) (x==0 ? PORT1_CHANNELS_ROWS() : (x==1 ? PORT2_CHANNELS_ROWS() : TRAINER_CHANNELS_ROWS())) + #define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) + #define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX) + + bool CURSOR_ON_CELL = (m_posHorz >= 0); + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(IS_D8_RX(0) ? (uint8_t)1 : (uint8_t)2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_XJT(1) && IS_D8_RX(1)) ? (uint8_t)1 : (IS_MODULE_PPM(1) || IS_MODULE_XJT(1) || IS_MODULE_DSM2(1)) ? (uint8_t)2 : HIDDEN_ROW, IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); +#elif defined(CPUM64) + #define CURSOR_ON_CELL (true) + #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) + + uint8_t protocol = g_model.protocol; + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2 }); +#else + #define CURSOR_ON_CELL (true) + #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) + + uint8_t protocol = g_model.protocol; + MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2, IF_PCBSKY9X(1) IF_PCBSKY9X(2) }); +#endif + + if (!MENU_CHECK(menuTabModel, e_ModelSetup, MODEL_SETUP_MAX_LINES)) { +#if defined(DSM2) + dsm2Flag = 0; +#endif +#if defined(PCBTARANIS) + pxxFlag[INTERNAL_MODULE] = 0; + pxxFlag[EXTERNAL_MODULE] = 0; +#endif + return; + } + + TITLE(STR_MENUSETUP); + + uint8_t sub = m_posVert - 1; + int8_t editMode = s_editMode; + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); + uint8_t attr = (sub == k ? blink : 0); + + switch(k) { + case ITEM_MODEL_NAME: + editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_MODELNAME, g_model.header.name, sizeof(g_model.header.name), event, attr); +#if defined(CPUARM) + memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name)); +#endif + break; + +#if defined(PCBTARANIS) && defined(SDCARD) + case ITEM_MODEL_BITMAP: + lcd_putsLeft(y, STR_BITMAP); + if (ZEXIST(g_model.header.bitmap)) + lcd_putsnAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.bitmap, sizeof(g_model.header.bitmap), attr); + else + lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VCSWFUNC, 0, attr); + if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) { + s_editMode = 0; + if (listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), g_model.header.bitmap, LIST_NONE_SD_FILE)) { + menuHandler = onModelSetupBitmapMenu; + } + else { + POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + s_menu_flags = 0; + } + } + break; +#endif + + case ITEM_MODEL_TIMER1: + case ITEM_MODEL_TIMER2: + case ITEM_MODEL_TIMER1_MINUTE_BEEP: + case ITEM_MODEL_TIMER2_MINUTE_BEEP: + case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP: + case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP: + { + TimerData *timer = &g_model.timers[k>=ITEM_MODEL_TIMER2 ? 1 : 0]; + if (k==ITEM_MODEL_TIMER1_MINUTE_BEEP || k==ITEM_MODEL_TIMER2_MINUTE_BEEP) { + timer->minuteBeep = onoffMenuItem(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); + } + else if (k==ITEM_MODEL_TIMER1_COUNTDOWN_BEEP || k==ITEM_MODEL_TIMER2_COUNTDOWN_BEEP) { +#if defined(CPUARM) + timer->countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, timer->countdownBeep, 0, 2, attr, event); +#else + timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); +#endif + } + else { + putsStrIdx(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1); + putsTmrMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, m_posHorz==0 ? attr : 0); + putsTime(MODEL_SETUP_2ND_COLUMN+5*FW-2+5*FWNUM+1, y, timer->start, m_posHorz==1 ? attr : 0, m_posHorz==2 ? attr : 0); +#if defined(PCBTARANIS) + if (attr && m_posHorz < 0) lcd_filled_rect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); +#endif + if (attr && (editMode>0 || p1valdiff)) { + div_t qr = div(timer->start, 60); + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, timer->mode, -2*(MAX_PSWITCH+NUM_CSW), TMR_VAROFS-1+2*(MAX_PSWITCH+NUM_CSW)); + break; + case 1: + CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 59); + timer->start = qr.rem + qr.quot*60; + break; + case 2: + qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2; + timer->start -= qr.rem ; + if ((int16_t)timer->start < 0) timer->start=0; + break; + } + } + } + break; + } + +#if defined(CPUARM) || defined(PCBGRUVIN9X) + case ITEM_MODEL_TIMER1_PERSISTENT: + case ITEM_MODEL_TIMER2_PERSISTENT: + { + TimerData &timer = g_model.timers[k==ITEM_MODEL_TIMER2_PERSISTENT]; + timer.persistent = onoffMenuItem(timer.persistent, MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, attr, event); + break; + } +#endif + + case ITEM_MODEL_EXTENDED_LIMITS: + g_model.extendedLimits = onoffMenuItem(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event); + break; + + case ITEM_MODEL_EXTENDED_TRIMS: +#if defined(CPUM64) + g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event); +#else + g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 ? attr : 0); + if (attr && m_posHorz>0) { + s_editMode = 0; + if (event==EVT_KEY_LONG(KEY_ENTER)) { + for (uint8_t i=0; i MIXSRC_Thr) + idx += 1; + if (idx >= MIXSRC_FIRST_POT+NUM_POTS) + idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS; + putsMixerSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr); + break; + } + + case ITEM_MODEL_THROTTLE_TRIM: + g_model.thrTrim = onoffMenuItem(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event); + break; + + case ITEM_MODEL_THROTTLE_WARNING: + g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); + break; + + case ITEM_MODEL_SWITCHES_WARNING: + { + lcd_putsLeft(y, STR_SWITCHWARNING); + swstate_t states = g_model.switchWarningStates; + char c = !(states & 1); + menu_lcd_onoff(MODEL_SETUP_2ND_COLUMN, y, c, attr); + if (attr) { + s_editMode = 0; + switch(event) { + case EVT_KEY_LONG(KEY_ENTER): + if (!READ_ONLY()) { + killEvents(event); + getMovedSwitch(); + g_model.switchWarningStates = 0x01 + (switches_states << 1); + } + // no break + CASE_EVT_ROTARY_BREAK + case EVT_KEY_BREAK(KEY_ENTER): +#if !defined(PCBTARANIS) + case EVT_KEY_BREAK(KEY_LEFT): + case EVT_KEY_BREAK(KEY_RIGHT): +#endif + if (!READ_ONLY()) { + g_model.switchWarningStates ^= 0x01; + eeDirty(EE_MODEL); + } + break; + } + } + if (c) { + states >>= 1; + for (uint8_t i=1; i>= 2; +#else + attr = 0; + if (IS_3POS(i-1)) { + c = '0'+(states & 0x03); + states >>= 2; + } + else { + if (states & 0x01) + attr = INVERS; + c = pgm_read_byte(STR_VSWITCHES - 2 + 6 + (3*i)); + states >>= 1; + } + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+2*FW+i*FW, y, c, attr); +#endif + } + } + break; + } + + case ITEM_MODEL_BEEP_CENTER: + lcd_putsLeft(y, STR_BEEPCTR); + for (uint8_t i=0; i0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.externalModule, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1); + if (checkIncDec_Ret) { + g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; + if (g_model.externalModule == MODULE_TYPE_PPM) + g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0; + else + g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_PORT2_CHANNELS(); + } + break; + case 1: + if (IS_MODULE_DSM2(EXTERNAL_MODULE)) + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX); + else + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST); + if (checkIncDec_Ret) { + g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; + g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_PORT2_CHANNELS(); + } + } + } + break; + + case ITEM_MODEL_INTERNAL_MODULE_CHANNELS: + case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS: + case ITEM_MODEL_TRAINER_CHANNELS: + { + uint8_t moduleIdx = (k>=ITEM_MODEL_TRAINER_LABEL ? 2 : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0)); + ModuleData & moduleData = g_model.moduleData[moduleIdx]; + lcd_putsLeft(y, STR_CHANNELRANGE); + if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) { + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN, y, STR_CH, m_posHorz==0 ? attr : 0); + lcd_outdezAtt(lcdLastPos, y, moduleData.channelsStart+1, LEFT | (m_posHorz==0 ? attr : 0)); + lcd_putc(lcdLastPos, y, '-'); + lcd_outdezAtt(lcdLastPos + FW+1, y, moduleData.channelsStart+NUM_CHANNELS(moduleIdx), LEFT | (m_posHorz==1 ? attr : 0)); + if (attr && (editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min(MAX_CHANNELS(moduleIdx), 32-8-moduleData.channelsStart)); + if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.externalModule == MODULE_TYPE_PPM) || (k == ITEM_MODEL_TRAINER_CHANNELS)) + SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx); + break; + } + } + } + break; + } + + case ITEM_MODEL_INTERNAL_MODULE_BIND: + case ITEM_MODEL_EXTERNAL_MODULE_BIND: + case ITEM_MODEL_TRAINER_SETTINGS: + { + uint8_t moduleIdx = (k>=ITEM_MODEL_TRAINER_LABEL ? 2 : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0)); + ModuleData & moduleData = g_model.moduleData[moduleIdx]; + if (IS_MODULE_PPM(moduleIdx)) { + lcd_putsLeft(y, STR_PPMFRAME); + lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); + lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (moduleData.ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, moduleData.ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); + + if (attr && (editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, moduleData.ppmFrameLength, -20, 35); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, moduleData.ppmDelay, -4, 10); + break; + case 2: + CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.ppmPulsePol, 1); + break; + } + } + } + else { + horzpos_t l_posHorz = m_posHorz; + uint8_t xOffsetBind = 3*FW; + if (IS_MODULE_XJT(moduleIdx) && IS_D8_RX(moduleIdx)) { + xOffsetBind = 0; + lcd_putsLeft(y, INDENT "Receiver"); + if (attr) l_posHorz += 1; + } + else { + lcd_putsLeft(y, STR_RXNUM); + } + if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) { + if (xOffsetBind) lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId, (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2); + if (attr && l_posHorz==0) { + if (editMode>0 || p1valdiff) { + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId, IS_MODULE_DSM2(moduleIdx) ? 20 : 63); + if (checkIncDec_Ret) { + modelHeaders[g_eeGeneral.currModel].modelId = g_model.header.modelId; + } + } + if (editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) { + checkModelIdUnique(g_eeGeneral.currModel); + } + } + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+7*FW+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); + if (IS_MODULE_XJT(moduleIdx)) { + uint8_t newFlag = 0; + if (attr && l_posHorz>0 && s_editMode>0) { + if (l_posHorz == 1) + newFlag = PXX_SEND_RXNUM; + else if (l_posHorz == 2) { + newFlag = PXX_SEND_RANGECHECK; + } + } + pxxFlag[moduleIdx] = newFlag; + } +#if defined(DSM2) + else { + uint8_t newFlag = 0; + if (attr && l_posHorz>0 && s_editMode>0) { + if (l_posHorz == 1) + newFlag = DSM2_BIND_FLAG; + else if (l_posHorz == 2) { + newFlag = DSM2_RANGECHECK_FLAG; + } + } + dsm2Flag = newFlag; + } +#endif + } + } + break; + } + + case ITEM_MODEL_INTERNAL_MODULE_FAILSAFE: + case ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE: + { + uint8_t moduleIdx = (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0); + ModuleData & moduleData = g_model.moduleData[moduleIdx]; + lcd_putsLeft(y, TR_FAILSAFE); + if (IS_MODULE_XJT(moduleIdx)) { + lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, m_posHorz==0 ? attr : 0); + if (moduleData.failsafeMode == FAILSAFE_CUSTOM) lcd_putsAtt(MODEL_SETUP_2ND_COLUMN + 10*FW, y, STR_SET, m_posHorz==1 ? attr : 0); + if (attr) { + if (moduleData.failsafeMode != FAILSAFE_CUSTOM) + m_posHorz = 0; + if (m_posHorz==0) { + if (editMode>0 || p1valdiff) { + CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.failsafeMode, FAILSAFE_LAST); + if (checkIncDec_Ret) SEND_FAILSAFE_NOW(moduleIdx); + } + } + else if (m_posHorz==1) { + s_editMode = 0; + if (moduleData.failsafeMode==FAILSAFE_CUSTOM && event==EVT_KEY_FIRST(KEY_ENTER)) { + g_moduleIdx = moduleIdx; + pushMenu(menuModelFailsafe); + } + } + else { + lcd_filled_rect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); + } + } + } + break; + } + + case ITEM_MODEL_TRAINER_LABEL: + lcd_putsLeft(y, STR_TRAINER); + break; + + case ITEM_MODEL_TRAINER_MODE: + g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, 0, 1, attr, event); + break; + +#else + + case ITEM_MODEL_PPM1_PROTOCOL: +#if defined(PCBSKY9X) + lcd_putsLeft(y, PSTR("Port1")); +#else + lcd_putsLeft(y, NO_INDENT(STR_PROTO)); +#endif + + lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, protocol, m_posHorz<=0 ? attr : 0); + +#if defined(PCBSKY9X) + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, m_posHorz==1 ? attr : 0); + lcd_outdezAtt(lcdLastPos, y, g_model.moduleData[0].channelsStart+1, LEFT | (m_posHorz==1 ? attr : 0)); + lcd_putc(lcdLastPos, y, '-'); + lcd_outdezAtt(lcdLastPos + FW+1, y, g_model.moduleData[0].channelsStart+NUM_PORT1_CHANNELS(), LEFT | (m_posHorz==2 ? attr : 0)); +#else + if (IS_PPM_PROTOCOL(protocol)) { + lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN+7*FW, y, STR_NCHANNELS, g_model.ppmNCH+2, m_posHorz!=0 ? attr : 0); + } + else if (attr) { + MOVE_CURSOR_FROM_HERE(); + } +#endif + + if (attr && (editMode>0 || p1valdiff +#if !defined(PCBSKY9X) + || (!IS_PPM_PROTOCOL(protocol) && !IS_DSM2_PROTOCOL(protocol)) +#endif + )) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.protocol, PROTO_MAX-1); + break; + case 1: +#if defined(PCBSKY9X) + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[0].channelsStart, 32-8-g_model.moduleData[0].channelsCount); + g_model.moduleData[0].ppmFrameLength = max((int8_t)0, g_model.moduleData[0].channelsCount) * 4; + SET_DEFAULT_PPM_FRAME_LENGTH(0); +#else + CHECK_INCDEC_MODELVAR(event, g_model.ppmNCH, -2, 4); + g_model.ppmFrameLength = g_model.ppmNCH * 8; +#endif + break; +#if defined(PCBSKY9X) + case 2: + if (IS_PPM_PROTOCOL(protocol)) { + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].channelsCount, -4, min(8, 32-8-g_model.moduleData[0].channelsStart)); + SET_DEFAULT_PPM_FRAME_LENGTH(0); + } + else + REPEAT_LAST_CURSOR_MOVE(); + break; +#endif + } + } + break; + +#if defined(PCBSKY9X) + case ITEM_MODEL_PPM2_PROTOCOL: + lcd_putsLeft(y, PSTR("Port2")); + lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, 0, 0); + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, m_posHorz<=0 ? attr : 0); + lcd_outdezAtt(lcdLastPos, y, g_model.moduleData[1].channelsStart+1, LEFT | (m_posHorz<=0 ? attr : 0)); + lcd_putc(lcdLastPos, y, '-'); + lcd_outdezAtt(lcdLastPos + FW+1, y, g_model.moduleData[1].channelsStart+8+g_model.moduleData[1].channelsCount, LEFT | (m_posHorz!=0 ? attr : 0)); + if (attr && (editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].channelsStart, 32-8-g_model.moduleData[1].channelsCount); + SET_DEFAULT_PPM_FRAME_LENGTH(1); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].channelsCount, -4, min(8, 32-8-g_model.moduleData[1].channelsStart)); + SET_DEFAULT_PPM_FRAME_LENGTH(1); + break; + } + } + break; + + case ITEM_MODEL_PPM2_PARAMS: + lcd_putsLeft(y, STR_PPMFRAME); + lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[1].ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); + lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[1].ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[1].ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); + if (attr && (editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmFrameLength, -20, 35); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmDelay, -4, 10); + break; + case 2: + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].ppmPulsePol, 1); + break; + } + } + break; +#endif + + case ITEM_MODEL_PPM1_PARAMS: +#if defined(PCBSKY9X) + if (IS_PPM_PROTOCOL(protocol)) { + lcd_putsLeft(y, STR_PPMFRAME); + lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[0].ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); + lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[0].ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[0].ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); + if (attr && (editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].ppmFrameLength, -20, 35); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].ppmDelay, -4, 10); + break; + case 2: + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[0].ppmPulsePol, 1); + break; + } + } + } +#else + if (IS_PPM_PROTOCOL(protocol)) { + lcd_putsLeft(y, STR_PPMFRAME); + lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); + lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); + lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); + lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.pulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); + if (attr && (editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.ppmFrameLength, -20, 35); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.ppmDelay, -4, 10); + break; + case 2: + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.pulsePol, 1); + break; + } + } + } +#endif +#if defined(DSM2) || defined(PXX) + else if (IS_DSM2_PROTOCOL(protocol) || IS_PXX_PROTOCOL(protocol)) { + if (attr && m_posHorz > 1) { + REPEAT_LAST_CURSOR_MOVE(); // limit 3 column row to 2 colums (Rx_Num and RANGE fields) + } + + lcd_putsLeft(y, STR_RXNUM); + lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId, (m_posHorz<=0 ? attr : 0) | LEADING0|LEFT, 2); + if (attr && (m_posHorz==0 && (editMode>0 || p1valdiff))) { + CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId, 99); +#if defined(CPUARM) + if (checkIncDec_Ret) + modelHeaders[g_eeGeneral.currModel].modelId = g_model.header.modelId; +#endif + } + +#if defined(PXX) + if (protocol == PROTO_PXX) { +#if defined(CPUARM) + if (attr && m_posHorz==0 && editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) + checkModelIdUnique(g_eeGeneral.currModel); +#endif + + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_SYNCMENU, m_posHorz!=0 ? attr : 0); + if (attr && m_posHorz>0 && editMode>0) { + // send reset code + pxxFlag[0] = PXX_SEND_RXNUM; + } + } +#endif + +#if defined(DSM2) + if (IS_DSM2_PROTOCOL(protocol)) { + lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_MODULE_RANGE, m_posHorz!=0 ? attr : 0); + dsm2Flag = (attr && m_posHorz>0 && editMode>0) ? DSM2_RANGECHECK_FLAG : 0; // [MENU] key toggles range check mode + } +#endif + } +#endif + break; +#endif // defined(PCBTARANIS) + } + } + +#if defined(PCBTARANIS) + if (pxxFlag[INTERNAL_MODULE] == PXX_SEND_RANGECHECK || pxxFlag[EXTERNAL_MODULE] == PXX_SEND_RANGECHECK) { + displayPopup("RSSI: "); + lcd_outdezAtt(16+4*FW, 5*FH, frskyData.rssi[0].value, BOLD); + } +#endif +} + +static uint8_t s_currIdx; + +#if MENU_COLUMNS < 2 + #if LCD_W >= 212 + #define MIXES_2ND_COLUMN (18*FW) + #else + #define MIXES_2ND_COLUMN (12*FW) + #endif +#else + #define MIXES_2ND_COLUMN (9*FW) +#endif + +#if LCD_W >= 212 + #define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90) + #define EXPO_ONE_FP_WIDTH (9*FW) +#else + #define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) + #define EXPO_ONE_FP_WIDTH (5*FW) +#endif + +#if MENU_COLUMNS > 1 +uint8_t editDelay(const xcoord_t x, const uint8_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay) +{ + lcd_puts(x, y, str); + lcd_outdezAtt(x+MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX); + return delay; +} +#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(x, y, event, attr, str, delay) +#else +uint8_t editDelay(const uint8_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay) +{ + lcd_putsLeft(y, str); + lcd_outdezAtt(MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX); + return delay; +} +#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(y, event, attr, str, delay) +#endif + +#if defined(FLIGHT_MODES) + +#if defined(CPUARM) + #define FlightModesType uint16_t +#else + #define FlightModesType uint8_t +#endif + +void displayFlightModes(uint8_t x, uint8_t y, FlightModesType value) +{ + uint8_t p = MAX_PHASES; + do { + --p; + if (!(value & (1< EXPO_ONE_2ND_COLUMN-FW))) + continue; +#endif +#if defined(PCBTARANIS) + LcdFlags flags = 0; + if (attr) { + flags |= INVERS; + if (posHorz==p) flags |= BLINK; + } + if (value & (1<= 212 + +enum FlightModesItems { + ITEM_PHASES_NAME, + ITEM_PHASES_SWITCH, + ITEM_PHASES_TRIMS, + ITEM_PHASES_FADE_IN, + ITEM_PHASES_FADE_OUT, + ITEM_PHASES_COUNT, + ITEM_PHASES_LAST = ITEM_PHASES_COUNT-1 +}; + +void editPhaseTrims(uint8_t x, uint8_t y, uint8_t phase, uint8_t event, uint8_t active) +{ + static uint8_t cursorPos = 0; + + for (uint8_t t=0; t 0) { + if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) + || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { + int16_t v = getRawTrimValue(phase, cur); + if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX; + v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL); + if (checkIncDec_Ret) { + if (v == TRIM_EXTENDED_MAX) v = 0; + setTrimValue(phase, cur, v); + } + } + + switch (event) { +#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) + case EVT_ROTARY_BREAK: + if (s_editMode == EDIT_MODIFY_FIELD) { + s_editMode = EDIT_MODIFY_STRING; + cur = 0; + } + else if (cur0) cur--; + break; + case EVT_KEY_BREAK(KEY_RIGHT): + if (cur 0) { posHorz += 2; } + + if (sub=0) { + displayColumnHeader(STR_PHASES_HEADERS, posHorz); + } + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); + uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; + switch(j) + { + case ITEM_PHASES_NAME: + editName(4*FW, y, p->name, sizeof(p->name), event, attr); + break; + + case ITEM_PHASES_SWITCH: + if (k == 0) { + lcd_puts((5+LEN_FP_NAME)*FW+FW/2, y, STR_DEFAULT); + } + else { + putsSwitches((5+LEN_FP_NAME)*FW+FW/2, y, p->swtch, attr); + if (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, -MAX_SWITCH, MAX_SWITCH); + } + break; + + case ITEM_PHASES_TRIMS: + if (k != 0) { + editPhaseTrims((10+LEN_FP_NAME)*FW+FW/2, y, k, event, attr); + } + break; + + case ITEM_PHASES_FADE_IN: + lcd_outdezAtt(29*FW, y, (10/DELAY_STEP)*p->fadeIn, attr|PREC1); + if (active) p->fadeIn = checkIncDec(event, p->fadeIn, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS); + break; + + case ITEM_PHASES_FADE_OUT: + lcd_outdezAtt(34*FW, y, (10/DELAY_STEP)*p->fadeOut, attr|PREC1); + if (active) p->fadeOut = checkIncDec(event, p->fadeOut, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS); + break; + + } + } + } +} + +#else // LCD_W >= 212 + +enum menuModelPhaseItems { + ITEM_MODEL_PHASE_NAME, + ITEM_MODEL_PHASE_SWITCH, + ITEM_MODEL_PHASE_TRIMS, + IF_ROTARY_ENCODERS(ITEM_MODEL_PHASE_ROTARY_ENCODERS) + ITEM_MODEL_PHASE_FADE_IN, + ITEM_MODEL_PHASE_FADE_OUT, +#if defined(GVARS) && !defined(PCBSTD) + ITEM_MODEL_PHASE_GVARS_LABEL, + ITEM_MODEL_PHASE_GV1, + ITEM_MODEL_PHASE_GV2, + ITEM_MODEL_PHASE_GV3, + ITEM_MODEL_PHASE_GV4, + ITEM_MODEL_PHASE_GV5, +#endif + ITEM_MODEL_PHASE_MAX +}; + +void menuModelPhaseOne(uint8_t event) +{ + PhaseData *phase = phaseAddress(s_currIdx); + putsFlightPhase(13*FW, 0, s_currIdx+1, (getFlightPhase()==s_currIdx ? BOLD : 0)); + +#if defined(GVARS) && !defined(PCBSTD) + static const pm_uint8_t mstate_tab_phase1[] PROGMEM = {0, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1}; + static const pm_uint8_t mstate_tab_others[] PROGMEM = {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0, 0, (uint8_t)-1, 2, 2, 2, 2, 2}; + + if (!check(event, 0, NULL, 0, (s_currIdx == 0) ? mstate_tab_phase1 : mstate_tab_others, DIM(mstate_tab_others)-1, ITEM_MODEL_PHASE_MAX - 1 - (s_currIdx==0 ? (ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH) : 0))) return; + + TITLE(STR_MENUFLIGHTPHASE); + + #define PHASE_ONE_FIRST_LINE (1+1*FH) +#else + SUBMENU(STR_MENUFLIGHTPHASE, 3 + (s_currIdx==0 ? 0 : 2 + (bool)NUM_ROTARY_ENCODERS), {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0/*, 0*/}); + #define PHASE_ONE_FIRST_LINE (1+1*FH) +#endif + + int8_t sub = m_posVert; + int8_t editMode = s_editMode; + +#if defined(GVARS) && !defined(PCBSTD) + if (s_currIdx == 0 && sub>=ITEM_MODEL_PHASE_SWITCH) sub += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH; + + for (uint8_t k=0; k=ITEM_MODEL_PHASE_SWITCH) i += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH; + uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); +#else + for (uint8_t i=0, k=0, y=PHASE_ONE_FIRST_LINE; i0 ? BLINK|INVERS : INVERS) : 0); +#endif + switch(i) { + case ITEM_MODEL_PHASE_NAME: + editSingleName(MIXES_2ND_COLUMN, y, STR_PHASENAME, phase->name, sizeof(phase->name), event, attr); + break; + case ITEM_MODEL_PHASE_SWITCH: + phase->swtch = switchMenuItem(MIXES_2ND_COLUMN, y, phase->swtch, attr, event); + break; + case ITEM_MODEL_PHASE_TRIMS: + lcd_putsLeft(y, STR_TRIMS); + for (uint8_t t=0; t0) || p1valdiff)) { + int16_t v = getRawTrimValue(s_currIdx, t); + if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX; + v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL); + if (checkIncDec_Ret) { + if (v == TRIM_EXTENDED_MAX) v = 0; + setTrimValue(s_currIdx, t, v); + } + } + } + break; + +#if ROTARY_ENCODERS > 0 + case ITEM_MODEL_PHASE_ROTARY_ENCODERS: + lcd_putsLeft(y, STR_ROTARY_ENCODER); + for (uint8_t t=0; t0) || p1valdiff)) { +#if ROTARY_ENCODERS > 2 + int16_t v; + if(t < (NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)) + v = phaseAddress(s_currIdx)->rotaryEncoders[t]; + else + v = g_model.rotaryEncodersExtra[s_currIdx][t-(NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)]; +#else + int16_t v = phaseAddress(s_currIdx)->rotaryEncoders[t]; +#endif + if (v < ROTARY_ENCODER_MAX) v = ROTARY_ENCODER_MAX; + v = checkIncDec(event, v, ROTARY_ENCODER_MAX, ROTARY_ENCODER_MAX+MAX_PHASES-1, EE_MODEL); + if (checkIncDec_Ret) { + if (v == ROTARY_ENCODER_MAX) v = 0; +#if ROTARY_ENCODERS > 2 + if (t < (NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)) + phaseAddress(s_currIdx)->rotaryEncoders[t] = v; + else + g_model.rotaryEncodersExtra[s_currIdx][t-(NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)] = v; +#else + phaseAddress(s_currIdx)->rotaryEncoders[t] = v; +#endif + } + } + } + break; +#endif + + case ITEM_MODEL_PHASE_FADE_IN: + phase->fadeIn = EDIT_DELAY(0, y, event, attr, STR_FADEIN, phase->fadeIn); + break; + + case ITEM_MODEL_PHASE_FADE_OUT: + phase->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, phase->fadeOut); + break; + +#if defined(GVARS) && !defined(PCBSTD) + case ITEM_MODEL_PHASE_GVARS_LABEL: + lcd_putsLeft(y, STR_GLOBAL_VARS); + break; + + default: + { + uint8_t idx = i-ITEM_MODEL_PHASE_GV1; + uint8_t posHorz = m_posHorz; + if (attr && posHorz > 0 && s_currIdx==0) posHorz++; + + putsStrIdx(INDENT_WIDTH, y, STR_GV, idx+1); + + editName(4*FW, y, g_model.gvars[idx].name, LEN_GVAR_NAME, event, posHorz==0 ? attr : 0); + + int16_t v = phase->gvars[idx]; + if (v > GVAR_MAX) { + uint8_t p = v - GVAR_MAX - 1; + if (p >= s_currIdx) p++; + putsFlightPhase(11*FW, y, p+1, posHorz==1 ? attr : 0); + } + else { + lcd_putsAtt(11*FW, y, STR_OWN, posHorz==1 ? attr : 0); + } + if (attr && s_currIdx>0 && posHorz==1 && (editMode>0 || p1valdiff)) { + if (v < GVAR_MAX) v = GVAR_MAX; + v = checkIncDec(event, v, GVAR_MAX, GVAR_MAX+MAX_PHASES-1, EE_MODEL); + if (checkIncDec_Ret) { + if (v == GVAR_MAX) v = 0; + phase->gvars[idx] = v; + } + } + + uint8_t p = getGVarFlightPhase(s_currIdx, idx); + lcd_outdezAtt(21*FW, y, GVAR_VALUE(idx, p), posHorz==2 ? attr : 0); + if (attr && posHorz==2 && ((editMode>0) || p1valdiff)) { + GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -GVAR_LIMIT, GVAR_LIMIT, EE_MODEL); + } + + break; + } +#endif + } + } +} + +#if defined(ROTARY_ENCODERS) + #if ROTARY_ENCODERS > 2 + #define NAME_OFS (-4-12) + #define SWITCH_OFS (-FW/2-2-13) + #define TRIMS_OFS (-FW/2-4-15) + #define ROTARY_ENC_OFS (0) + #else + #define NAME_OFS (-4) + #define SWITCH_OFS (-FW/2-2) + #define TRIMS_OFS (-FW/2-4) + #define ROTARY_ENC_OFS (2) + #endif +#else + #define NAME_OFS 0 + #define SWITCH_OFS (FW/2) + #define TRIMS_OFS (FW/2) +#endif + +void menuModelFlightModesAll(uint8_t event) +{ + SIMPLE_MENU(STR_MENUFLIGHTPHASES, menuTabModel, e_FlightModesAll, 1+MAX_PHASES+1); + + int8_t sub = m_posVert - 1; + + switch (event) { + CASE_EVT_ROTARY_BREAK + case EVT_KEY_FIRST(KEY_ENTER): + if (sub == MAX_PHASES) { + s_editMode = 0; + trimsCheckTimer = 200; // 2 seconds + } + // no break + case EVT_KEY_FIRST(KEY_RIGHT): + if (sub >= 0 && sub < MAX_PHASES) { + s_currIdx = sub; + pushMenu(menuModelPhaseOne); + } + break; + } + + uint8_t att; + for (uint8_t i=0; i(LCD_LINES-1)*FH+1) continue; +#else + uint8_t y = 1 + (i+1)*FH; +#endif + att = (i==sub ? INVERS : 0); + PhaseData *p = phaseAddress(i); +#if ROTARY_ENCODERS > 2 + putsFlightPhase(0, y, i+1, att|CONDENSED|(getFlightPhase()==i ? BOLD : 0)); +#else + putsFlightPhase(0, y, i+1, att|(getFlightPhase()==i ? BOLD : 0)); +#endif + + lcd_putsnAtt(4*FW+NAME_OFS, y, p->name, sizeof(p->name), ZCHAR); + if (i == 0) { + lcd_puts((5+LEN_FP_NAME)*FW+SWITCH_OFS, y, STR_DEFAULT); + } + else { + putsSwitches((5+LEN_FP_NAME)*FW+SWITCH_OFS, y, p->swtch, 0); + for (uint8_t t=0; tfadeIn || p->fadeOut) + lcd_putc(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, (p->fadeIn && p->fadeOut) ? '*' : (p->fadeIn ? 'I' : 'O')); + + } + +#if defined(CPUARM) + if (s_pgOfs != MAX_PHASES-(LCD_LINES-2)) return; +#endif + + lcd_putsLeft((LCD_LINES-1)*FH+1, STR_CHECKTRIMS); + putsFlightPhase(OFS_CHECKTRIMS, (LCD_LINES-1)*FH+1, s_perout_flight_phase+1); + if (sub==MAX_PHASES && !trimsCheckTimer) { + lcd_status_line(); + } +} + +#endif // defined(PCBTARANIS) + +#else // defined(FLIGHT_MODES) + +#define displayFlightModes(...) + +#endif + +#if defined(HELI) + +enum menuModelHeliItems { + ITEM_HELI_SWASHTYPE, + ITEM_HELI_COLLECTIVE, + ITEM_HELI_SWASHRING, + ITEM_HELI_ELEDIRECTION, + ITEM_HELI_AILDIRECTION, + ITEM_HELI_COLDIRECTION +}; + +#if LCD_W >= 212 + #define HELI_PARAM_OFS (23*FW) +#else + #define HELI_PARAM_OFS (14*FW) +#endif + +void menuModelHeli(uint8_t event) +{ + SIMPLE_MENU(STR_MENUHELISETUP, menuTabModel, e_Heli, 7); + + uint8_t sub = m_posVert - 1; + + for (uint8_t i=0; i<6; i++) { + uint8_t y = 1 + 1*FH + i*FH; + uint8_t attr = (sub == i ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); + switch(i) { + case ITEM_HELI_SWASHTYPE: + g_model.swashR.type = selectMenuItem(HELI_PARAM_OFS, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_NUM, attr, event); + break; + + case ITEM_HELI_COLLECTIVE: +#if defined(PCBTARANIS) + lcd_putsLeft(y, STR_COLLECTIVE); + if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH); +#else + g_model.swashR.collectiveSource = selectMenuItem(HELI_PARAM_OFS, y, STR_COLLECTIVE, NULL, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH, attr, event); +#endif + putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.collectiveSource, attr); + break; + + case ITEM_HELI_SWASHRING: + lcd_putsLeft(y, STR_SWASHRING); + lcd_outdezAtt(HELI_PARAM_OFS, y, g_model.swashR.value, LEFT|attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.swashR.value, 100); + break; + + case ITEM_HELI_ELEDIRECTION: + g_model.swashR.invertELE = selectMenuItem(HELI_PARAM_OFS, y, STR_ELEDIRECTION, STR_MMMINV, g_model.swashR.invertELE, 0, 1, attr, event); + break; + + case ITEM_HELI_AILDIRECTION: + g_model.swashR.invertAIL = selectMenuItem(HELI_PARAM_OFS, y, STR_AILDIRECTION, STR_MMMINV, g_model.swashR.invertAIL, 0, 1, attr, event); + break; + + case ITEM_HELI_COLDIRECTION: + g_model.swashR.invertCOL = selectMenuItem(HELI_PARAM_OFS, y, STR_COLDIRECTION, STR_MMMINV, g_model.swashR.invertCOL, 0, 1, attr, event); + break; + } + } +} +#endif + +typedef int16_t (*FnFuncP) (int16_t x); + +int16_t expoFn(int16_t x) +{ + ExpoData *ed = expoAddress(s_currIdx); + int16_t anas[NUM_INPUTS] = {0}; +#if defined(PCBTARANIS) + applyExpos(anas, e_perout_mode_inactive_phase, ed->srcRaw, x); +#else + anas[ed->chn] = x; + applyExpos(anas, e_perout_mode_inactive_phase); +#endif + return anas[ed->chn]; +} + +void DrawFunction(FnFuncP fn, uint8_t offset=0) +{ + lcd_vlineStip(X0-offset, 0, LCD_H, 0xee); + lcd_hlineStip(X0-WCHART-offset, Y0, WCHART*2, 0xee); + + uint8_t prev_yv = 255; + + for (int8_t xv=-WCHART; xv<=WCHART; xv++) { + uint8_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/WCHART))) / 2 * (LCD_H-1) / RESX); + if (prev_yv != 255) { + if (abs((int8_t)yv-prev_yv) <= 1) { + lcd_plot(X0+xv-offset-1, prev_yv, FORCE); + } + else { + uint8_t tmp = (prev_yv < yv ? 0 : 1); + lcd_vline(X0+xv-offset-1, yv+tmp, prev_yv-yv); + } + } + prev_yv = yv; + } +} + +#if defined(CURVES) +static uint8_t s_curveChan; +int16_t curveFn(int16_t x) +{ + return applyCustomCurve(x, s_curveChan); +} + +struct point_t { + uint8_t x; + uint8_t y; +}; + +point_t getPoint(uint8_t i) +{ + point_t result = {0, 0}; +#if defined(PCBTARANIS) + CurveInfo &crv = g_model.curves[s_curveChan]; + int8_t *points = curveAddress(s_curveChan); + bool custom = (crv.type == CURVE_TYPE_CUSTOM); + uint8_t count = 5+crv.points; +#else + CurveInfo crv = curveInfo(s_curveChan); + int8_t *points = crv.crv; + bool custom = crv.custom; + uint8_t count = crv.points; +#endif + if (i < count) { +#if defined(PCBTARANIS) + result.x = X0-1-WCHART+i*WCHART*2/(count-1); +#else + result.x = X0-1-WCHART+i*WCHART/(count/2); +#endif + result.y = (LCD_H-1) - (100 + points[i]) * (LCD_H-1) / 200; + if (custom && i>0 && i g_model.points + sizeof(g_model.points)) { + AUDIO_WARNING2(); + return false; + } + + int8_t *nextCrv = curveAddress(index+1); + memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+curveEnd[MAX_CURVES-1]-curveEnd[index]); + if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift); + while (index NUM_POINTS-5*MAX_CURVES) { + AUDIO_WARNING2(); + return false; + } + + int8_t *crv = curveAddress(index); + if (shift < 0) { + for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); + lcd_putsLeft(3*FH+1, STR_TYPE); + lcd_putsiAtt(INDENT_WIDTH, 4*FH+1, "\010StandardCustom\0", crv.type, attr); + if (attr) { + uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST); + if (newType != crv.type) { + for (int i=1; i<4+crv.points; i++) + points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i*200/(4+crv.points)), s_curveChan)); + moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3+crv.points : -3-crv.points); + if (newType == CURVE_TYPE_CUSTOM) { + for (int i=0; i<3+crv.points; i++) + points[5+crv.points+i] = -100 + ((i+1)*200) / (4+crv.points); + } + crv.type = newType; + } + } + + attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); + lcd_putsLeft(5*FH+1, "Count"); + lcd_outdezAtt(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr); + lcd_putsAtt(lcdLastPos, 6*FH+1, PSTR("pts"), attr); + if (attr) { + int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts + if (checkIncDec_Ret) { + int8_t newPoints[MAX_POINTS]; + newPoints[0] = points[0]; + newPoints[4+count] = points[4+crv.points]; + for (int i=1; i<4+count; i++) + newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + (i*200) / (4+count)), s_curveChan)); + moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM?2:1)); + for (int i=0; i<5+count; i++) { + points[i] = newPoints[i]; + if (crv.type == CURVE_TYPE_CUSTOM && i!=0 && i!=4+count) + points[5+count+i-1] = -100 + (i*200) / (4+count); + } + crv.points = count; + } + } + + lcd_putsLeft(7*FH+1, PSTR("Smooth")); + menu_lcd_onoff(7*FW, 7*FH+1, crv.smooth, m_posVert==3 ? INVERS : 0); + if (m_posVert==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1); + + switch(event) { + case EVT_ENTRY: + pointsOfs = 0; + SET_SCROLLBAR_X(0); + break; + case EVT_KEY_LONG(KEY_ENTER): + if (m_posVert > 1) { + killEvents(event); + MENU_ADD_ITEM(STR_CURVE_PRESET); + MENU_ADD_ITEM(STR_MIRROR); + MENU_ADD_ITEM(STR_CLEAR); + menuHandler = onCurveOneMenu; + } + break; + case EVT_KEY_LONG(KEY_MENU): + pushMenu(menuChannelsView); + killEvents(event); + return; + } + + DrawCurve(FW); + + uint8_t posY = FH+1; + attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); + for (uint8_t i=0; i<5+crv.points; i++) { + point_t point = getPoint(i); + uint8_t selectionMode = 0; + if (crv.type==CURVE_TYPE_CUSTOM) { + if (m_posVert==4+2*i || (i==5+crv.points-1 && m_posVert==4+5+crv.points+5+crv.points-2-1)) + selectionMode = 2; + else if (i>0 && m_posVert==3+2*i) + selectionMode = 1; + } + else if (m_posVert == 4+i) { + selectionMode = 2; + } + + if (i>=pointsOfs && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; + lcd_outdezAtt(6+8*FW, posY, i+1, LEFT); + lcd_outdezAtt(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); + lcd_outdezAtt(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); + posY += FH; + } + + if (selectionMode > 0) { + // do selection square + lcd_filled_rect(point.x-FW-1, point.y-2, 5, 5, SOLID, FORCE); + lcd_filled_rect(point.x-FW, point.y-1, 3, 3, SOLID); + if (s_editMode > 0) { + if (selectionMode == 1) + CHECK_INCDEC_MODELVAR(event, points[5+crv.points+i-1], i==1 ? -100 : points[5+crv.points+i-2], i==5+crv.points-2 ? 100 : points[5+crv.points+i]); // edit X + else if (selectionMode == 2) + CHECK_INCDEC_MODELVAR(event, points[i], -100, 100); + } + if (i < pointsOfs) + pointsOfs = i; + else if (i > pointsOfs+6) + pointsOfs = i-6; + } + } +} +#else +void menuModelCurveOne(uint8_t event) +{ + TITLE(STR_MENUCURVE); + lcd_outdezAtt(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT); + DISPLAY_PROGRESS_BAR(20*FW+1); + + CurveInfo crv = curveInfo(s_curveChan); + + switch(event) { + case EVT_ENTRY: + s_editMode = 1; + break; + CASE_EVT_ROTARY_BREAK + case EVT_KEY_BREAK(KEY_ENTER): + if (s_editMode <= 0) + m_posHorz = 0; + if (s_editMode == 1 && crv.custom) + s_editMode = 2; + else + s_editMode = 1; + break; + case EVT_KEY_LONG(KEY_ENTER): + if (s_editMode <= 0) { + if (int8_t(++m_posHorz) > 4) + m_posHorz = -4; + for (uint8_t i=0; i 0) { + if (--s_editMode == 0) + m_posHorz = 0; + } + else { + popMenu(); + } + break; + + /* CASE_EVT_ROTARY_LEFT */ + case EVT_KEY_REPT(KEY_LEFT): + case EVT_KEY_FIRST(KEY_LEFT): + if (s_editMode==1 && m_posHorz>0) m_posHorz--; + if (s_editMode <= 0) { + if (crv.custom) { + moveCurve(s_curveChan, -crv.points+2); + } + else if (crv.points > MIN_POINTS) { + moveCurve(s_curveChan, -1, (crv.points+1)/2); + } + else { + AUDIO_WARNING2(); + } + return; + } + break; + + /* CASE_EVT_ROTARY_RIGHT */ + case EVT_KEY_REPT(KEY_RIGHT): + case EVT_KEY_FIRST(KEY_RIGHT): + if (s_editMode==1 && m_posHorz<(crv.points-1)) m_posHorz++; + if (s_editMode <= 0) { + if (!crv.custom) { + moveCurve(s_curveChan, crv.points-2, crv.points); + } + else if (crv.points < MAX_POINTS) { + if (moveCurve(s_curveChan, 1)) { + for (int8_t i=crv.points+crv.points-2; i>=0; i--) { + if (i%2) + crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2; + else + crv.crv[i] = crv.crv[i/2]; + } + } + } + else { + AUDIO_WARNING2(); + } + } + break; + } + + lcd_putsLeft(7*FH, STR_TYPE); + uint8_t attr = (s_editMode <= 0 ? INVERS : 0); + lcd_outdezAtt(5*FW-2, 7*FH, crv.points, LEFT|attr); + lcd_putsAtt(lcdLastPos, 7*FH, crv.custom ? PSTR("pt'") : PSTR("pt"), attr); + + DrawCurve(); + + if (s_editMode>0) { + uint8_t i = m_posHorz; + point_t point = getPoint(i); + + if (s_editMode==1 || !BLINK_ON_PHASE) { + // do selection square + lcd_filled_rect(point.x-1, point.y-2, 5, 5, SOLID, FORCE); + lcd_filled_rect(point.x, point.y-1, 3, 3, SOLID); + } + + int8_t x = -100 + 200*i/(crv.points-1); + if (crv.custom && i>0 && i=0; i--) { + ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw); + if (ch != 0) { + count++; + } + } + return count; +} + +bool reachExpoMixCountLimit(uint8_t expo) +{ + // check mixers count limit + if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) { + POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER); + return true; + } + return false; +} + +void deleteExpoMix(uint8_t expo, uint8_t idx) +{ + pauseMixerCalculations(); + if (expo) { + ExpoData *expo = expoAddress(idx); + memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); + } + else { + MixData *mix = mixAddress(idx); + memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData)); + } + resumeMixerCalculations(); + eeDirty(EE_MODEL); +} + +// TODO avoid this global s_currCh on ARM boards ... +int8_t s_currCh; +void insertExpoMix(uint8_t expo, uint8_t idx) +{ + pauseMixerCalculations(); + if (expo) { + ExpoData *expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(expo, sizeof(ExpoData)); +#if defined(PCBTARANIS) + expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); + expo->curve.type = CURVE_REF_EXPO; +#else + expo->mode = 3; // pos&neg +#endif + expo->chn = s_currCh - 1; + expo->weight = 100; + } + else { + MixData *mix = mixAddress(idx); + memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + memclear(mix, sizeof(MixData)); + mix->destCh = s_currCh-1; +#if defined(PCBTARANIS) + mix->srcRaw = s_currCh; + if (!isSourceAvailable(mix->srcRaw)) + mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); +#else + mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); +#endif + mix->weight = 100; + } + resumeMixerCalculations(); + eeDirty(EE_MODEL); +} + +void copyExpoMix(uint8_t expo, uint8_t idx) +{ + pauseMixerCalculations(); + if (expo) { + ExpoData *expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + } + else { + MixData *mix = mixAddress(idx); + memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + } + resumeMixerCalculations(); + eeDirty(EE_MODEL); +} + +void memswap(void *a, void *b, uint8_t size) +{ + uint8_t *x = (uint8_t*)a; + uint8_t *y = (uint8_t*)b; + uint8_t temp ; + + while (size--) { + temp = *x; + *x++ = *y; + *y++ = temp; + } +} + +bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up) +{ + void *x, *y; + uint8_t size; + int8_t tgt_idx = (up ? idx-1 : idx+1); + + if (expo) { + x = (ExpoData *)expoAddress(idx); + + if (tgt_idx < 0) { + if (((ExpoData *)x)->chn == 0) + return false; + ((ExpoData *)x)->chn--; + return true; + } + + if (tgt_idx == MAX_EXPOS) { + if (((ExpoData *)x)->chn == NUM_STICKS-1) + return false; + ((ExpoData *)x)->chn++; + return true; + } + + y = (ExpoData *)expoAddress(tgt_idx); + if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) { + if (up) { + if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--; + else return false; + } + else { + if (((ExpoData *)x)->chnchn++; + else return false; + } + return true; + } + + size = sizeof(ExpoData); + } + else { + x = (MixData *)mixAddress(idx); + + if (tgt_idx < 0) { + if (((MixData *)x)->destCh == 0) + return false; + ((MixData *)x)->destCh--; + return true; + } + + if (tgt_idx == MAX_MIXERS) { + if (((MixData *)x)->destCh == NUM_CHNOUT-1) + return false; + ((MixData *)x)->destCh++; + return true; + } + + y = (MixData *)mixAddress(tgt_idx); + uint8_t destCh = ((MixData *)x)->destCh; + if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) { + if (up) { + if (destCh>0) ((MixData *)x)->destCh--; + else return false; + } + else { + if (destChdestCh++; + else return false; + } + return true; + } + + size = sizeof(MixData); + } + + pauseMixerCalculations(); + memswap(x, y, size); + resumeMixerCalculations(); + + idx = tgt_idx; + return true; +} + +enum ExposFields { + CASE_PCBTARANIS(EXPO_FIELD_INPUT_NAME) + IF_CPUARM(EXPO_FIELD_NAME) + CASE_PCBTARANIS(EXPO_FIELD_SOURCE) + CASE_PCBTARANIS(EXPO_FIELD_SCALE) + EXPO_FIELD_WEIGHT, + CASE_PCBTARANIS(EXPO_FIELD_OFFSET) + CASE_9X(EXPO_FIELD_EXPO) + IF_CURVES(EXPO_FIELD_CURVE) + IF_FLIGHT_MODES(EXPO_FIELD_FLIGHT_PHASE) + EXPO_FIELD_SWITCH, + CASE_9X(EXPO_FIELD_SIDE) + CASE_PCBTARANIS(EXPO_FIELD_TRIM) + EXPO_FIELD_MAX +}; + +#if defined(PCBTARANIS) + #define CURVE_ROWS 1 +#else + #define CURVE_ROWS 0 +#endif + +void menuModelExpoOne(uint8_t event) +{ +#if defined(PCBTARANIS) + if (event == EVT_KEY_LONG(KEY_MENU)) { + pushMenu(menuChannelsView); + killEvents(event); + return; + } +#endif + + ExpoData *ed = expoAddress(s_currIdx); +#if defined(PCBTARANIS) + putsMixerSource(7*FW+FW/2, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); +#else + putsMixerSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0); +#endif + + SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {CASE_PCBTARANIS(0) IF_CPUARM(0) CASE_PCBTARANIS(0) CASE_PCBTARANIS((ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW)) 0, CASE_PCBTARANIS(0) CASE_9X(0) IF_CURVES(CURVE_ROWS) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); + + SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); + + int8_t sub = m_posVert; + + uint8_t y = FH+1; + +#if defined(PCBTARANIS) + for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); + switch(i) + { +#if defined(PCBTARANIS) + case EXPO_FIELD_INPUT_NAME: + editSingleName(EXPO_ONE_2ND_COLUMN, y, "Input Name", g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); + break; +#endif + +#if defined(CPUARM) + case EXPO_FIELD_NAME: + editSingleName(EXPO_ONE_2ND_COLUMN-IF_9X(sizeof(ed->name)*FW), y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); + break; +#endif + +#if defined(PCBTARANIS) + case EXPO_FIELD_SOURCE: + lcd_putsLeft(y, NO_INDENT(STR_SOURCE)); + putsMixerSource(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); + break; + + case EXPO_FIELD_SCALE: + lcd_putsLeft(y, STR_SCALE); + putsTelemetryChannel(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw - MIXSRC_FIRST_TELEM, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr); + if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL, NULL); + break; +#endif + + case EXPO_FIELD_WEIGHT: + lcd_putsLeft(y, STR_WEIGHT); + ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, IF_PCBTARANIS(LEFT)|attr, 0, event); + break; + +#if defined(PCBTARANIS) + case EXPO_FIELD_OFFSET: + lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); + ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); + break; +#endif + +#if !defined(PCBTARANIS) + case EXPO_FIELD_EXPO: + lcd_putsLeft(y, STR_EXPO); + if (ed->curveMode==MODE_EXPO || ed->curveParam==0) { + ed->curveMode = MODE_EXPO; + ed->curveParam = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, 0, event); + } + else { + lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); + } + break; +#endif + +#if defined(CURVES) + case EXPO_FIELD_CURVE: + lcd_putsLeft(y, STR_CURVE); +#if defined(PCBTARANIS) + editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); +#else + if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) { + putsCurve(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr); + if (attr) { + CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1); + if (ed->curveParam) ed->curveMode = MODE_CURVE; + if (ed->curveParam>=CURVE_BASE && event==EVT_KEY_LONG(KEY_ENTER)) { + s_curveChan = ed->curveParam - CURVE_BASE; + pushMenu(menuModelCurveOne); + } + } + } + else { + lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); + } +#endif + break; +#endif + +#if defined(FLIGHT_MODES) + case EXPO_FIELD_FLIGHT_PHASE: + ed->phases = editFlightModes(EXPO_ONE_2ND_COLUMN-IF_9X(EXPO_ONE_FP_WIDTH), y, event, ed->phases, attr); + break; +#endif + + case EXPO_FIELD_SWITCH: + ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN-IF_9X(3*FW), y, ed->swtch, attr, event); + break; + +#if !defined(PCBTARANIS) + case EXPO_FIELD_SIDE: + ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); + break; +#endif + +#if defined(PCBTARANIS) + case EXPO_FIELD_TRIM: + uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); + int8_t carryTrim = -ed->carryTrim; + lcd_putsLeft(y, STR_TRIM); + lcd_putsiAtt(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); + if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); + break; +#endif + } + y += FH; + } + + DrawFunction(expoFn); + +#if defined(PCBTARANIS) + int x512 = getValue(ed->srcRaw); + if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannel(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x512, 0); + if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); + x512 = limit(-1024, x512, 1024); + } + else { + lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); + } + int y512 = expoFn(x512); + lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); +#else + int16_t x512 = calibratedStick[ed->chn]; + lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto100(x512), 0); + int16_t y512 = expoFn(x512); + lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0); +#endif + + x512 = X0+x512/(RESXu/WCHART); +#if defined(CPUARM) + y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; +#else + y512 = (LCD_H-1) - (uint16_t)((y512+RESX)/2) * (LCD_H-1) / RESX; +#endif + + lcd_vline(x512, y512-3, 3*2+1); + lcd_hline(x512-3, y512, 3*2+1); +} + +enum MixFields { + IF_CPUARM(MIX_FIELD_NAME) + MIX_FIELD_SOURCE, + MIX_FIELD_WEIGHT, + MIX_FIELD_OFFSET, + CASE_9X(MIX_FIELD_TRIM) + IF_CURVES(MIX_FIELD_CURVE) + IF_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE) + MIX_FIELD_SWITCH, + MIX_FIELD_WARNING, + MIX_FIELD_MLTPX, + MIX_FIELD_DELAY_UP, + MIX_FIELD_DELAY_DOWN, + MIX_FIELD_SLOW_UP, + MIX_FIELD_SLOW_DOWN, + MIX_FIELD_COUNT +}; + +void gvarWeightItem(xcoord_t x, uint8_t y, MixData *md, uint8_t attr, uint8_t event) +{ + u_int8int16_t weight; + MD_WEIGHT_TO_UNION(md, weight); + weight.word = GVAR_MENU_ITEM(x, y, weight.word, -500, 500, attr, 0, event); + MD_UNION_TO_WEIGHT(weight, md); +} + +void menuModelMixOne(uint8_t event) +{ +#if defined(PCBTARANIS) + if (event == EVT_KEY_LONG(KEY_MENU)) { + pushMenu(menuChannelsView); + killEvents(event); + return; + } +#endif + + TITLE(s_currCh ? STR_INSERTMIX : STR_EDITMIX); + MixData *md2 = mixAddress(s_currIdx) ; + putsChn(lcdLastPos+1*FW, 0, md2->destCh+1,0); + +#if defined(ROTARY_ENCODERS) +#if defined(CURVES) + if ((m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) || (m_posVert == MIX_FIELD_CURVE && md2->curveMode == MODE_CURVE)) +#else + if (m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) +#endif + SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(0) IF_CURVES(0) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}) + else + SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); +#else + SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); +#endif + +#if MENU_COLUMNS > 1 + lcd_vline(MENU_COLUMN2_X-4, FH+1, LCD_H-FH-1); +#endif + + int8_t sub = m_posVert; + int8_t editMode = s_editMode; + + for (uint8_t k=0; k 1 + uint8_t y; + uint8_t COLUMN_X; + if (k >= LCD_LINES-1) { + y = 1 + (k-LCD_LINES+2)*FH; + COLUMN_X = MENU_COLUMN2_X; + } + else { + y = 1 + (k+1)*FH; + COLUMN_X = 0; + } + int8_t i = k; +#else + uint8_t y = 1 + (k+1)*FH; + int8_t i = k + s_pgOfs; +#endif + + uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); + switch(i) { +#if defined(CPUARM) + case MIX_FIELD_NAME: + editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr); + break; +#endif + case MIX_FIELD_SOURCE: + lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_SOURCE)); + putsMixerSource(COLUMN_X+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); + if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); + break; + case MIX_FIELD_WEIGHT: + lcd_putsColumnLeft(COLUMN_X, y, STR_WEIGHT); + gvarWeightItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); + break; + case MIX_FIELD_OFFSET: + { + lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_OFFSET)); + u_int8int16_t offset; + MD_OFFSET_TO_UNION(md2, offset); + offset.word = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_NEG, GV_RANGELARGE, attr|LEFT, 0, event); + MD_UNION_TO_OFFSET(offset, md2); + break; + } + +#if !defined(PCBTARANIS) + case MIX_FIELD_TRIM: + { + uint8_t not_stick = (md2->srcRaw > NUM_STICKS); + int8_t carryTrim = -md2->carryTrim; + lcd_putsColumnLeft(COLUMN_X, y, STR_TRIM); +#if LCD_W >= 212 && defined(TRANSLATIONS_FR) + lcd_putsiAtt((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+11*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); +#else + lcd_putsiAtt((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+6*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); +#endif + if (attr && m_posHorz==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); + if (!not_stick) { + lcd_puts(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX); + menu_lcd_onoff(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, !md2->noExpo, m_posHorz==1 ? attr : 0); + if (attr && m_posHorz==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1); + } + else if (attr) { + REPEAT_LAST_CURSOR_MOVE(); + } + break; + } +#endif + +#if defined(CURVES) + case MIX_FIELD_CURVE: + { + lcd_putsColumnLeft(COLUMN_X, y, STR_CURVE); +#if defined(PCBTARANIS) + editCurveRef(COLUMN_X+MIXES_2ND_COLUMN, y, md2->curve, event, attr); +#else + int8_t curveParam = md2->curveParam; + if (md2->curveMode == MODE_CURVE) { + putsCurve(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr); + if (attr) { + if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){ + s_curveChan = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE); + pushMenu(menuModelCurveOne); + } + else { + CHECK_INCDEC_MODELVAR(event, md2->curveParam, -MAX_CURVES, CURVE_BASE+MAX_CURVES-1); + if (md2->curveParam == 0) + md2->curveMode = MODE_DIFFERENTIAL; +#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) + MOVE_CURSOR_FROM_HERE(); +#else + m_posHorz = 0; +#endif + } + } + } + else { + lcd_putsAtt(COLUMN_X+MIXES_2ND_COLUMN, y, PSTR("Diff"), m_posHorz==0 ? attr : 0); + md2->curveParam = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, curveParam, -100, 100, LEFT|(m_posHorz==1 ? attr : 0), 0, editMode>0 ? event : 0); + if (attr && editMode>0 && m_posHorz==0) { + int8_t tmp = 0; + CHECK_INCDEC_MODELVAR(event, tmp, -1, 1); + if (tmp != 0) { + md2->curveMode = MODE_CURVE; + md2->curveParam = tmp; + } + } + } +#endif + break; + } +#endif +#if defined(FLIGHT_MODES) + case MIX_FIELD_FLIGHT_PHASE: + md2->phases = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->phases, attr); + break; +#endif + case MIX_FIELD_SWITCH: + md2->swtch = switchMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event); + break; + case MIX_FIELD_WARNING: + lcd_putsColumnLeft(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING); + if (md2->mixWarn) + lcd_outdezAtt(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT); + else + lcd_putsAtt(COLUMN_X+MIXES_2ND_COLUMN, y, STR_OFF, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3); + break; + case MIX_FIELD_MLTPX: + md2->mltpx = selectMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event); + break; + case MIX_FIELD_DELAY_UP: + md2->delayUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYUP, md2->delayUp); + break; + case MIX_FIELD_DELAY_DOWN: + md2->delayDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYDOWN, md2->delayDown); + break; + case MIX_FIELD_SLOW_UP: + md2->speedUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWUP, md2->speedUp); + break; + case MIX_FIELD_SLOW_DOWN: + md2->speedDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWDOWN, md2->speedDown); + break; + } + } +} + +static uint8_t s_maxLines = 8; +static uint8_t s_copySrcIdx; +static uint8_t s_copySrcCh; + +#define _STR_MAX(x) PSTR("/" #x) +#define STR_MAX(x) _STR_MAX(x) + +#define MIX_LINE_SRC_POS 4*FW-1 + +#if LCD_W >= 212 + #define EXPO_LINE_WEIGHT_POS 8*FW+1 + #define EXPO_LINE_SRC_POS 9*FW-2 + #define EXPO_LINE_CURVE_POS 12*FW+4 + #define EXPO_LINE_SWITCH_POS 17*FW-1 + #define EXPO_LINE_SELECT_POS 5*FW+2 + #define EXPO_LINE_FM_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH-FW-1 + #define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH + #define MIX_LINE_WEIGHT_POS 11*FW+5 + #define MIX_LINE_CURVE_POS 12*FW+4 + #define MIX_LINE_SWITCH_POS 16*FW+1 + #define MIX_LINE_DELAY_POS 19*FW+2 +#elif defined(CPUARM) + #define EXPO_LINE_WEIGHT_POS 7*FW-1 + #define EXPO_LINE_EXPO_POS 10*FW+5 + #define EXPO_LINE_SWITCH_POS 11*FW+2 + #define EXPO_LINE_SIDE_POS 14*FW+2 + #define EXPO_LINE_SELECT_POS 24 + #define EXPO_LINE_FM_POS + #define EXPO_LINE_NAME_POS LCD_W-sizeof(ed->name)*FW-MENUS_SCROLLBAR_WIDTH + #define MIX_LINE_WEIGHT_POS 11*FW+3 + #define MIX_LINE_CURVE_POS 12*FW+2 + #define MIX_LINE_SWITCH_POS 16*FW + #define MIX_LINE_DELAY_POS 19*FW+7 +#else + #define EXPO_LINE_WEIGHT_POS 7*FW-1 + #define EXPO_LINE_EXPO_POS 11*FW + #define EXPO_LINE_SWITCH_POS 11*FW+4 + #if MAX_PHASES == 6 + #define EXPO_LINE_SIDE_POS 15*FW + #else + #define EXPO_LINE_SIDE_POS 15*FW+2 + #endif + #define EXPO_LINE_FM_POS LCD_W-FW-MENUS_SCROLLBAR_WIDTH + #define EXPO_LINE_SELECT_POS 24 + #define MIX_LINE_WEIGHT_POS 11*FW+3 + #define MIX_LINE_CURVE_POS 12*FW+2 + #define MIX_LINE_SWITCH_POS 16*FW + #define MIX_LINE_DELAY_POS 19*FW+7 +#endif + +#if defined(NAVIGATION_MENUS) +void onExpoMixMenu(const char *result) +{ + bool expo = (g_menuStack[g_menuStackPtr] == menuModelExposAll); + uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); + + if (result == STR_EDIT) { + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + } + else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { + if (!reachExpoMixCountLimit(expo)) { + s_currCh = chn; + if (result == STR_INSERT_AFTER) { s_currIdx++; m_posVert++; } + insertExpoMix(expo, s_currIdx); + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + } + } + else if (result == STR_COPY || result == STR_MOVE) { + s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE); + s_copySrcIdx = s_currIdx; + s_copySrcCh = chn; + s_copySrcRow = m_posVert; + } + else if (result == STR_DELETE) { + deleteExpoMix(expo, s_currIdx); + } +} +#endif + +#if LCD_W >= 212 +void displayHeaderChannelName(uint8_t ch) +{ + uint8_t len = zlen(g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name)); + if (len) { + lcd_putc(17*FW, 0, ' '); + lcd_putsnAtt(18*FW, 0, g_model.limitData[ch-1].name, len, ZCHAR); + lcd_putc(18*FW+len*FW, 0, ' '); + } +} +#endif + +void menuModelExpoMix(uint8_t expo, uint8_t event) +{ + uint8_t sub = m_posVert; + + if (s_editMode > 0) + s_editMode = 0; + + uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); + + switch (event) + { + case EVT_ENTRY: + case EVT_ENTRY_UP: + s_copyMode = 0; + s_copyTgtOfs = 0; + break; + case EVT_KEY_LONG(KEY_EXIT): + if (s_copyMode && s_copyTgtOfs == 0) { + deleteExpoMix(expo, s_currIdx); + killEvents(event); + event = 0; + } + // no break +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LONG: + if (s_copyMode) { + killEvents(event); + } +#endif + case EVT_KEY_BREAK(KEY_EXIT): + if (s_copyMode) { + if (s_copyTgtOfs) { + // cancel the current copy / move operation + if (s_copyMode == COPY_MODE) { + deleteExpoMix(expo, s_currIdx); + } + else { + do { + swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0); + s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); + } while (s_copyTgtOfs != 0); + eeDirty(EE_MODEL); + } + m_posVert = s_copySrcRow; + s_copyTgtOfs = 0; + } + s_copyMode = 0; + event = 0; + } + break; + case EVT_KEY_BREAK(KEY_ENTER): + if (sub != 0 && (!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) { + s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); + s_copySrcIdx = s_currIdx; + s_copySrcCh = chn; + s_copySrcRow = sub; + break; + } + // no break + + CASE_EVT_ROTARY_BREAK + case EVT_KEY_LONG(KEY_ENTER): + killEvents(event); + if (s_copyTgtOfs) { + s_copyMode = 0; + s_copyTgtOfs = 0; + } + else if (sub != 0) { + if (READ_ONLY()) { + if (!s_currCh) { + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + return; + } + } + else { + if (s_copyMode) s_currCh = 0; +#if defined(NAVIGATION_MENUS) + if (s_currCh) { + if (reachExpoMixCountLimit(expo)) break; + insertExpoMix(expo, s_currIdx); + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + s_copyMode = 0; + return; + } + else { + event = 0; + s_copyMode = 0; + MENU_ADD_ITEM(STR_EDIT); + MENU_ADD_ITEM(STR_INSERT_BEFORE); + MENU_ADD_ITEM(STR_INSERT_AFTER); + MENU_ADD_ITEM(STR_COPY); + MENU_ADD_ITEM(STR_MOVE); + MENU_ADD_ITEM(STR_DELETE); + menuHandler = onExpoMixMenu; + } +#else + if (s_currCh) { + if (reachExpoMixCountLimit(expo)) break; + insertExpoMix(expo, s_currIdx); + } + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + s_copyMode = 0; + return; +#endif + } + } + break; + case EVT_KEY_LONG(KEY_LEFT): + case EVT_KEY_LONG(KEY_RIGHT): + if (s_copyMode && !s_copyTgtOfs) { + if (reachExpoMixCountLimit(expo)) break; + s_currCh = chn; + if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; m_posVert++; } + insertExpoMix(expo, s_currIdx); + pushMenu(expo ? menuModelExpoOne : menuModelMixOne); + s_copyMode = 0; + killEvents(event); + return; + } + break; +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_LEFT: + case EVT_ROTARY_RIGHT: +#endif + case EVT_KEY_FIRST(KEY_MOVE_UP): + case EVT_KEY_REPT(KEY_MOVE_UP): + case EVT_KEY_FIRST(KEY_MOVE_DOWN): + case EVT_KEY_REPT(KEY_MOVE_DOWN): + if (s_copyMode) { + uint8_t key = (event & 0x1f); + uint8_t next_ofs = ((IS_ROTARY_UP(event) || key==KEY_MOVE_UP) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1); + + if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) { + // insert a mix on the same channel (just above / just below) + if (reachExpoMixCountLimit(expo)) break; + copyExpoMix(expo, s_currIdx); + if (IS_ROTARY_DOWN(event) || key==KEY_MOVE_DOWN) s_currIdx++; + else if (sub-s_pgOfs >= 6) s_pgOfs++; + } + else if (next_ofs==0 && s_copyMode==COPY_MODE) { + // delete the mix + deleteExpoMix(expo, s_currIdx); + if (IS_ROTARY_UP(event) || key==KEY_MOVE_UP) s_currIdx--; + } + else { + // only swap the mix with its neighbor + if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_UP(event) || key==KEY_MOVE_UP)) break; + eeDirty(EE_MODEL); + } + + s_copyTgtOfs = next_ofs; + } + break; + } + + lcd_outdezAtt(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, getExpoMixCount(expo)); + lcd_puts(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS)); + SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, s_maxLines); + + sub = m_posVert; + s_currCh = 0; + uint8_t cur = 1; + uint8_t i = 0; + + for (uint8_t ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { + void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; + uint8_t y = 1+(cur-s_pgOfs)*FH; + if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { + if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { + if (expo) { +#if defined(PCBTARANIS) + putsMixerSource(0, y, ch, 0); +#else + putsMixerSource(0, y, MIXSRC_Rud+ch-1, 0); +#endif + } + else { + putsChn(0, y, ch, 0); // show CHx + } + } + uint8_t mixCnt = 0; + do { + if (s_copyMode) { + if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < 8 && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lcd_rect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED); + cur++; y+=FH; + } + if (s_currIdx == i) { + sub = m_posVert = cur; + s_currCh = ch; + } + } + else if (sub == cur) { + s_currIdx = i; + } + if (s_pgOfs < cur && cur-s_pgOfs < 8) { + uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); + if (expo) { + ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event); + +#if defined(PCBTARANIS) + putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0); +#endif + +#if defined(PCBTARANIS) + putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0); +#else + if (ed->curveMode == MODE_CURVE) + putsCurve(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam); + else + displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100); +#endif + + putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); + +#if !defined(PCBTARANIS) + if (ed->mode!=3) lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); +#endif + +#if defined(CPUARM) && LCD_W >= 212 + displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); + if (ed->name[0]) lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); +#elif defined(CPUARM) + if (ed->name[0]) lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); +#else + displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); +#endif + } + else { +#if LCD_W >= 212 + if (attr) { + displayHeaderChannelName(ch); + } +#endif + + if (mixCnt > 0) lcd_putsiAtt(FW, y, STR_VMLTPX2, md->mltpx, 0); + + putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, isMixActive(i) ? BOLD : 0); + + gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr, event); + +#if LCD_W >= 212 + displayFlightModes(EXPO_LINE_FM_POS, y, md->phases); +#endif + +#if defined(CPUARM) + if (md->name[0]) { + lcd_putsnAtt(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR | (isMixActive(i) ? BOLD : 0)); + } +#if LCD_W < 212 + else +#endif +#endif + { +#if defined(PCBTARANIS) +#else + if (md->curveParam) { + if (md->curveMode == MODE_CURVE) + putsCurve(MIX_LINE_CURVE_POS, y, md->curveParam); + else + displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100); + } +#endif + if (md->swtch) putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); + + char cs = ' '; + if (md->speedDown || md->speedUp) + cs = 'S'; + if ((md->delayUp || md->delayDown)) + cs = (cs =='S' ? '*' : 'D'); + lcd_putc(MIX_LINE_DELAY_POS, y, cs); + } + } + if (s_copyMode) { + if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + /* draw a border around the raw on selection mode (copy/move) */ + lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); + } + if (cur == sub) { + /* invert the raw when it's the current one */ + lcd_filled_rect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7); + } + } + } + cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++; + } while (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)); + if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED); + cur++; y+=FH; + } + } + else { + uint8_t attr = 0; + if (sub == cur) { + s_currIdx = i; + s_currCh = ch; + if (!s_copyMode) { + attr = INVERS; + } + } + if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { + if (expo) { +#if defined(PCBTARANIS) + putsMixerSource(0, y, ch, attr); +#else + putsMixerSource(0, y, MIXSRC_Rud+ch-1, attr); +#endif + } + else { + putsChn(0, y, ch, attr); // show CHx +#if LCD_W >= 212 + if (attr) { + displayHeaderChannelName(ch); + } +#endif + } + if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { + lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED); + } + } + cur++; y+=FH; + } + } + s_maxLines = cur; + if (sub >= s_maxLines-1) m_posVert = s_maxLines-1; +} + +void menuModelExposAll(uint8_t event) +{ + return menuModelExpoMix(1, event); +} + +void menuModelMixAll(uint8_t event) +{ + return menuModelExpoMix(0, event); +} + +bool thrOutput(uint8_t ch) +{ + for (uint8_t i=0; idestCh==ch && mix->srcRaw==MIXSRC_Thr) + return true; + } + return false; +} + +enum LimitsItems { +#if defined(PCBTARANIS) + ITEM_LIMITS_CH_NAME, +#endif + ITEM_LIMITS_OFFSET, + ITEM_LIMITS_MIN, + ITEM_LIMITS_MAX, + ITEM_LIMITS_DIRECTION, +#if defined(PCBTARANIS) && defined(CURVES) + ITEM_LIMITS_CURVE, +#endif +#if defined(PPM_CENTER_ADJUSTABLE) + ITEM_LIMITS_PPM_CENTER, +#endif +#if defined(PPM_LIMITS_SYMETRICAL) + ITEM_LIMITS_SYMETRICAL, +#endif + ITEM_LIMITS_COUNT, + ITEM_LIMITS_MAXROW = ITEM_LIMITS_COUNT-1 +}; + +#if defined(PCBTARANIS) + #define LIMITS_NAME_POS 4*FW + #define LIMITS_OFFSET_POS 14*FW+4 + #define LIMITS_MIN_POS 20*FW-3 + #if defined(PPM_CENTER_ADJUSTABLE) + #define LIMITS_DIRECTION_POS 20*FW-3 + #define LIMITS_MAX_POS 24*FW+2 + #define LIMITS_REVERT_POS 25*FW-1 + #define LIMITS_CURVE_POS 27*FW-1 + #define LIMITS_PPM_CENTER_POS 34*FW + #else + #define LIMITS_DIRECTION_POS 21*FW + #define LIMITS_MAX_POS 26*FW + #define LIMITS_REVERT_POS 27*FW + #define LIMITS_CURVE_POS 32*FW + #endif +#else + #if defined(PPM_UNIT_US) + #define LIMITS_MIN_POS 12*FW+1 + #else + #define LIMITS_MIN_POS 12*FW + #endif + #define LIMITS_OFFSET_POS 8*FW + #if defined(PPM_LIMITS_SYMETRICAL) + #if defined(PPM_CENTER_ADJUSTABLE) + #define LIMITS_MAX_POS 15*FW + #define LIMITS_REVERT_POS 16*FW-3 + #define LIMITS_PPM_CENTER_POS 20*FW+1 + #else + #define LIMITS_DIRECTION_POS 12*FW+4 + #define LIMITS_MAX_POS 16*FW+4 + #define LIMITS_REVERT_POS 17*FW + #endif + #else + #if defined(PPM_CENTER_ADJUSTABLE) + #define LIMITS_MAX_POS 16*FW + #define LIMITS_REVERT_POS 17*FW-2 + #define LIMITS_PPM_CENTER_POS 21*FW+2 + #else + #define LIMITS_MAX_POS 17*FW + #define LIMITS_REVERT_POS 18*FW + #define LIMITS_DIRECTION_POS 12*FW+5 + #endif + #endif +#endif + +#if defined(CPUARM) + #define LIMITS_MIN_MAX_OFFSET 1000 + #define CONVERT_US_MIN_MAX(x) (((x)*128)/250) + #define MIN_MAX_LIMIT (10*limit) + #define MIN_MAX_ATTR attr|PREC1 +#else + #define LIMITS_MIN_MAX_OFFSET 100 + #define CONVERT_US_MIN_MAX(x) ((int16_t(x)*128)/25) + #define MIN_MAX_LIMIT (limit) + #define MIN_MAX_ATTR attr +#endif + +#if defined(PPM_UNIT_US) + #define MIN_MAX_DISPLAY(x) CONVERT_US_MIN_MAX(x) + #undef MIN_MAX_ATTR + #define MIN_MAX_ATTR attr +#else + #define MIN_MAX_DISPLAY(x) (x) +#endif + +#if defined(PCBTARANIS) +void onLimitsMenu(const char *result) +{ + uint8_t ch = m_posVert - 1; + + if (result == STR_RESET) { + LimitData *ld = limitAddress(ch); + ld->min = 0; + ld->max = 0; + ld->offset = 0; + ld->ppmCenter = 0; + ld->revert = false; + ld->curve = 0; + } + else if (result == STR_COPY_TRIMS_TO_OFFSET) { + copyTrimsToOffset(ch); + } +} +#endif + +void menuModelLimits(uint8_t event) +{ + uint8_t sub = m_posVert - 1; + + if (sub < NUM_CHNOUT) { +#if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US) + lcd_outdezAtt(13*FW, 0, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, 0); + lcd_puts(13*FW, 0, STR_US); +#else + lcd_outdezAtt(13*FW, 0, calcRESXto1000(channelOutputs[sub]), PREC1); +#endif + } + +#if defined(CPUARM) + MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, 0}); +#else + MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, 0}); +#endif + +#if LCD_W >= 212 + if (sub=0) { + displayColumnHeader(STR_LIMITS_HEADERS, m_posHorz); + } +#endif + + if (s_warning_result) { + s_warning_result = 0; + LimitData *ld = limitAddress(sub); + ld->revert = !ld->revert; + eeDirty(EE_MODEL); + } + + for (uint8_t i=0; i= 212 || !defined(PPM_CENTER_ADJUSTABLE) + int16_t v = (ld->revert) ? -ld->offset : ld->offset; + char swVal = '-'; // '-', '<', '>' + if((channelOutputs[k] - v) > 50) swVal = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim! + if((channelOutputs[k] - v) < -50) swVal = (ld->revert ? 126 : 127); + putsChn(0, y, k+1, 0); + lcd_putc(LIMITS_DIRECTION_POS, y, swVal); +#endif + +#if defined(PPM_CENTER_ADJUSTABLE) + int8_t limit = ((g_model.extendedLimits && !limitAddress(k)->ppmCenter) ? 125 : 100); +#else + int8_t limit = (g_model.extendedLimits ? 125 : 100); +#endif + +#if defined(PCBTARANIS) + putsChn(0, y, k+1, (sub==k && m_posHorz < 0) ? INVERS : 0); + if (sub==k && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + MENU_ADD_ITEM(STR_RESET); + MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFFSET); + menuHandler = onLimitsMenu; + } +#else + putsChn(0, y, k+1, 0); +#endif + + for (uint8_t j=0; j0) ? BLINK|INVERS : INVERS) : 0); + uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; + if (active) STICK_SCROLL_DISABLE(); + switch(j) + { +#if defined(PCBTARANIS) + case ITEM_LIMITS_CH_NAME: + editName(LIMITS_NAME_POS, y, ld->name, sizeof(ld->name), event, attr); + break; +#endif + + case ITEM_LIMITS_OFFSET: +#if defined(PCBTARANIS) + ld->offset = GVAR_MENU_ITEM(LIMITS_OFFSET_POS, y, MIN_MAX_DISPLAY(ld->offset), -1000, 1000, attr|PREC1, 0, event); +#else + #if defined(PPM_UNIT_US) + lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1); + #else + lcd_outdezAtt(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1); + #endif + if (active) { + ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL|NO_INCDEC_MARKS); + } + else if (attr && event==EVT_KEY_LONG(KEY_MENU)) { + copyTrimsToOffset(k); + s_editMode = 0; + } +#endif + break; + + case ITEM_LIMITS_MIN: +#if defined(CPUARM) + ld->min = LIMITS_MIN_MAX_OFFSET + GVAR_MENU_ITEM(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), -MIN_MAX_LIMIT, 0, MIN_MAX_ATTR, DBLKEYS_1000, event); +#else + lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); + if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDecModel(event, ld->min-LIMITS_MIN_MAX_OFFSET, -MIN_MAX_LIMIT, 0); +#endif + break; + + case ITEM_LIMITS_MAX: +#if defined(CPUARM) + ld->max = -LIMITS_MIN_MAX_OFFSET + GVAR_MENU_ITEM(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), 0, MIN_MAX_LIMIT, MIN_MAX_ATTR, DBLKEYS_1000, event); +#else + lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); + if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDecModelZero(event, ld->max+LIMITS_MIN_MAX_OFFSET, +MIN_MAX_LIMIT); +#endif + break; + + case ITEM_LIMITS_DIRECTION: + { + uint8_t revert = ld->revert; +#if defined(PPM_CENTER_ADJUSTABLE) + lcd_putcAtt(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr); +#else + lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr); +#endif + if (active) { + uint8_t revert_new = checkIncDecModel(event, revert, 0, 1); + if (checkIncDec_Ret && thrOutput(k)) { + POPUP_CONFIRMATION(STR_INVERT_THR); + } + else { + ld->revert = revert_new; + } + } + break; + } + +#if defined(PCBTARANIS) && defined(CURVES) + case ITEM_LIMITS_CURVE: + putsCurve(LIMITS_CURVE_POS, y, ld->curve, attr); + if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) { + s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1); + pushMenu(menuModelCurveOne); + } + if (active) { + CHECK_INCDEC_MODELVAR(event, ld->curve, -MAX_CURVES, +MAX_CURVES); + } + break; +#endif + +#if defined(PPM_CENTER_ADJUSTABLE) + case ITEM_LIMITS_PPM_CENTER: + lcd_outdezAtt(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr); +#pragma message("could be less restrictive!") + if (active && ld->max <= 0 && ld->min >= 0) { + CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -125, +125); + } + break; +#endif + +#if defined(PPM_LIMITS_SYMETRICAL) + case ITEM_LIMITS_SYMETRICAL: + lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '^', attr); + if (active) { + CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1); + } + break; +#endif + } + } + } +} + +#if defined(CURVES) + +#if defined(GVARS) + #define CURVE_SELECTED() (sub >= 0 && sub < MAX_CURVES) + #define GVAR_SELECTED() (sub >= MAX_CURVES) +#else + #define CURVE_SELECTED() (sub >= 0) +#endif + +void menuModelCurvesAll(uint8_t event) +{ +#if defined(GVARS) && defined(PCBSTD) + SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES+MAX_GVARS); +#else + SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES); +#endif + + int8_t sub = m_posVert - 1; + + switch (event) { +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_BREAK: +#endif +#if defined(PCBTARANIS) + case EVT_KEY_BREAK(KEY_ENTER): +#else + case EVT_KEY_FIRST(KEY_RIGHT): + case EVT_KEY_FIRST(KEY_ENTER): +#endif + if (CURVE_SELECTED() && !READ_ONLY()) { + s_curveChan = sub; + pushMenu(menuModelCurveOne); + } + break; + } + + for (uint8_t i=0; i= MAX_CURVES) { + putsStrIdx(0, y, STR_GV, k-MAX_CURVES+1); + if (GVAR_SELECTED()) { + if (attr && s_editMode>0) attr |= BLINK; + lcd_outdezAtt(10*FW, y, GVAR_VALUE(k-MAX_CURVES, -1), attr); + if (attr) g_model.gvars[k-MAX_CURVES] = checkIncDec(event, g_model.gvars[k-MAX_CURVES], -1000, 1000, EE_MODEL); + } + } + else +#endif + { + putsStrIdx(0, y, STR_CV, k+1, attr); +#if defined(PCBTARANIS) + editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); + CurveInfo & crv = g_model.curves[k]; + lcd_outdezAtt(11*FW, y, 5+crv.points, LEFT); + lcd_putsAtt(lcdLastPos, y, PSTR("pts"), 0); +#endif + } + } + + if (CURVE_SELECTED()) { + s_curveChan = sub; + DrawCurve(23); + } +} +#endif + +#if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) + +void onGVARSMenu(const char *result) +{ + int8_t sub = m_posVert - 1; + + if (result == STR_ENABLE_POPUP) { + g_model.gvars[sub].popup = true; + eeDirty(EE_MODEL); + } + else if (result == STR_DISABLE_POPUP) { + g_model.gvars[sub].popup = false; + eeDirty(EE_MODEL); + } + else if (result == STR_CLEAR) { + for (int i=0; i 6 + for (uint8_t l=0; l0) ? BLINK|INVERS : INVERS) : 0); + xcoord_t x = 12*FW + FWNUM + (j-1)*(2+3*FWNUM) - 3; + +#if MAX_GVARS == 6 + if (i==0 && j!=9) putsStrIdx(x+2, FH+1, STR_FP, j, SMLSIZE); +#elif MAX_GVARS <= 5 + if (i==0 && j!=9) putsStrIdx(x+2, 2*FH, STR_FP, j, SMLSIZE); +#endif + + switch(j) + { + case 0: + editName(4*FW-3, y, g_model.gvars[i].name, LEN_GVAR_NAME, event, attr); + break; + + default: + { + PhaseData *phase = &g_model.phaseData[j-1]; + int16_t & v = phase->gvars[i]; + int16_t vmin, vmax; + if (v > GVAR_MAX) { + uint8_t p = v - GVAR_MAX - 1; + if (p >= j-1) p++; + putsFlightPhase(x-15, y, p+1, attr|SMLSIZE); + vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_PHASES-1; + } + else { + if (abs(v) >= 100) + lcd_outdezAtt(x, y+1, v, attr | TINSIZE); + else + lcd_outdezAtt(x, y, v, attr); + vmin = -GVAR_MAX; vmax = GVAR_MAX; + } + if (attr) { + if (event == EVT_KEY_LONG(KEY_ENTER)) { + s_editMode = 2; // TODO constant for that ... + v = (v > GVAR_MAX ? 0 : GVAR_MAX+1); + eeDirty(EE_MODEL); + } + else if (s_editMode>0 || p1valdiff) { + v = checkIncDec(event, v, vmin, vmax, EE_MODEL); + } + } + break; + } + } + } + } + +#if defined(CPUARM) + #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL + #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) + #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) +#elif defined(CPUM64) + #define INCDEC_DECLARE_VARS() + #define INCDEC_SET_FLAG(f) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) +#else + #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL + #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) +#endif + + if (m_posVert > 0 && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + if (g_model.gvars[sub].popup) + MENU_ADD_ITEM(STR_DISABLE_POPUP); + else + MENU_ADD_ITEM(STR_ENABLE_POPUP); + MENU_ADD_ITEM(STR_CLEAR); + menuHandler = onGVARSMenu; + } +} +#endif + +#if defined(CPUARM) + #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL + #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) + #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) +#elif defined(CPUM64) + #define INCDEC_DECLARE_VARS() + #define INCDEC_SET_FLAG(f) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) +#else + #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL + #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) +#endif + +enum CustomSwitchFields { + CSW_FIELD_FUNCTION, + CSW_FIELD_V1, + CSW_FIELD_V2, + CSW_FIELD_ANDSW, +#if defined(CPUARM) + CSW_FIELD_DURATION, + CSW_FIELD_DELAY, +#endif + CSW_FIELD_COUNT, + CSW_FIELD_LAST = CSW_FIELD_COUNT-1 +}; + +#if LCD_W >= 212 + #define CSW_1ST_COLUMN (4*FW-3) + #define CSW_2ND_COLUMN (8*FW+1) + #define CSW_3RD_COLUMN (14*FW) + #define CSW_4TH_COLUMN (21*FW+1) + #define CSW_5TH_COLUMN (26*FW+1) + #define CSW_6TH_COLUMN (31*FW+1) +#else + #define CSW_1ST_COLUMN (4*FW-3) + #define CSW_2ND_COLUMN (8*FW-3) + #define CSW_3RD_COLUMN (13*FW-6) + #define CSW_4TH_COLUMN (18*FW+2) +#endif + +#if defined(CPUARM) && LCD_W < 212 + +#define CSWONE_2ND_COLUMN (11*FW) + +void menuModelCustomSwitchOne(uint8_t event) +{ + TITLE(STR_MENUCUSTOMSWITCH); + + CustomSwData * cs = cswAddress(s_currIdx); + uint8_t sw = SWSRC_SW1+s_currIdx; + putsSwitches(14*FW, 0, sw, (getSwitch(sw) ? BOLD : 0)); + SIMPLE_SUBMENU_NOTITLE(CSW_FIELD_COUNT); + + int8_t sub = m_posVert; + + for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); + uint8_t cstate = cswFamily(cs->func); + switch(i) { + case CSW_FIELD_FUNCTION: + lcd_putsLeft(y, STR_FUNC); + lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_VCSWFUNC, cs->func, attr); + if (attr) { + CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); + if (cstate != cswFamily(cs->func)) { + cs->v1 = 0; + cs->v2 = 0; + } + } + break; + case CSW_FIELD_V1: + { + lcd_putsLeft(y, STR_V1); + int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM; + if (cstate == CS_VBOOL) { + putsSwitches(CSWONE_2ND_COLUMN, y, cs->v1, attr); + v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; + } + else if (cstate == CS_VTIMER) { + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v1+1, LEFT|attr); + v1_max = 99; + } + else { + putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v1, attr); + } + if (attr) { + CHECK_INCDEC_MODELVAR(event, cs->v1, v1_min, v1_max); + } + break; + } + case CSW_FIELD_V2: + { + lcd_putsLeft(y, STR_V2); + int8_t v2_min=0, v2_max=MIXSRC_LAST_TELEM; + if (cstate == CS_VBOOL) { + putsSwitches(CSWONE_2ND_COLUMN, y, cs->v2, attr); + v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; + } + else if (cstate == CS_VTIMER) { + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2+1, LEFT|attr); + v2_max = 99; + } + else if (cstate == CS_VCOMP) { + putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v2, attr); + } + else { +#if defined(FRSKY) + if (cs->v1 >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannel(CSWONE_2ND_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), attr|LEFT); + v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); + if (cstate == CS_VOFS) { + v2_min = -128; + v2_max -= 128; + } + else { + v2_max = min((uint8_t)127, (uint8_t)v2_max); + v2_min = -v2_max; + } + if (cs->v2 > v2_max) { + cs->v2 = v2_max; + eeDirty(EE_MODEL); + } + } + else +#endif + { + v2_min = -125; v2_max = 125; + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2, LEFT|attr); + } + } + + if (attr) { + CHECK_INCDEC_MODELVAR(event, cs->v2, v2_min, v2_max); + } + break; + } + case CSW_FIELD_ANDSW: + lcd_putsLeft(y, STR_AND_SWITCH); + putsSwitches(CSWONE_2ND_COLUMN, y, cs->andsw, attr); + if (attr) CHECK_INCDEC_MODELVAR(event, cs->andsw, -MAX_SWITCH, MAX_SWITCH); + break; + case CSW_FIELD_DURATION: + lcd_putsLeft(y, STR_DURATION); + if (cs->duration > 0) + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 5*cs->duration, attr|PREC1|LEFT); + else + lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_CSW_DURATION); + break; + case CSW_FIELD_DELAY: + lcd_putsLeft(y, STR_DELAY); + if (cs->delay > 0) + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 5*cs->delay, attr|PREC1|LEFT); + else + lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_CSW_DELAY); + break; + } + } +} + +void menuModelCustomSwitches(uint8_t event) +{ + SIMPLE_MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1); + + uint8_t y = 0; + uint8_t k = 0; + int8_t sub = m_posVert - 1; + + switch (event) { +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_BREAK: +#endif + case EVT_KEY_FIRST(KEY_RIGHT): + case EVT_KEY_FIRST(KEY_ENTER): + if (sub >= 0) { + s_currIdx = sub; + pushMenu(menuModelCustomSwitchOne); + } + break; + } + + for (uint8_t i=0; ifunc > 0) { + // CSW func + lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, 0); + + // CSW params + uint8_t cstate = cswFamily(cs->func); + + if (cstate == CS_VBOOL) { + putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0); + putsSwitches(CSW_3RD_COLUMN, y, cs->v2, 0); + } + else if (cstate == CS_VCOMP) { + putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); + putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, 0); + } + else if (cstate == CS_VTIMER) { + lcd_outdezAtt(CSW_2ND_COLUMN, y, cs->v1+1, LEFT); + lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2+1, LEFT); + } + else { + putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); + if (cs->v1 >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT); + } + else { + lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT); + } + } + + // CSW and switch + putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, 0); + } + } +} + +#else + +#if defined(PCBTARANIS) +enum ClipboardType { + CLIPBOARD_TYPE_NONE, + CLIPBOARD_TYPE_CUSTOM_SWITCH, + CLIPBOARD_TYPE_CUSTOM_FUNCTION, +}; + +struct Clipboard { + ClipboardType type; + union { + CustomSwData csw; + CustomFnData cfn; + } data; +}; + +Clipboard clipboard; + +void onCustomSwitchesMenu(const char *result) +{ + int8_t sub = m_posVert-1; + CustomSwData * cs = cswAddress(sub); + + if (result == STR_COPY) { + clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH; + clipboard.data.csw = *cs; + } + else if (result == STR_PASTE) { + *cs = clipboard.data.csw; + eeDirty(EE_MODEL); + } + else if (result == STR_DELETE) { + memset(cs, 0, sizeof(CustomSwData)); + eeDirty(EE_MODEL); + } +} +#endif + +void menuModelCustomSwitches(uint8_t event) +{ + INCDEC_DECLARE_VARS(); + + MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1, {0, NAVIGATION_LINE_BY_LINE|CSW_FIELD_LAST/*repeated...*/}); + + uint8_t y = 0; + uint8_t k = 0; + int8_t sub = m_posVert - 1; + horzpos_t horz = m_posHorz; + +#if LCD_W >= 212 + if (horz>=0) { + displayColumnHeader(STR_CSW_HEADERS, horz); + } +#endif + +#if defined(PCBTARANIS) + if (sub>=0 && horz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { + killEvents(event); + CustomSwData * cs = cswAddress(sub); + if (cs->func) MENU_ADD_ITEM(STR_COPY); + if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH) + MENU_ADD_ITEM(STR_PASTE); + if (cs->func || cs->v1 || cs->v2 || cs->delay || cs->duration || cs->andsw) MENU_ADD_ITEM(STR_DELETE); + menuHandler = onCustomSwitchesMenu; + } +#endif + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); + uint8_t attr1 = (horz==1 ? attr : 0); + uint8_t attr2 = (horz==2 ? attr : 0); + CustomSwData * cs = cswAddress(k); + + // CSW name + uint8_t sw = SWSRC_SW1+k; + putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && horz<0) ? INVERS : 0)); + + // CSW func + lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0); + + // CSW params + uint8_t cstate = cswFamily(cs->func); +#if defined(CPUARM) + int16_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; +#else + int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; +#endif + + if (cstate == CS_VBOOL) { + putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); + putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2); + v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; + v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; + INCDEC_SET_FLAG(INCDEC_SWITCH); + INCDEC_ENABLE_CHECK(NULL); + } + else if (cstate == CS_VCOMP) { + putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, attr1); + putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2); + INCDEC_SET_FLAG(INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } + else if (cstate == CS_VTIMER) { + lcd_outdezAtt(CSW_2ND_COLUMN, y, cswTimerValue(cs->v1), LEFT|PREC1|attr1); + lcd_outdezAtt(CSW_3RD_COLUMN, y, cswTimerValue(cs->v2), LEFT|PREC1|attr2); + v1_min = v2_min = -128; + v1_max = v2_max = 122; + INCDEC_SET_FLAG(0); + INCDEC_ENABLE_CHECK(NULL); + } + else { + putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, attr1); + if (horz == 1) { + INCDEC_SET_FLAG(INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } + else { + INCDEC_SET_FLAG(0); + INCDEC_ENABLE_CHECK(NULL); + } +#if defined(FRSKY) + if (cs->v1 >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); + v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); +#if defined(CPUARM) + v2_min = minTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); + if (cs->v2 < v2_min || cs->v2 > v2_max) { + cs->v2 = 0; + eeDirty(EE_MODEL); + } +#else + if (cstate == CS_VOFS) { + v2_min = -128; + v2_max -= 128; + } + else { + v2_max = min((uint8_t)127, (uint8_t)v2_max); + v2_min = -v2_max; + } + if (cs->v2 > v2_max) { + cs->v2 = v2_max; + eeDirty(EE_MODEL); + } +#endif + } + else { + lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); + v2_min = -125; v2_max = 125; + } +#else + if (cs->v1 >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); + v2_min = -128; v2_max = 127; + } + else { + lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); + v2_min = -125; v2_max = 125; + } +#endif + } + + // CSW and switch + putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==3 ? attr : 0); + +#if defined(CPUARM) + // CSW duration + if (cs->duration > 0) + lcd_outdezAtt(CSW_5TH_COLUMN, y, 5*cs->duration, (horz==4 ? attr : 0)|PREC1|LEFT); + else + lcd_putsiAtt(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==4 ? attr : 0); + + // CSW delay + if (cs->delay > 0) + lcd_outdezAtt(CSW_6TH_COLUMN, y, 5*cs->delay, (horz==5 ? attr : 0)|PREC1|LEFT); + else + lcd_putsiAtt(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==5 ? attr : 0); +#endif + + if ((s_editMode>0 || p1valdiff) && attr) { + switch (horz) { + case CSW_FIELD_FUNCTION: + { + CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); + uint8_t new_cstate = cswFamily(cs->func); + if (cstate != new_cstate) + cs->v1 = cs->v2 = (new_cstate==CS_VTIMER ? -119/*1.0*/ : 0); + break; + } + case CSW_FIELD_V1: + cs->v1 = CHECK_INCDEC_PARAM(event, cs->v1, v1_min, v1_max); + break; + case CSW_FIELD_V2: + cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); +#if defined(PCBTARANIS) + if (cstate==CS_VOFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + getvalue_t x = getValue(cs->v1); + TRACE("AUTO x=%d", x); + if (cs->v1 < MIXSRC_GVAR1) + cs->v2 = calcRESXto100(x); + else if (cs->v1 - MIXSRC_FIRST_TELEM + 1 == TELEM_ALT) + cs->v2 *= 100; + eeDirty(EE_MODEL); + } +#endif + break; + case CSW_FIELD_ANDSW: +#if defined(CPUARM) + CHECK_INCDEC_MODELSWITCH(event, cs->andsw, -MAX_CSW_ANDSW, MAX_CSW_ANDSW); +#else + CHECK_INCDEC_MODELVAR_ZERO(event, cs->andsw, MAX_CSW_ANDSW); +#endif + break; +#if defined(CPUARM) + case CSW_FIELD_DURATION: + CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_CSW_DURATION); + break; + case CSW_FIELD_DELAY: + CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_CSW_DELAY); + break; +#endif + } + } + } +} +#endif + +#if LCD_W >= 212 + #define MODEL_CUSTOM_FUNC_1ST_COLUMN (5+4*FW) + #define MODEL_CUSTOM_FUNC_2ND_COLUMN (9*FW) + #define MODEL_CUSTOM_FUNC_3RD_COLUMN (21*FW) + #define MODEL_CUSTOM_FUNC_4TH_COLUMN (33*FW-3) + #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (34*FW-3) +#else + #define MODEL_CUSTOM_FUNC_1ST_COLUMN (3) + #define MODEL_CUSTOM_FUNC_2ND_COLUMN (5*FW-2) + #define MODEL_CUSTOM_FUNC_3RD_COLUMN (15*FW+2) + #define MODEL_CUSTOM_FUNC_4TH_COLUMN (20*FW) + #if defined(GRAPHICS) + #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (20*FW) + #else + #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (18*FW+2) + #endif +#endif + +#if defined(CPUARM) && defined(SDCARD) +void onCustomFunctionsFileSelectionMenu(const char *result) +{ + int8_t sub = m_posVert - 1; + + if (result == STR_UPDATE_LIST) { + char directory[] = SOUNDS_PATH; + strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); + if (!listSdFiles(directory, SOUNDS_EXT, sizeof(g_model.funcSw[sub].param), NULL)) { + POPUP_WARNING(STR_NO_SOUNDS_ON_SD); + s_menu_flags = 0; + } + } + else { + // The user choosed a wav file in the list + memcpy(g_model.funcSw[sub].param.name, result, sizeof(g_model.funcSw[sub].param.name)); + eeDirty(EE_MODEL); + } +} +#endif + +#if defined(PCBTARANIS) +void onCustomFunctionsMenu(const char *result) +{ + int8_t sub = m_posVert-1; + CustomFnData * cfn = &g_model.funcSw[sub]; + + if (result == STR_COPY) { + clipboard.type = CLIPBOARD_TYPE_CUSTOM_FUNCTION; + clipboard.data.cfn = *cfn; + } + else if (result == STR_PASTE) { + *cfn = clipboard.data.cfn; + eeDirty(EE_MODEL); + } + else if (result == STR_CLEAR) { + memset(cfn, 0, sizeof(CustomFnData)); + eeDirty(EE_MODEL); + } + else if (result == STR_INSERT) { + memmove(cfn+1, cfn, (NUM_CFN-sub-1)*sizeof(CustomFnData)); + memset(cfn, 0, sizeof(CustomFnData)); + eeDirty(EE_MODEL); + } + else if (result == STR_DELETE) { + memmove(cfn, cfn+1, (NUM_CFN-sub-1)*sizeof(CustomFnData)); + memset(&g_model.funcSw[NUM_CFN-1], 0, sizeof(CustomFnData)); + eeDirty(EE_MODEL); + } +} + +#endif + +void menuModelCustomFunctions(uint8_t event) +{ + MENU(STR_MENUCUSTOMFUNC, menuTabModel, e_CustomFunctions, NUM_CFN+1, {0, NAVIGATION_LINE_BY_LINE|3/*repeated*/}); + + uint8_t y; + uint8_t k = 0; + int8_t sub = m_posVert - 1; + +#if defined(PCBTARANIS) + if (sub>=0 && m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { + killEvents(event); + CustomFnData *sd = &g_model.funcSw[sub]; + if (!CFN_EMPTY(sd)) + MENU_ADD_ITEM(STR_COPY); + if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION) + MENU_ADD_ITEM(STR_PASTE); + if (!CFN_EMPTY(sd) && CFN_EMPTY(&g_model.funcSw[NUM_CFN-1])) + MENU_ADD_ITEM(STR_INSERT); + if (CFN_EMPTY(sd)) + MENU_ADD_ITEM(STR_DELETE); + else + MENU_ADD_ITEM(STR_CLEAR); + menuHandler = onCustomFunctionsMenu; + } +#endif + + for (uint8_t i=0; i= 212 + putsStrIdx(0, y, STR_CF, k+1, (sub==k && m_posHorz<0) ? INVERS : 0); +#endif + + CustomFnData *sd = &g_model.funcSw[k]; + for (uint8_t j=0; j<4; j++) { + uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); + uint8_t active = (attr && (s_editMode>0 || p1valdiff)); + switch (j) { + case 0: + putsSwitches(MODEL_CUSTOM_FUNC_1ST_COLUMN, y, sd->swtch, attr | ((activeFnSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0)); + if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_MODELSWITCH(event, sd->swtch, SWSRC_FIRST, SWSRC_LAST); + break; + + case 1: + if (sd->swtch) { + uint8_t func_displayed; + if (CFN_FUNC(sd) < FUNC_TRAINER) { + func_displayed = 0; + putsChn(MODEL_CUSTOM_FUNC_2ND_COLUMN+6*FW, y, CFN_CH_NUMBER(sd)+1, attr); + } + else if (CFN_FUNC(sd) <= FUNC_TRAINER + NUM_STICKS) { + func_displayed = 1; + if (CFN_FUNC(sd) != FUNC_TRAINER) + putsMixerSource(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, MIXSRC_Rud+CFN_FUNC(sd)-FUNC_TRAINER-1, attr); + } +#if defined(DEBUG) + else if (CFN_FUNC(sd) == FUNC_TEST) { +#if defined(GVARS) + func_displayed = FUNC_TEST - FUNC_TRAINER - NUM_STICKS - MAX_GVARS + 2; +#else + func_displayed = FUNC_TEST - FUNC_TRAINER - NUM_STICKS + 1; +#endif + } +#endif +#if defined(GVARS) + else if (CFN_FUNC(sd) >= FUNC_ADJUST_GV1) { + func_displayed = FUNC_ADJUST_GV1 - FUNC_TRAINER - NUM_STICKS + 1; + putsStrIdx(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, STR_GV, CFN_FUNC(sd)-FUNC_ADJUST_GV1+1, attr); + } +#endif + else { + func_displayed = 2 + CFN_FUNC(sd) - FUNC_TRAINER - NUM_STICKS - 1; + } + lcd_putsiAtt(MODEL_CUSTOM_FUNC_2ND_COLUMN, y, STR_VFSWFUNC, func_displayed, attr); + if (active) { +#if defined(CPUARM) + CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(sd), FUNC_MAX-1); +#else + if (CFN_FUNC(sd) < FUNC_TRAINER) { + CHECK_INCDEC_MODELVAR_ZERO(event, sd->internal.func_safety.func, 16); + } + else { + CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(sd), FUNC_MAX-1); + if (CFN_FUNC(sd) < FUNC_TRAINER) + sd->internal.func_safety.func = 15; + } +#endif + if (checkIncDec_Ret) CFN_RESET(sd); + } + } + else if (attr) { + REPEAT_LAST_CURSOR_MOVE(); + } + break; + + case 2: + if (sd->swtch) { + INCDEC_DECLARE_VARS(); + int16_t val_displayed = CFN_PARAM(sd); + int8_t val_min = 0; + uint8_t val_max = 255; + if (CFN_FUNC(sd) == FUNC_PLAY_SOUND) { +#if defined(AUDIO) + val_max = AU_FRSKY_LAST-AU_FRSKY_FIRST-1; + lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_FUNCSOUNDS, val_displayed, attr); +#else + break; +#endif + } +#if defined(HAPTIC) + else if (CFN_FUNC(sd) == FUNC_HAPTIC) { + val_max = 3; + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); + } +#endif +#if defined(CPUARM) && defined(SDCARD) + else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK || CFN_FUNC(sd) == FUNC_BACKGND_MUSIC) { +#if LCD_W >= 212 + xcoord_t x = MODEL_CUSTOM_FUNC_3RD_COLUMN; +#else + xcoord_t x = (CFN_FUNC(sd) == FUNC_PLAY_TRACK ? MODEL_CUSTOM_FUNC_2ND_COLUMN + FW + FW*strlen(TR_PLAY_TRACK) : MODEL_CUSTOM_FUNC_3RD_COLUMN); +#endif + if (ZEXIST(sd->param.name)) + lcd_putsnAtt(x, y, sd->param.name, sizeof(sd->param.name), attr); + else + lcd_putsiAtt(x, y, STR_VCSWFUNC, 0, attr); + if (active && event==EVT_KEY_BREAK(KEY_ENTER)) { + s_editMode = 0; + char directory[] = SOUNDS_PATH; + strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); + if (listSdFiles(directory, SOUNDS_EXT, sizeof(sd->param.name), sd->param.name)) { + menuHandler = onCustomFunctionsFileSelectionMenu; + } + else { + POPUP_WARNING(STR_NO_SOUNDS_ON_SD); + s_menu_flags = 0; + } + } + break; + } + else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { + val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } +#endif +#if defined(CPUARM) + else if (CFN_FUNC(sd) == FUNC_VOLUME) { + val_max = MIXSRC_LAST_CH; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } +#elif defined(VOICE) + else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK) { +#if defined(GVARS) + if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + s_editMode = !s_editMode; + active = true; + val_displayed = (val_displayed > 250 ? 0 : 251); + } + if (val_displayed > 250) { + putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed-250, attr); + } + else { + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT); + } +#else + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT); +#endif + } + else if (CFN_FUNC(sd) == FUNC_PLAY_BOTH) { + lcd_putcAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+3*FWNUM, y, '|', attr); + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+3*FWNUM, y, val_displayed+PROMPT_CUSTOM_BASE, attr); + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+2+3*FWNUM, y, (val_displayed+PROMPT_CUSTOM_BASE+1)%10, attr|LEFT); + } + else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { + val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } +#endif +#if defined(SDCARD) + else if (CFN_FUNC(sd) == FUNC_LOGS) { + if (val_displayed) { + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|PREC1|LEFT); + lcd_putc(lcdLastPos, y, 's'); + } + else { + lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_MMMINV, 0, attr); + } + } +#endif + else if (CFN_FUNC(sd) == FUNC_RESET) { + val_max = FUNC_RESET_PARAM_LAST; + lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_VFSWRESET, CFN_PARAM(sd), attr); + } + else if (CFN_FUNC(sd) < FUNC_TRAINER) { + val_displayed = (int8_t)CFN_PARAM(sd); + val_min = -125; val_max = 125; + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); + } +#if defined(GVARS) + else if (CFN_FUNC(sd) >= FUNC_ADJUST_GV1 +#if defined(DEBUG) + && CFN_FUNC(sd) <= FUNC_ADJUST_GVLAST +#endif + ) { + switch (CFN_GVAR_MODE(sd)) { + case FUNC_ADJUST_GVAR_CONSTANT: + val_displayed = (int8_t)CFN_PARAM(sd); + val_min = -125; val_max = 125; + lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); + break; + case FUNC_ADJUST_GVAR_SOURCE: + val_max = MIXSRC_LAST_CH; + putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); + INCDEC_ENABLE_CHECK(isSourceAvailable); + break; + case FUNC_ADJUST_GVAR_GVAR: + val_max = MAX_GVARS-1; + putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed+1, attr); + break; + default: // FUNC_ADJUST_GVAR_INC + val_max = 1; + lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, PSTR("\002-1+1"), val_displayed, attr); + break; + } + + if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + s_editMode = !s_editMode; + active = true; + CFN_GVAR_MODE(sd) += 1; + val_displayed = 0; + } + } +#endif + else { + if (attr) m_posHorz = (CURSOR_MOVED_LEFT(event) ? 1 : 3); + break; + } + + if (active) { + CFN_PARAM(sd) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max); + } + } + else if (attr) { + REPEAT_LAST_CURSOR_MOVE(); + } + break; + + case 3: + if (sd->swtch && (CFN_FUNC(sd) <= FUNC_INSTANT_TRIM +#if defined(GVARS) + || CFN_FUNC(sd) >= FUNC_ADJUST_GV1 +#endif +#if defined(CPUARM) + || CFN_FUNC(sd) == FUNC_VOLUME +#endif + )) { + menu_lcd_onoff(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(sd), attr); + if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_ACTIVE(sd), 1); + } + else if (sd->swtch && HAS_REPEAT_PARAM(sd)) { + if (CFN_PLAY_REPEAT(sd) == 0) { +#if LCD_W >= 212 + lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); +#else + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '-', attr); +#endif + } +#if defined(CPUARM) + else if (CFN_PLAY_REPEAT(sd) == CFN_PLAY_REPEAT_NOSTART) { +#if LCD_W >= 212 + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN-2, y, '!', attr); + lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); +#else + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '!', attr); +#endif + } +#endif + else { + lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(sd)*CFN_PLAY_REPEAT_MUL, attr); +#if LCD_W >= 212 + lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, 's', attr); +#endif + } +#if defined(CPUARM) + if (active) CFN_PLAY_REPEAT(sd) = checkIncDecModel(event, CFN_PLAY_REPEAT(sd)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(sd), -1, 60/CFN_PLAY_REPEAT_MUL); +#else + if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(sd), 60/CFN_PLAY_REPEAT_MUL); +#endif + } + else if (attr) { + REPEAT_LAST_CURSOR_MOVE(); + } + break; + } + } + } +} + +#if defined(LUA_MODEL_SCRIPTS) +void onModelCustomScriptMenu(const char *result) +{ + ScriptData &sd = g_model.scriptsData[s_currIdx]; + + if (result == STR_UPDATE_LIST) { + if (!listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), NULL)) { + POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + s_menu_flags = 0; + } + } + else { + // The user choosed a lua file in the list + copySelection(sd.file, result, sizeof(sd.file)); + memset(sd.inputs, 0, sizeof(sd.inputs)); + eeDirty(EE_MODEL); + LUA_LOAD_MODEL_SCRIPT(s_currIdx); + } +} + +enum menuModelCustomScriptItems { + ITEM_MODEL_CUSTOMSCRIPT_FILE, + ITEM_MODEL_CUSTOMSCRIPT_NAME, + ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL, +}; + +#define SCRIPT_ONE_2ND_COLUMN_POS (12*FW) +#define SCRIPT_ONE_3RD_COLUMN_POS (23*FW) + +void menuModelCustomScriptOne(uint8_t event) +{ + TITLE(STR_MENUCUSTOMSCRIPT); + + ScriptData &sd = g_model.scriptsData[s_currIdx]; + + putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); + + SUBMENU_NOTITLE(3+scriptInternalData[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); + + int8_t sub = m_posVert; + + for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); + + if (i == ITEM_MODEL_CUSTOMSCRIPT_FILE) { + lcd_putsLeft(y, "Script"); + if (ZEXIST(sd.file) > 0) + lcd_putsnAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.file, sizeof(sd.file), attr); + else + lcd_putsiAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, STR_VCSWFUNC, 0, attr); + if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && !READ_ONLY()) { + s_editMode = 0; + if (listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { + menuHandler = onModelCustomScriptMenu; + } + else { + POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); + s_menu_flags = 0; + } + } + } + else if (i == ITEM_MODEL_CUSTOMSCRIPT_NAME) { + lcd_putsLeft(y, "Name"); + editName(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.name, sizeof(sd.name), event, attr); + } + else if (i == ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL) { + lcd_putsLeft(y, "Inputs"); + } + else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInternalData[s_currIdx].inputsCount) { + int inputIdx = i-ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL-1; + lcd_putsnAtt(INDENT_WIDTH, y, scriptInternalData[s_currIdx].inputs[inputIdx].name, 10, 0); + if (scriptInternalData[s_currIdx].inputs[inputIdx].type == 0) { + lcd_outdezAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr|LEFT); + if (attr) { + CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx], scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); + } + } + else { + putsMixerSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr); + if (attr) { + uint8_t *source = (uint8_t *)&g_model.scriptsData[s_currIdx].inputs[inputIdx]; + CHECK_INCDEC_MODELSOURCE(event, *source, scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); + } + } + } + } + + if (scriptInternalData[s_currIdx].outputsCount > 0) { + lcd_vline(SCRIPT_ONE_3RD_COLUMN_POS-4, FH+1, LCD_H-FH-1); + lcd_puts(SCRIPT_ONE_3RD_COLUMN_POS, FH+1, "Outputs"); + + for (int i=0; i= 0) { + s_currIdx = sub; + pushMenu(menuModelCustomScriptOne); + } + break; + } + + for (int i=0; i= 212 + #define TELEM_COL1 (1*FW) + #define TELEM_COL2 (16*FW) + #define TELEM_COL3 (28*FW) + #define TELEM_BARS_COLMIN (3*FW+56) + #define TELEM_BARS_COLMAX (20*FW-3) + #define TELEM_SCRTYPE_COL (10*FW) +#else + #define TELEM_COL1 INDENT_WIDTH + #if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_CZ) + #define TELEM_COL2 (9*FW) + #else + #define TELEM_COL2 (8*FW) + #endif + #define TELEM_BARS_COLMIN (56-3*FW) + #define TELEM_BARS_COLMAX (14*FW-3) + #define TELEM_SCRTYPE_COL (10*FW) +#endif + +#if defined(PCBTARANIS) + #define CHANNEL_ROWS (uint8_t)-1, 1, 0, 0, 0, + #define RSSI_ROWS (uint8_t)-1, 0, 0, +#else + #define CHANNEL_ROWS (uint8_t)-1, 1, 0, 2, 2, + #define RSSI_ROWS (uint8_t)-1, 1, 1, +#endif + +#if defined(GAUGES) + #define SCREEN_TYPE_ROWS 0 +#else + #define SCREEN_TYPE_ROWS (uint8_t)-1 +#endif + +#if defined(PCBSTD) + #define VARIO_RANGE_ROWS 1 +#else + #define VARIO_RANGE_ROWS 3 +#endif + +void menuModelTelemetry(uint8_t event) +{ + MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, CHANNEL_ROWS CHANNEL_ROWS RSSI_ROWS USRDATA_LINES 0, 0, IF_CPUARM(0) IF_VARIO(LABEL(Vario)) IF_VARIO(0) IF_VARIO(VARIO_RANGE_ROWS) CASE_PCBTARANIS(LABEL(TopBar)) CASE_PCBTARANIS(0) SCREEN_TYPE_ROWS, 2, 2, 2, 2, SCREEN_TYPE_ROWS, 2, 2, 2, 2, IF_CPUARM(SCREEN_TYPE_ROWS) IF_CPUARM(2) IF_CPUARM(2) IF_CPUARM(2) IF_CPUARM(2) }); + + uint8_t sub = m_posVert - 1; + +#if !defined(PCBTARANIS) + switch (event) { + case EVT_KEY_BREAK(KEY_DOWN): + case EVT_KEY_BREAK(KEY_UP): + case EVT_KEY_BREAK(KEY_LEFT): + case EVT_KEY_BREAK(KEY_RIGHT): + if (s_editMode>0 && sub<=ITEM_TELEMETRY_RSSI_ALARM2) + frskySendAlarms(); // update FrSky module when edit mode exited + break; + } +#endif + + for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); + uint8_t attr = (sub == k ? blink : 0); + uint8_t ch = (k >= ITEM_TELEMETRY_A2_LABEL) ? 1 : 0; + FrSkyChannelData & channel = g_model.frsky.channels[ch]; + uint8_t dest=TELEM_A1-1+ch; + switch(k) { + case ITEM_TELEMETRY_A1_LABEL: + case ITEM_TELEMETRY_A2_LABEL: + lcd_putsLeft(y, STR_ACHANNEL); + lcd_outdezAtt(2*FW, y, ch+1, 0); + putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, frskyData.analog[ch].value, LEFT); + break; + + case ITEM_TELEMETRY_A1_RANGE: + case ITEM_TELEMETRY_A2_RANGE: + lcd_putsLeft(y, STR_RANGE); + putsTelemetryChannel(TELEM_COL2, y, dest, 255-channel.offset, (m_posHorz<=0 ? attr : 0)|NO_UNIT|LEFT); + lcd_putsiAtt(lcdLastPos, y, STR_VTELEMUNIT, channel.type, m_posHorz!=0 ? attr : 0); + if (attr && (s_editMode>0 || p1valdiff)) { + if (m_posHorz == 0) { + uint16_t ratio = checkIncDec(event, channel.ratio, 0, 256, EE_MODEL); + if (checkIncDec_Ret) { + if (ratio == 127 && channel.multiplier > 0) { + channel.multiplier--; channel.ratio = 255; + } + else if (ratio == 256) { + if (channel.multiplier < FRSKY_MULTIPLIER_MAX) { channel.multiplier++; channel.ratio = 128; } + } + else { + channel.ratio = ratio; + } + } + } + else { + CHECK_INCDEC_MODELVAR_ZERO(event, channel.type, UNIT_A1A2_MAX); + } + } + break; + + case ITEM_TELEMETRY_A1_OFFSET: + case ITEM_TELEMETRY_A2_OFFSET: + lcd_putsLeft(y, STR_OFFSET); + putsTelemetryChannel(TELEM_COL2, y, dest, 0, LEFT|attr); + if (attr) channel.offset = checkIncDec(event, channel.offset, -256, 256, EE_MODEL); + break; + + case ITEM_TELEMETRY_A1_ALARM1: + case ITEM_TELEMETRY_A1_ALARM2: + case ITEM_TELEMETRY_A2_ALARM1: + case ITEM_TELEMETRY_A2_ALARM2: + { + uint8_t j = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1) ? 0 : 1); +#if defined(PCBTARANIS) + lcd_putsLeft(y, (j==0 ? STR_LOWALARM : STR_CRITICALALARM)); + putsTelemetryChannel(TELEM_COL2, y, dest, channel.alarms_value[j], LEFT|attr); + if (attr && (s_editMode>0 || p1valdiff)) { + channel.alarms_value[j] = checkIncDec(event, channel.alarms_value[j], 0, 255, EE_MODEL); + } +#else + lcd_putsLeft(y, STR_ALARM); + lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ALARM_LEVEL(ch, j), m_posHorz<=0 ? attr : 0); + lcd_putsiAtt(TELEM_COL2+4*FW, y, STR_VALARMFN, ALARM_GREATER(ch, j), (m_posHorz<0 || m_posHorz==1) ? attr : 0); + putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, channel.alarms_value[j], ((m_posHorz<0 || m_posHorz==2) ? attr : 0) | LEFT); + + if (attr && (s_editMode>0 || p1valdiff)) { + uint8_t t; + switch (m_posHorz) { + case 0: + t = ALARM_LEVEL(ch, j); + channel.alarms_level = (channel.alarms_level & ~(3<<(2*j))) + (checkIncDecModel(event, t, 0, 3) << (2*j)); + break; + case 1: + t = ALARM_GREATER(ch, j); + if (t != checkIncDecModel(event, t, 0, 1)) { + channel.alarms_greater ^= (1 << j); + frskySendAlarms(); + } + break; + case 2: + channel.alarms_value[j] = checkIncDec(event, channel.alarms_value[j], 0, 255, EE_MODEL); + break; + } + } +#endif + break; + } + + case ITEM_TELEMETRY_RSSI_LABEL: + lcd_putsLeft(y, PSTR("RSSI")); + break; + + case ITEM_TELEMETRY_RSSI_ALARM1: + case ITEM_TELEMETRY_RSSI_ALARM2: { + uint8_t j = k-ITEM_TELEMETRY_RSSI_ALARM1; +#if defined(PCBTARANIS) + lcd_putsLeft(y, (j==0 ? STR_LOWALARM : STR_CRITICALALARM)); + lcd_outdezNAtt(TELEM_COL2, y, getRssiAlarmValue(j), LEFT|attr, 3); + if (attr && (s_editMode>0 || p1valdiff)) { + CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].value, -30, 30); + } +#else + lcd_putsLeft(y, STR_ALARM); + lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ((2+j+g_model.frsky.rssiAlarms[j].level)%4), m_posHorz<=0 ? attr : 0); + lcd_putc(TELEM_COL2+4*FW, y, '<'); + lcd_outdezNAtt(TELEM_COL2+6*FW, y, getRssiAlarmValue(j), LEFT|(m_posHorz!=0 ? attr : 0), 3); + + if (attr && (s_editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].level, -3, 2); // circular (saves flash) + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].value, -30, 30); + break; + } + } +#endif + break; + } + +#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) + case ITEM_TELEMETRY_USR_LABEL: + lcd_putsLeft(y, STR_USRDATA); + break; + +#if !defined(PCBTARANIS) + case ITEM_TELEMETRY_USR_PROTO: + lcd_putsLeft(y, STR_PROTO); + lcd_putsiAtt(TELEM_COL2, y, STR_VTELPROTO, g_model.frsky.usrProto, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.usrProto, USR_PROTO_LAST); + break; +#endif + + case ITEM_TELEMETRY_USR_BLADES: + lcd_putsLeft(y, STR_BLADES); + lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 3); + break; +#endif + + case ITEM_TELEMETRY_USR_VOLTAGE_SOURCE: + lcd_putsLeft(y, STR_VOLTAGE); + lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.voltsSource+1, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.voltsSource, 3); + break; + + case ITEM_TELEMETRY_USR_CURRENT_SOURCE: + lcd_putsLeft(y, STR_CURRENT); + lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.currentSource, attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.currentSource, 3); + break; + +#if defined(CPUARM) + case ITEM_TELEMTETRY_PERSISTENT_MAH: + g_model.frsky.mAhPersistent = onoffMenuItem(g_model.frsky.mAhPersistent, TELEM_COL2, y, STR_PERSISTENT_MAH, attr, event); + break; +#endif + +#if defined(VARIO) + case ITEM_TELEMETRY_VARIO_LABEL: + lcd_putsLeft(y, STR_VARIO); + break; + + case ITEM_TELEMETRY_VARIO_SOURCE: + lcd_putsLeft(y, STR_SOURCE); + lcd_putsiAtt(TELEM_COL2, y, STR_VARIOSRC, g_model.frsky.varioSource, attr); + if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioSource, 0, VARIO_SOURCE_LAST); + break; + + case ITEM_TELEMETRY_VARIO_RANGE: + lcd_putsLeft(y, STR_LIMIT); +#if defined(PCBSTD) + lcd_outdezAtt(TELEM_COL2, y, 5+g_model.frsky.varioCenterMax, (m_posHorz==0 ? attr : 0)|PREC1|LEFT); + lcd_outdezAtt(TELEM_COL2+8*FW, y, 10+g_model.frsky.varioMax, (m_posHorz==1 ? attr : 0)); + if (attr && (s_editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -15, +15); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); + break; + } + } +#else + lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz<=0 ? attr : 0)|LEFT); + if (g_model.frsky.varioCenterMin == -16) + lcd_putsAtt(TELEM_COL2+4*FW-2, y, STR_OFF, m_posHorz==1 ? attr : 0); + else + lcd_outdezAtt(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((m_posHorz<0 || m_posHorz==1) ? attr : 0)|PREC1); + lcd_outdezAtt(TELEM_COL2+10*FW, y, 5+g_model.frsky.varioCenterMax, ((m_posHorz<0 || m_posHorz==2) ? attr : 0)|PREC1); + lcd_outdezAtt(TELEM_COL2+13*FW+2, y, 10+g_model.frsky.varioMax, ((m_posHorz<0 || m_posHorz==3) ? attr : 0)); + if (attr && (s_editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7); + break; + case 1: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min(10, g_model.frsky.varioCenterMax+5)); + break; + case 2: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max(-10, g_model.frsky.varioCenterMin-5), +15); + break; + case 3: + CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); + break; + } + } +#endif + break; +#endif + +#if defined(PCBTARANIS) + case ITEM_TELEMETRY_TOP_BAR_LABEL: + lcd_putsLeft(y, STR_TOP_BAR); + break; + + case ITEM_TELEMETRY_TOP_BAR_ALTITUDE: + g_model.frsky.altitudeDisplayed = onoffMenuItem(g_model.frsky.altitudeDisplayed, TELEM_COL2, y, STR_ALTITUDE, attr, event); + break; +#endif + + case ITEM_TELEMETRY_SCREEN_LABEL1: + case ITEM_TELEMETRY_SCREEN_LABEL2: +#if defined(CPUARM) + case ITEM_TELEMETRY_SCREEN_LABEL3: + { + uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 0 : (k < ITEM_TELEMETRY_SCREEN_LABEL3 ? 1 : 2)); + putsStrIdx(0*FW, y, STR_SCREEN, screenIndex+1); +#if defined(GAUGES) + bool screenType = IS_BARS_SCREEN(screenIndex); + if (screenType != selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VSCREEN, screenType, 0, 1, attr, event)) + g_model.frsky.screensType ^= (1 << screenIndex); +#endif + break; + } +#else + { + uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 1 : 2); + putsStrIdx(0*FW, y, STR_SCREEN, screenIndex); +#if defined(GAUGES) + bool screenType = g_model.frsky.screensType & screenIndex; + if (screenType != selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VSCREEN, screenType, 0, 1, attr, event)) + g_model.frsky.screensType ^= screenIndex; +#endif + break; + } +#endif + + case ITEM_TELEMETRY_SCREEN_LINE1: + case ITEM_TELEMETRY_SCREEN_LINE2: + case ITEM_TELEMETRY_SCREEN_LINE3: + case ITEM_TELEMETRY_SCREEN_LINE4: + case ITEM_TELEMETRY_SCREEN_LINE5: + case ITEM_TELEMETRY_SCREEN_LINE6: + case ITEM_TELEMETRY_SCREEN_LINE7: + case ITEM_TELEMETRY_SCREEN_LINE8: + +#if defined(CPUARM) + case ITEM_TELEMETRY_SCREEN_LINE9: + case ITEM_TELEMETRY_SCREEN_LINE10: + case ITEM_TELEMETRY_SCREEN_LINE11: + case ITEM_TELEMETRY_SCREEN_LINE12: +#endif + + { + uint8_t screenIndex, lineIndex; + if (k < ITEM_TELEMETRY_SCREEN_LABEL2) { + screenIndex = 0; + lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1; + } +#if defined(CPUARM) + else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) { + screenIndex = 2; + lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9; + } +#endif + else { + screenIndex = 1; + lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5; + } + +#if 0 + putsStrIdx(0, y, PSTR(INDENT"Line"), lineIndex+1, m_posHorz<0 ? attr : 0); +#endif + +#if defined(GAUGES) + if (IS_BARS_SCREEN(screenIndex)) { + FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex]; + uint8_t barSource = bar.source; + lcd_putsiAtt(TELEM_COL1, y, STR_VTELEMCHNS, barSource, m_posHorz==0 ? attr : 0); + if (barSource) { + putsTelemetryChannel(TELEM_BARS_COLMIN, y, barSource-1, convertTelemValue(barSource, bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT); + putsTelemetryChannel(TELEM_BARS_COLMAX, y, barSource-1, convertTelemValue(barSource, 255-bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT); + } + else if (attr) { + MOVE_CURSOR_FROM_HERE(); + } + if (attr && (s_editMode>0 || p1valdiff)) { + switch (m_posHorz) { + case 0: + bar.source = checkIncDecModel(event, barSource, 0, TELEM_DISPLAY_MAX); + if (checkIncDec_Ret) { + bar.barMin = 0; + bar.barMax = 255-maxTelemValue(bar.source); + } + break; + case 1: + bar.barMin = checkIncDec(event, bar.barMin, 0, 254-bar.barMax, EE_MODEL|NO_INCDEC_MARKS); + break; + case 2: + bar.barMax = 255 - checkIncDec(event, 255-bar.barMax, bar.barMin+1, maxTelemValue(barSource), EE_MODEL|NO_INCDEC_MARKS); + break; + } + } + } + else +#endif + { + for (uint8_t c=0; c0 || p1valdiff)) { + CHECK_INCDEC_MODELVAR_ZERO(event, value, (lineIndex==3 && c==0) ? TELEM_STATUS_MAX : TELEM_DISPLAY_MAX); + } + } + if (attr && m_posHorz == NUM_LINE_ITEMS) { + REPEAT_LAST_CURSOR_MOVE(); + } + } + break; + } + } + } +} +#endif + +#if defined(TEMPLATES) +void menuModelTemplates(uint8_t event) +{ + SIMPLE_MENU(STR_MENUTEMPLATES, menuTabModel, e_Templates, 1+TMPL_COUNT); + + uint8_t sub = m_posVert - 1; + + if (sub < TMPL_COUNT) { + if (s_warning_result) { + s_warning_result = 0; + applyTemplate(sub); + AUDIO_WARNING2(); + } + if (event==EVT_KEY_BREAK(KEY_ENTER)) { + POPUP_CONFIRMATION(STR_VTEMPLATES+1 + (sub * LEN2_VTEMPLATES)); + s_editMode = 0; + } + } + + uint8_t y = 1 + 1*FH; + uint8_t k = 0; + for (uint8_t i=0; i + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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 myeeprom_h +#define myeeprom_h + +#include + +#define WARN_THR_BIT 0x01 +#define WARN_BEP_BIT 0x80 +#define WARN_SW_BIT 0x02 +#define WARN_MEM_BIT 0x04 +#define WARN_BVAL_BIT 0x38 + +#define WARN_THR (!(g_eeGeneral.warnOpts & WARN_THR_BIT)) +#define WARN_BEP (!(g_eeGeneral.warnOpts & WARN_BEP_BIT)) +#define WARN_SW (!(g_eeGeneral.warnOpts & WARN_SW_BIT)) +#define WARN_MEM (!(g_eeGeneral.warnOpts & WARN_MEM_BIT)) +#define BEEP_VAL ( (g_eeGeneral.warnOpts & WARN_BVAL_BIT) >>3 ) + +#if defined(PCBTARANIS) + #define EEPROM_VER 216 +#elif defined(PCBSKY9X) + #define EEPROM_VER 216 +#elif defined(CPUM2560) || defined(CPUM2561) + #define EEPROM_VER 216 +#elif defined(CPUM128) + #define EEPROM_VER 216 +#else + #define EEPROM_VER 216 +#endif + +#ifndef PACK +#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#endif + +#if defined(PCBTARANIS) + #define MAX_MODELS 60 + #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 + #define MAX_PHASES 9 + #define MAX_MIXERS 64 + #define MAX_EXPOS 64 + #define NUM_CSW 32 // number of custom switches + #define NUM_CFN 32 // number of functions assigned to switches + #define MAX_SCRIPTS 3 + #define MAX_INPUTS 32 +#elif defined(CPUARM) + #define MAX_MODELS 60 + #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 + #define MAX_PHASES 9 + #define MAX_MIXERS 64 + #define MAX_EXPOS 32 + #define NUM_CSW 32 // number of custom switches + #define NUM_CFN 32 // number of functions assigned to switches +#elif defined(CPUM2560) || defined(CPUM2561) + #define MAX_MODELS 30 + #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 + #define MAX_PHASES 6 + #define MAX_MIXERS 32 + #define MAX_EXPOS 16 + #define NUM_CSW 15 // number of custom switches + #define NUM_CFN 24 // number of functions assigned to switches +#elif defined(CPUM128) + #define MAX_MODELS 30 + #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 + #define MAX_PHASES 5 + #define MAX_MIXERS 32 + #define MAX_EXPOS 14 + #define NUM_CSW 15 // number of custom switches + #define NUM_CFN 24 // number of functions assigned to switches +#else + #define MAX_MODELS 16 + #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 + #define MAX_PHASES 5 + #define MAX_MIXERS 32 + #define MAX_EXPOS 14 + #define NUM_CSW 12 // number of custom switches + #define NUM_CFN 16 // number of functions assigned to switches +#endif + +#define MAX_TIMERS 2 + +#if defined(PCBTARANIS) + enum CurveType { + CURVE_TYPE_STANDARD, + CURVE_TYPE_CUSTOM, + CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM + }; +PACK(typedef struct t_CurveInfo { + uint8_t type:3; + uint8_t smooth:1; + uint8_t spare:4; + int8_t points; +}) CurveInfo; + #define MAX_CURVES 32 + #define NUM_POINTS 512 + #define CURVDATA CurveInfo +#elif defined(CPUARM) + #define MAX_CURVES 16 + #define NUM_POINTS 512 + #define CURVDATA int16_t +#else + #define MAX_CURVES 8 + #define NUM_POINTS (112-MAX_CURVES) + #define CURVDATA int8_t +#endif + +#if defined(PCBTARANIS) || defined(PCBSKY9X) + #define NUM_MODULES 2 +#else + #define NUM_MODULES 1 +#endif + +typedef int16_t gvar_t; + +#if !defined(PCBSTD) + #define LEN_GVAR_NAME 6 + #define GVAR_MAX 1024 + #define GVAR_LIMIT 500 + PACK(typedef struct { + char name[LEN_GVAR_NAME]; + uint8_t popup:1; + uint8_t spare:7; + }) global_gvar_t; +#endif + +#define RESERVE_RANGE_FOR_GVARS 10 +// even we do not spend space in EEPROM for 10 GVARS, we reserve the space inside the range of values, like offset, weight, etc. + +#if defined(PCBSTD) && defined(GVARS) + #define MAX_GVARS 5 + #define MODEL_GVARS_DATA gvar_t gvars[MAX_GVARS]; + #define PHASE_GVARS_DATA + #define GVAR_VALUE(x, p) g_model.gvars[x] +#elif defined(PCBSTD) + #define MAX_GVARS 0 + #define MODEL_GVARS_DATA + #define PHASE_GVARS_DATA +#else + #if defined(CPUARM) + #define MAX_GVARS 9 + #else + #define MAX_GVARS 5 + #endif + #define MODEL_GVARS_DATA global_gvar_t gvars[MAX_GVARS]; + #define PHASE_GVARS_DATA gvar_t gvars[MAX_GVARS] + #define GVAR_VALUE(x, p) g_model.phaseData[p].gvars[x] +#endif + +PACK(typedef struct t_TrainerMix { + uint8_t srcChn:6; // 0-7 = ch1-8 + uint8_t mode:2; // off,add-mode,subst-mode + int8_t studWeight; +}) TrainerMix; + +PACK(typedef struct t_TrainerData { + int16_t calib[4]; + TrainerMix mix[4]; +}) TrainerData; + +PACK(typedef struct t_FrSkyRSSIAlarm { + int8_t level:2; + int8_t value:6; +}) FrSkyRSSIAlarm; + +#if defined(PCBTARANIS) +enum MainViews { + VIEW_TIMERS, + VIEW_INPUTS, + VIEW_SWITCHES, + VIEW_COUNT +}; +#else +enum MainViews { + VIEW_OUTPUTS_VALUES, + VIEW_OUTPUTS_BARS, + VIEW_INPUTS, + VIEW_TIMER2, + VIEW_COUNT +}; +#endif + +enum BeeperMode { + e_mode_quiet = -2, + e_mode_alarms, + e_mode_nokeys, + e_mode_all +}; + +#if defined(CPUARM) + #define EXTRA_GENERAL_FIELDS \ + uint8_t backlightBright; \ + int8_t currentCalib; \ + int8_t temperatureWarn; \ + uint8_t mAhWarn; \ + uint16_t mAhUsed; \ + uint32_t globalTimer; \ + int8_t temperatureCalib; \ + uint8_t btBaudrate; \ + uint8_t optrexDisplay; \ + uint8_t sticksGain; \ + uint8_t rotarySteps; \ + uint8_t countryCode; \ + uint8_t imperial; \ + char ttsLanguage[2]; \ + int8_t beepVolume; \ + int8_t wavVolume; \ + int8_t varioVolume; \ + int8_t backgroundVolume; +#elif defined(PXX) + #define EXTRA_GENERAL_FIELDS uint8_t countryCode; +#else + #define EXTRA_GENERAL_FIELDS +#endif + +PACK(typedef struct t_ModuleData { + int8_t rfProtocol; + uint8_t channelsStart; + int8_t channelsCount; // 0=8 channels + uint8_t failsafeMode; + int16_t failsafeChannels[NUM_CHNOUT]; + int8_t ppmDelay; + int8_t ppmFrameLength; + uint8_t ppmPulsePol; +}) ModuleData; + +#define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppmFrameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount) + +#define MAX_SCRIPT_INPUTS 10 +#define MAX_SCRIPT_OUTPUTS 6 +PACK(typedef struct t_ScriptData { + char file[10]; + char name[10]; + int8_t inputs[MAX_SCRIPT_INPUTS]; +}) ScriptData; + +#if defined(PCBTARANIS) + enum ModuleIndex { + INTERNAL_MODULE, + EXTERNAL_MODULE, + TRAINER_MODULE + }; + #define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; + #define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][4]; + #define LIMITDATA_EXTRA char name[LEN_CHANNEL_NAME]; int8_t curve; + #define swstate_t uint16_t +#elif defined(PCBSKY9X) + #define MODELDATA_BITMAP + #define MODELDATA_EXTRA ModuleData moduleData[NUM_MODULES]; + #define LIMITDATA_EXTRA + #define swstate_t uint8_t +#else + #define MODELDATA_BITMAP + #define MODELDATA_EXTRA + #define LIMITDATA_EXTRA + #define swstate_t uint8_t +#endif + +enum BacklightMode { + e_backlight_mode_off = 0, + e_backlight_mode_keys = 1, + e_backlight_mode_sticks = 2, + e_backlight_mode_all = e_backlight_mode_keys+e_backlight_mode_sticks, + e_backlight_mode_on +}; + +#if defined(FSPLASH) || defined(XSPLASH) + #define SPLASH_MODE uint8_t splashMode:3 +#else + #define SPLASH_MODE uint8_t splashMode:1; uint8_t spare4:2 +#endif + +#define ALTERNATE_VIEW 0x10 +PACK(typedef struct t_EEGeneral { + uint8_t version; + uint16_t variant; + int16_t calibMid[NUM_STICKS+NUM_POTS]; + int16_t calibSpanNeg[NUM_STICKS+NUM_POTS]; + int16_t calibSpanPos[NUM_STICKS+NUM_POTS]; + uint16_t chkSum; + int8_t currModel; + uint8_t contrast; + uint8_t vBatWarn; + int8_t vBatCalib; + int8_t backlightMode; + TrainerData trainer; + uint8_t view; // index of view in main screen + int8_t buzzerMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all + uint8_t fai:1; + int8_t beepMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all + uint8_t alarmsFlash:1; + uint8_t disableMemoryWarning:1; + uint8_t disableAlarmWarning:1; + uint8_t stickMode:2; + int8_t timezone:5; + uint8_t spare1:1; + uint8_t inactivityTimer; + uint8_t mavbaud:3; + SPLASH_MODE; /* 3bits */ + int8_t hapticMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all + uint8_t blOffBright:4; + uint8_t blOnBright:4; + uint8_t lightAutoOff; + uint8_t templateSetup; // RETA order for receiver channels + int8_t PPM_Multiplier; + int8_t hapticLength; + uint8_t reNavigation; // not used on STOCK board + int8_t beepLength:3; + uint8_t hapticStrength:3; + uint8_t gpsFormat:1; + uint8_t unexpectedShutdown:1; + uint8_t speakerPitch; + int8_t speakerVolume; + int8_t vBatMin; + int8_t vBatMax; + + EXTRA_GENERAL_FIELDS + + swstate_t switchUnlockStates; + +}) EEGeneral; + +#if defined(PCBTARANIS) + #define LEN_MODEL_NAME 12 + #define LEN_BITMAP_NAME 10 + #define LEN_EXPOMIX_NAME 8 + #define LEN_FP_NAME 10 + #define LEN_CHANNEL_NAME 6 +#elif defined(PCBSKY9X) + #define LEN_MODEL_NAME 10 + #define LEN_EXPOMIX_NAME 6 + #define LEN_FP_NAME 6 +#else + #define LEN_MODEL_NAME 10 + #define LEN_FP_NAME 6 +#endif + +#if defined(PCBTARANIS) +enum CurveRefType { + CURVE_REF_DIFF, + CURVE_REF_EXPO, + CURVE_REF_FUNC, + CURVE_REF_CUSTOM +}; +PACK(typedef struct t_CurveRef { + uint8_t type; + int8_t value; +}) CurveRef; +#else + #define MODE_DIFFERENTIAL 0 + #define MODE_EXPO 0 + #define MODE_CURVE 1 +#endif + +#if defined(PCBTARANIS) +PACK(typedef struct t_ExpoData { + uint8_t srcRaw; + uint16_t scale; + uint8_t chn; + int8_t swtch; + uint16_t phases; + int8_t weight; + int8_t carryTrim; + char name[LEN_EXPOMIX_NAME]; + int8_t offset; + CurveRef curve; + uint8_t spare; +}) ExpoData; +#define MIN_EXPO_WEIGHT -100 +#define EXPO_VALID(ed) ((ed)->srcRaw) +#define EXPO_MODE_ENABLE(ed, v) (true) +#elif defined(CPUARM) +PACK(typedef struct t_ExpoData { + uint8_t mode; // 0=end, 1=pos, 2=neg, 3=both + uint8_t chn; + int8_t swtch; + uint16_t phases; + int8_t weight; + uint8_t curveMode; + char name[LEN_EXPOMIX_NAME]; + int8_t curveParam; +}) ExpoData; +#define MIN_EXPO_WEIGHT 0 +#define EXPO_VALID(ed) ((ed)->mode) +#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) +#elif defined(CPUM2560) || defined(CPUM2561) +PACK(typedef struct t_ExpoData { + uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both + uint8_t chn:2; + uint8_t curveMode:1; + uint8_t spare:3; + uint8_t phases; + int8_t swtch; + uint8_t weight; + int8_t curveParam; +}) ExpoData; +#define MIN_EXPO_WEIGHT 0 +#define EXPO_VALID(ed) ((ed)->mode) +#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) +#else +PACK(typedef struct t_ExpoData { + uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both + int8_t swtch:6; + uint8_t chn:2; + uint8_t phases:5; + uint8_t curveMode:1; + uint8_t weight; // One spare bit here (used for GVARS) + int8_t curveParam; +}) ExpoData; +#define MIN_EXPO_WEIGHT 0 +#define EXPO_VALID(ed) ((ed)->mode) +#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) +#endif + +#if defined(CPUARM) + #define limit_min_max_t int16_t + #define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max+1000, 0, 1250) ? GET_GVAR(lim->max+1000, 0, 125, s_perout_flight_phase)*10 : lim->max+1000) + #define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min-1000, -1250, 0) ? GET_GVAR(lim->min-1000, -125, 0, s_perout_flight_phase)*10 : lim->min-1000) + #define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR(lim->offset, -100, 100, s_perout_flight_phase)*10 : lim->offset) + #define LIMIT_MAX_RESX(lim) calc1000toRESX(LIMIT_MAX(lim)) + #define LIMIT_MIN_RESX(lim) calc1000toRESX(LIMIT_MIN(lim)) + #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim)) +#else + #define limit_min_max_t int8_t + #define LIMIT_MAX(lim) (lim->max+100) + #define LIMIT_MIN(lim) (lim->min-100) + #define LIMIT_OFS(lim) (lim->offset) + #define LIMIT_MAX_RESX(lim) calc100toRESX(LIMIT_MAX(lim)) + #define LIMIT_MIN_RESX(lim) calc100toRESX(LIMIT_MIN(lim)) + #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim)) +#endif + +PACK(typedef struct t_LimitData { + limit_min_max_t min; + limit_min_max_t max; + int8_t ppmCenter; + int16_t offset:14; + uint16_t symetrical:1; + uint16_t revert:1; + + LIMITDATA_EXTRA + +}) LimitData; + +#define TRIM_OFF (1) +#define TRIM_ON (0) +#define TRIM_RUD (-1) +#define TRIM_ELE (-2) +#define TRIM_THR (-3) +#define TRIM_AIL (-4) + +#define MLTPX_ADD 0 +#define MLTPX_MUL 1 +#define MLTPX_REP 2 + +#if defined(CPUARM) +#define DELAY_STEP 10 +#define SLOW_STEP 10 +#define DELAY_MAX (25*DELAY_STEP) /* 25 seconds */ +#define SLOW_MAX (25*SLOW_STEP) /* 25 seconds */ +#if defined(PCBTARANIS) +PACK(typedef struct t_MixData { + uint8_t destCh; + uint16_t phases; + uint8_t mltpx; // multiplex method: 0 means +=, 1 means *=, 2 means := + int16_t weight; + int8_t swtch; + CurveRef curve; + uint8_t mixWarn:4; // mixer warning + uint8_t srcVariant:4; + uint8_t delayUp; + uint8_t delayDown; + uint8_t speedUp; + uint8_t speedDown; + uint8_t srcRaw; + int16_t offset; + char name[LEN_EXPOMIX_NAME]; + uint8_t spare; +}) MixData; +#else +PACK(typedef struct t_MixData { + uint8_t destCh; + uint16_t phases; + uint8_t curveMode:1; + uint8_t noExpo:1; + int8_t carryTrim:3; + uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := + uint8_t spare:1; + int16_t weight; + int8_t swtch; + int8_t curveParam; + uint8_t mixWarn:4; // mixer warning + uint8_t srcVariant:4; + uint8_t delayUp; + uint8_t delayDown; + uint8_t speedUp; + uint8_t speedDown; + uint8_t srcRaw; + int16_t offset; + char name[LEN_EXPOMIX_NAME]; +}) MixData; +#endif +#define MD_WEIGHT(md) (md->weight) +#define MD_WEIGHT_TO_UNION(md, var) var.word = md->weight +#define MD_UNION_TO_WEIGHT(var, md) md->weight = var.word +// #define MD_SETWEIGHT(md, val) md->weight = val + +PACK( union u_int8int16_t { + struct { + int8_t lo; + uint8_t hi; + } bytes_t; + int16_t word; +}); + +#define MD_OFFSET(md) (md->offset) +#define MD_OFFSET_TO_UNION(md, var) var.word = md->offset +#define MD_UNION_TO_OFFSET(var, md) md->offset = var.word +// #define MD_SETOFFSET(md, val) md->offset = val + +#else +#define DELAY_STEP 2 +#define SLOW_STEP 2 +#define DELAY_MAX 15 /* 7.5 seconds */ +#define SLOW_MAX 15 /* 7.5 seconds */ + +#if defined(CPUM2560) || defined(CPUM2561) +PACK(typedef struct t_MixData { + uint8_t destCh:4; // 0, 1..NUM_CHNOUT + uint8_t curveMode:1; // O=curve, 1=differential + uint8_t noExpo:1; + uint8_t weightMode:1; + uint8_t offsetMode:1; + uint8_t srcRaw; + int8_t weight; + int8_t swtch; + uint8_t phases; + uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := + int8_t carryTrim:3; + uint8_t mixWarn:2; // mixer warning + uint8_t spare:1; + uint8_t delayUp:4; + uint8_t delayDown:4; + uint8_t speedUp:4; + uint8_t speedDown:4; + int8_t curveParam; + int8_t offset; +}) MixData; +#else +PACK(typedef struct t_MixData { + uint8_t destCh:4; // 0, 1..NUM_CHNOUT + uint8_t curveMode:1; // O=curve, 1=differential + uint8_t noExpo:1; + uint8_t weightMode:1; + uint8_t offsetMode:1; + int8_t weight; + int8_t swtch:6; + uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := + uint8_t phases:5; + int8_t carryTrim:3; + uint8_t srcRaw:6; + uint8_t mixWarn:2; // mixer warning + uint8_t delayUp:4; + uint8_t delayDown:4; + uint8_t speedUp:4; + uint8_t speedDown:4; + int8_t curveParam; + int8_t offset; +}) MixData; +#endif +PACK( union u_gvarint_t { + struct { + int8_t lo; + uint8_t hi; + } bytes_t; + int16_t word; + + u_gvarint_t(int8_t l, uint8_t h) {bytes_t.lo=l; bytes_t.hi=h?255:0;} // hi bit is negativ sign + +private: + // prevent unwanted constructors, also saves program + u_gvarint_t() {} + u_gvarint_t(const u_gvarint_t&) {} +}); +#define MD_WEIGHT(md) (u_gvarint_t(md->weight,md->weightMode).word) + +PACK( union u_int8int16_t { + struct { + int8_t lo; + uint8_t hi; + } bytes_t; + int16_t word; +}); + +#define MD_WEIGHT_TO_UNION(md, var) var.bytes_t.lo=md->weight; var.bytes_t.hi=md->weightMode?255:0 +#define MD_UNION_TO_WEIGHT(var, md) md->weight=var.bytes_t.lo; if (var.word<0) md->weightMode=1; else md->weightMode=0 +// #define MD_SETWEIGHT(md, val) md->weight=val; if (val<0) md->weightMode=1; else md->weightMode=0 + +#define MD_OFFSET(md) (u_gvarint_t(md->offset,md->offsetMode).word) +#define MD_OFFSET_TO_UNION(md, var) var.bytes_t.lo=md->offset; var.bytes_t.hi=md->offsetMode?255:0 +#define MD_UNION_TO_OFFSET(var, md) md->offset=var.bytes_t.lo; if (var.word<0) md->offsetMode=1; else md->offsetMode=0 /* set negative sign */ +// #define MD_SETOFFSET(md, val) md->offset=val; if (val<0) md->offsetMode=1; else md->offsetMode=0 + +#endif + +#if defined(CPUARM) +#define MAX_CSW_DURATION 120 /*60s*/ +#define MAX_CSW_DELAY 120 /*60s*/ +#define MAX_CSW_ANDSW MAX_SWITCH +typedef int16_t csw_telemetry_value_t; +PACK(typedef struct t_CustomSwData { // Custom Switches data + int16_t v1; + int16_t v2; + uint8_t func; + uint8_t delay; + uint8_t duration; + int8_t andsw; +}) CustomSwData; +#else +typedef uint8_t csw_telemetry_value_t; +#define MAX_CSW_ANDSW 15 +PACK(typedef struct t_CustomSwData { // Custom Switches data + int8_t v1; //input + int8_t v2; //offset + uint8_t func:4; + uint8_t andsw:4; +}) CustomSwData; +#endif + +enum Functions { +#if defined(CPUARM) + FUNC_SAFETY_CH1, + FUNC_SAFETY_CH16=FUNC_SAFETY_CH1+15, +#else + FUNC_SAFETY_GROUP1, + FUNC_SAFETY_GROUP2, + FUNC_SAFETY_GROUP3, + FUNC_SAFETY_GROUP4, +#endif + FUNC_TRAINER, + FUNC_TRAINER_RUD, + FUNC_TRAINER_ELE, + FUNC_TRAINER_THR, + FUNC_TRAINER_AIL, + FUNC_INSTANT_TRIM, + FUNC_PLAY_SOUND, +#if !defined(PCBTARANIS) + FUNC_HAPTIC, +#endif + FUNC_RESET, + FUNC_VARIO, + FUNC_PLAY_TRACK, +#if !defined(CPUARM) + FUNC_PLAY_BOTH, +#endif + FUNC_PLAY_VALUE, +#if !defined(PCBSTD) + FUNC_LOGS, +#endif +#if defined(CPUARM) + FUNC_VOLUME, +#endif + FUNC_BACKLIGHT, +#if defined(CPUARM) + FUNC_BACKGND_MUSIC, + FUNC_BACKGND_MUSIC_PAUSE, +#endif +#if defined(GVARS) + FUNC_ADJUST_GV1, + FUNC_ADJUST_GVLAST = (FUNC_ADJUST_GV1 + (MAX_GVARS-1)), +#endif +#if defined(DEBUG) + FUNC_TEST, // should remain the last before MAX as not added in companion9x +#endif + FUNC_MAX +}; + +#if defined(GVARS) + #define IS_ADJUST_GV_FUNCTION(sd) (CFN_FUNC(sd) >= FUNC_ADJUST_GV1 && CFN_FUNC(sd) <= FUNC_ADJUST_GVLAST) +#else + #define IS_ADJUST_GV_FUNCTION(sd) (0) +#endif + +#if defined(VOICE) + #define HAS_REPEAT_PARAM(sd) (CFN_FUNC(sd) == FUNC_PLAY_SOUND || (CFN_FUNC(sd) >= FUNC_PLAY_TRACK && CFN_FUNC(sd) <= FUNC_PLAY_VALUE)) +#else + #define HAS_REPEAT_PARAM(sd) (CFN_FUNC(sd) == FUNC_PLAY_SOUND) +#endif + +enum ResetFunctionParam { + FUNC_RESET_TIMER1, + FUNC_RESET_TIMER2, + FUNC_RESET_ALL, +#if defined(FRSKY) + FUNC_RESET_TELEMETRY, +#endif +#if ROTARY_ENCODERS > 0 + FUNC_RESET_ROTENC1, +#endif +#if ROTARY_ENCODERS > 1 + FUNC_RESET_ROTENC2, +#endif + FUNC_RESET_PARAMS_COUNT, + FUNC_RESET_PARAM_LAST = FUNC_RESET_PARAMS_COUNT-1 +}; + +enum AdjustGvarFunctionParam { + FUNC_ADJUST_GVAR_CONSTANT, + FUNC_ADJUST_GVAR_SOURCE, + FUNC_ADJUST_GVAR_GVAR, + FUNC_ADJUST_GVAR_INC, +}; + +#if defined(CPUARM) +#if defined(PCBTARANIS) + #define LEN_CFN_NAME 10 +#else + #define LEN_CFN_NAME 6 +#endif +PACK(typedef struct t_CustomFnData { // Function Switches data + int8_t swtch; + uint8_t func; + PACK(union { + char name[LEN_CFN_NAME]; + struct { + int16_t val; + int16_t ext1; + int16_t ext2; + } composite; + }) param; + uint8_t mode:2; + uint8_t active:6; +}) CustomFnData; +#define CFN_EMPTY(p) (!(p)->swtch) +#define CFN_FUNC(p) ((p)->func) +#define CFN_ACTIVE(p) ((p)->active) +#define CFN_CH_NUMBER(p) (CFN_FUNC(p)) +#define CFN_PLAY_REPEAT(p) ((p)->active) +#define CFN_PLAY_REPEAT_MUL 1 +#define CFN_PLAY_REPEAT_NOSTART 0x3F +#define CFN_GVAR_MODE(p) ((p)->mode) +#define CFN_PARAM(p) ((p)->param.composite.val) +#define CFN_RESET(p) (p->active = 0, memset(&(p)->param, 0, sizeof((p)->param))) +#else +PACK(typedef struct t_CustomFnData { + int8_t swtch; // input + union { + struct { + uint8_t param:3; + uint8_t func:5; + } func_param; + + struct { + uint8_t active:1; + uint8_t param:2; + uint8_t func:5; + } func_param_enable; + + struct { + uint8_t active:1; + uint8_t func:7; + } func_safety; + } internal; + uint8_t param; +}) CustomFnData; +#define CFN_FUNC(p) ((p)->internal.func_param.func) +#define CFN_ACTIVE(p) ((p)->internal.func_param_enable.active) +#define CFN_CH_NUMBER(p) ((p)->internal.func_safety.func) +#define CFN_PLAY_REPEAT(p) ((p)->internal.func_param.param) +#define CFN_PLAY_REPEAT_MUL 10 +#define CFN_GVAR_MODE(p) ((p)->internal.func_param_enable.param) +#define CFN_PARAM(p) ((p)->param) +#define CFN_RESET(p) ((p)->internal.func_param_enable.active = 0, CFN_PARAM(p) = 0) +#endif + +enum TelemetryUnit { + UNIT_VOLTS, + UNIT_AMPS, + UNIT_METERS_PER_SECOND, + UNIT_RAW, + UNIT_KMH, + UNIT_METERS, + UNIT_DEGREES, + UNIT_PERCENT, + UNIT_MILLIAMPS, + UNIT_A1A2_MAX = UNIT_MILLIAMPS, + UNIT_MAH, + UNIT_WATTS, + UNIT_DBM, + UNIT_FEET, + UNIT_KTS, + UNIT_HOURS, + UNIT_MINUTES, + UNIT_SECONDS, + UNIT_RPMS, + UNIT_G, +}; + +#if defined(CPUARM) +PACK(typedef struct t_FrSkyChannelData { + uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. + int16_t offset:12; + uint16_t type:4; // channel unit (0=volts, ...) + uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. + uint8_t alarms_level:4; + uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) + uint8_t spare:2; + uint8_t multiplier; // 0=no multiplier, 1=*2 multiplier +}) FrSkyChannelData; +#else +PACK(typedef struct t_FrSkyChannelData { + uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. + int16_t offset:12; + uint16_t type:4; // channel unit (0=volts, ...) + uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. + uint8_t alarms_level:4; + uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) + uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier +}) FrSkyChannelData; +#endif + +enum TelemetrySource { + TELEM_NONE, + TELEM_TX_VOLTAGE, + TELEM_TM1, + TELEM_TM2, + TELEM_RSSI_TX, + TELEM_RSSI_RX, + TELEM_A1, + TELEM_A2, + TELEM_ALT, + TELEM_RPM, + TELEM_FUEL, + TELEM_T1, + TELEM_T2, + TELEM_SPEED, + TELEM_DIST, + TELEM_GPSALT, + TELEM_CELL, + TELEM_CELLS_SUM, + TELEM_VFAS, + TELEM_CURRENT, + TELEM_CONSUMPTION, + TELEM_POWER, + TELEM_ACCx, + TELEM_ACCy, + TELEM_ACCz, + TELEM_HDG, + TELEM_VSPD, + TELEM_MIN_A1, + TELEM_MIN_A2, + TELEM_MIN_ALT, + TELEM_MAX_ALT, + TELEM_MAX_RPM, + TELEM_MAX_T1, + TELEM_MAX_T2, + TELEM_MAX_SPEED, + TELEM_MAX_DIST, + // TODO TELEM_MIN_CELL, + // TODO TELEM_MIN_VFAS, + TELEM_MAX_CURRENT, + TELEM_MAX_POWER, + TELEM_ACC, + TELEM_GPS_TIME, + TELEM_CSW_MAX = TELEM_POWER, + TELEM_NOUSR_MAX = TELEM_A2, +#if defined(FRSKY) + TELEM_DISPLAY_MAX = TELEM_MAX_POWER, +#else + TELEM_DISPLAY_MAX = TELEM_TM2, // because used also in PlayValue +#endif + TELEM_STATUS_MAX = TELEM_GPS_TIME, +#if defined(FRSKY_SPORT) + TELEM_SWR = TELEM_RSSI_TX, + TELEM_FIRST_STREAMED_VALUE = TELEM_RSSI_RX, +#else + TELEM_FIRST_STREAMED_VALUE = TELEM_RSSI_TX, +#endif +}; + +enum VarioSource { +#if !defined(FRSKY_SPORT) + VARIO_SOURCE_ALTI, + VARIO_SOURCE_ALTI_PLUS, +#endif + VARIO_SOURCE_VARIO, + VARIO_SOURCE_A1, + VARIO_SOURCE_A2, + VARIO_SOURCE_LAST = VARIO_SOURCE_A2 +}; + +#if defined(FRSKY_HUB) + #define NUM_TELEMETRY TELEM_CSW_MAX +#elif defined(WS_HOW_HIGH) + #define NUM_TELEMETRY TELEM_ALT +#elif defined(FRSKY) + #define NUM_TELEMETRY TELEM_A2 +#elif defined(MAVLINK) + #define NUM_TELEMETRY 4 +#else + #define NUM_TELEMETRY TELEM_TM2 +#endif + +PACK(typedef struct t_FrSkyBarData { + uint8_t source; + uint8_t barMin; // minimum for bar display + uint8_t barMax; // ditto for max display (would usually = ratio) +}) FrSkyBarData; + +#if defined(PCBTARANIS) + #define NUM_LINE_ITEMS 3 +#else + #define NUM_LINE_ITEMS 2 +#endif +PACK(typedef struct t_FrSkyLineData { + uint8_t sources[NUM_LINE_ITEMS]; +}) FrSkyLineData; + +typedef union t_FrSkyScreenData { + FrSkyBarData bars[4]; + FrSkyLineData lines[4]; +} FrSkyScreenData; + +enum FrskyUsrProtocols { + USR_PROTO_NONE, + USR_PROTO_FRSKY, + USR_PROTO_WS_HOW_HIGH, + USR_PROTO_LAST = USR_PROTO_WS_HOW_HIGH, +}; + +enum FrskySource { + FRSKY_SOURCE_NONE, + FRSKY_SOURCE_A1, + FRSKY_SOURCE_A2, + FRSKY_SOURCE_FAS, + FRSKY_SOURCE_CELLS, +}; + +#if defined(CPUARM) +#define MAX_FRSKY_SCREENS 3 +PACK(typedef struct t_FrSkyData { + FrSkyChannelData channels[2]; + uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon + uint8_t voltsSource:7; + uint8_t altitudeDisplayed:1; + uint8_t blades; // How many blades for RPMs, 0=2 blades, 1=3 blades + uint8_t currentSource; + uint8_t screensType; + FrSkyScreenData screens[MAX_FRSKY_SCREENS]; + uint8_t varioSource; + int8_t varioCenterMax; + int8_t varioCenterMin; + int8_t varioMin; + int8_t varioMax; + FrSkyRSSIAlarm rssiAlarms[2]; + uint16_t mAhPersistent:1; + uint16_t storedMah:15; + int8_t fasOffset; +}) FrSkyData; +#else +#define MAX_FRSKY_SCREENS 2 +PACK(typedef struct t_FrSkyData { + FrSkyChannelData channels[2]; + uint8_t usrProto:2; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon + uint8_t blades:2; // How many blades for RPMs, 0=2 blades, 1=3 blades + uint8_t screensType:2; + uint8_t voltsSource:2; + int8_t varioMin:4; + int8_t varioMax:4; + FrSkyRSSIAlarm rssiAlarms[2]; + FrSkyScreenData screens[MAX_FRSKY_SCREENS]; + uint8_t varioSource:3; + int8_t varioCenterMin:5; + uint8_t currentSource:3; + int8_t varioCenterMax:5; + int8_t fasOffset; +}) FrSkyData; +#endif + +#if defined(MAVLINK) +PACK(typedef struct t_MavlinkData { + uint8_t rc_rssi_scale:4; + uint8_t pc_rssi_en:1; + uint8_t spare1:3; + uint8_t spare2[3]; +}) MavlinkData; +#endif + +PACK(typedef struct t_SwashRingData { // Swash Ring data + uint8_t invertELE:1; + uint8_t invertAIL:1; + uint8_t invertCOL:1; + uint8_t type:5; + uint8_t collectiveSource; + uint8_t value; +}) SwashRingData; + +#define TRIM_EXTENDED_MAX 500 +#define TRIM_EXTENDED_MIN (-TRIM_EXTENDED_MAX) +#define TRIM_MAX 125 +#define TRIM_MIN (-TRIM_MAX) + +#define ROTARY_ENCODER_MAX 1024 + +#if defined(PCBTARANIS) +#define NUM_ROTARY_ENCODERS 0 +#define NUM_ROTARY_ENCODERS_EXTRA 0 +#define ROTARY_ENCODER_ARRAY_EXTRA +#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[1]; +#elif defined(PCBSKY9X) +#define NUM_ROTARY_ENCODERS_EXTRA 0 +#define NUM_ROTARY_ENCODERS 1 +#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[1]; +#define ROTARY_ENCODER_ARRAY_EXTRA +#elif defined(PCBGRUVIN9X) && ROTARY_ENCODERS > 2 +#define NUM_ROTARY_ENCODERS_EXTRA 2 +#define NUM_ROTARY_ENCODERS (2+NUM_ROTARY_ENCODERS_EXTRA) +#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[2]; +#define ROTARY_ENCODER_ARRAY_EXTRA int16_t rotaryEncodersExtra[MAX_PHASES][NUM_ROTARY_ENCODERS_EXTRA]; +#elif defined(CPUM2560) && ROTARY_ENCODERS <= 2 +#define NUM_ROTARY_ENCODERS_EXTRA 0 +#define NUM_ROTARY_ENCODERS 2 +#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[2]; +#define ROTARY_ENCODER_ARRAY_EXTRA +#else +#define NUM_ROTARY_ENCODERS_EXTRA 0 +#define NUM_ROTARY_ENCODERS 0 +#define ROTARY_ENCODER_ARRAY +#define ROTARY_ENCODER_ARRAY_EXTRA +#endif + +#if defined(PCBSTD) + #define TRIMS_ARRAY int8_t trim[4]; int8_t trim_ext:8 + #define TRIMS_ARRAY_SIZE 5 +#else + #define TRIMS_ARRAY int16_t trim[4] + #define TRIMS_ARRAY_SIZE 8 +#endif + +#if defined(CPUARM) +PACK(typedef struct t_PhaseData { + TRIMS_ARRAY; + int8_t swtch; // swtch of phase[0] is not used + char name[LEN_FP_NAME]; + uint8_t fadeIn; + uint8_t fadeOut; + ROTARY_ENCODER_ARRAY; + PHASE_GVARS_DATA; +}) PhaseData; +#else +PACK(typedef struct t_PhaseData { + TRIMS_ARRAY; + int8_t swtch; // swtch of phase[0] is not used + char name[LEN_FP_NAME]; + uint8_t fadeIn:4; + uint8_t fadeOut:4; + ROTARY_ENCODER_ARRAY; + PHASE_GVARS_DATA; +}) PhaseData; +#endif + +enum SwitchSources { + SWSRC_NONE = 0, + + SWSRC_FIRST_SWITCH, + +#if defined(PCBTARANIS) + SWSRC_SA0 = SWSRC_FIRST_SWITCH, + SWSRC_SA1, + SWSRC_SA2, + SWSRC_SB0, + SWSRC_SB1, + SWSRC_SB2, + SWSRC_SC0, + SWSRC_SC1, + SWSRC_SC2, + SWSRC_SD0, + SWSRC_SD1, + SWSRC_SD2, + SWSRC_SE0, + SWSRC_SE1, + SWSRC_SE2, + SWSRC_SF0, + SWSRC_SF2, + SWSRC_SG0, + SWSRC_SG1, + SWSRC_SG2, + SWSRC_SH0, + SWSRC_SH2, +#else + SWSRC_ID0 = SWSRC_FIRST_SWITCH, + SWSRC_ID1, + SWSRC_ID2, +#if defined(EXTRA_3POS) + SWSRC_ID3, + SWSRC_ID4, + SWSRC_ID5, +#endif + SWSRC_THR, + SWSRC_RUD, + SWSRC_ELE, + SWSRC_AIL, + SWSRC_GEA, + SWSRC_TRN, +#endif + + SWSRC_FIRST_CSW, + SWSRC_SW1 = SWSRC_FIRST_CSW, + SWSRC_SW2, + SWSRC_SW3, + SWSRC_SW4, + SWSRC_SW5, + SWSRC_SW6, + SWSRC_SW7, + SWSRC_SW8, + SWSRC_SW9, + SWSRC_SWA, + SWSRC_SWB, + SWSRC_SWC, + SWSRC_LAST_CSW = SWSRC_SW1+NUM_CSW-1, + + SWSRC_ON, + + SWSRC_FIRST_MOMENT_SWITCH, + SWSRC_LAST_MOMENT_SWITCH = SWSRC_FIRST_MOMENT_SWITCH+SWSRC_ON-1, + +#if !defined(PCBSTD) + SWSRC_TRAINER_SHORT, + SWSRC_TRAINER_LONG, +#endif + +#if ROTARY_ENCODERS > 0 + SWSRC_FIRST_ROTENC_SWITCH, + SWSRC_LAST_ROTENC_SWITCH = SWSRC_FIRST_ROTENC_SWITCH+(2*ROTARY_ENCODERS)-1, +#endif + + SWSRC_COUNT, + SWSRC_FIRST = -SWSRC_LAST_MOMENT_SWITCH, + SWSRC_LAST = SWSRC_COUNT-1, + + SWSRC_OFF = -SWSRC_ON, + SWSRC_TRAINER = SWSRC_SW1-1, +}; + +enum MixSources { + MIXSRC_NONE, + +#if defined(PCBTARANIS) + MIXSRC_FIRST_INPUT, + MIXSRC_LAST_INPUT = MIXSRC_FIRST_INPUT+MAX_INPUTS-1, + + MIXSRC_FIRST_LUA, + MIXSRC_LAST_LUA = MIXSRC_FIRST_LUA+(MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)-1, +#endif + + MIXSRC_Rud, + MIXSRC_Ele, + MIXSRC_Thr, + MIXSRC_Ail, + + MIXSRC_FIRST_POT, +#if defined(PCBTARANIS) + MIXSRC_S1 = MIXSRC_FIRST_POT, + MIXSRC_S2, + MIXSRC_S3, + MIXSRC_S4, + MIXSRC_LAST_POT = MIXSRC_S4, +#else + MIXSRC_P1 = MIXSRC_FIRST_POT, + MIXSRC_P2, + #if defined(EXTRA_3POS) + MIXSRC_LAST_POT = MIXSRC_P2, + #else + MIXSRC_P3, + MIXSRC_LAST_POT = MIXSRC_P3, + #endif +#endif + +#if defined(PCBSKY9X) + MIXSRC_REa, + MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REa, +#elif defined(PCBGRUVIN9X) || defined(PCBMEGA2560) + MIXSRC_REa, + MIXSRC_REb, + #if ROTARY_ENCODERS > 2 + MIXSRC_REc, + MIXSRC_REd, + MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REd, + #else + MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REb, + #endif +#endif + + MIXSRC_MAX, + + MIXSRC_CYC1, + MIXSRC_CYC2, + MIXSRC_CYC3, + + MIXSRC_TrimRud, + MIXSRC_TrimEle, + MIXSRC_TrimThr, + MIXSRC_TrimAil, + + MIXSRC_FIRST_SWITCH, + +#if defined(PCBTARANIS) + MIXSRC_SA = MIXSRC_FIRST_SWITCH, + MIXSRC_SB, + MIXSRC_SC, + MIXSRC_SD, + MIXSRC_SE, + MIXSRC_SF, + MIXSRC_SG, + MIXSRC_SH, +#else + MIXSRC_3POS = MIXSRC_FIRST_SWITCH, + #if defined(EXTRA_3POS) + MIXSRC_3POS2, + #endif + MIXSRC_THR, + MIXSRC_RUD, + MIXSRC_ELE, + MIXSRC_AIL, + MIXSRC_GEA, + MIXSRC_TRN, +#endif + MIXSRC_FIRST_CSW, + MIXSRC_SW1 = MIXSRC_FIRST_CSW, + MIXSRC_SW9 = MIXSRC_SW1 + 8, + MIXSRC_SWA, + MIXSRC_SWB, + MIXSRC_SWC, + MIXSRC_LAST_CSW = MIXSRC_FIRST_CSW+NUM_CSW-1, + + MIXSRC_FIRST_PPM, + MIXSRC_LAST_PPM = MIXSRC_FIRST_PPM + 7, + + MIXSRC_FIRST_CH, + MIXSRC_CH1 = MIXSRC_FIRST_CH, + MIXSRC_CH2, + MIXSRC_CH3, + MIXSRC_CH4, + MIXSRC_CH5, + MIXSRC_CH6, + MIXSRC_CH7, + MIXSRC_CH8, + MIXSRC_CH9, + MIXSRC_CH10, + MIXSRC_CH11, + MIXSRC_CH12, + MIXSRC_CH13, + MIXSRC_CH14, + MIXSRC_CH15, + MIXSRC_CH16, + MIXSRC_LAST_CH = MIXSRC_CH1+NUM_CHNOUT-1, + + MIXSRC_GVAR1, + MIXSRC_LAST_GVAR = MIXSRC_GVAR1+MAX_GVARS-1, + + MIXSRC_FIRST_TELEM, + MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+NUM_TELEMETRY-1 +}; + +#define MIXSRC_FIRST (MIXSRC_NONE+1) +#define MIXSRC_LAST MIXSRC_LAST_CH +#define INPUTSRC_FIRST MIXSRC_Rud +#define INPUTSRC_LAST MIXSRC_LAST_TELEM + +#define MIN_POINTS 3 +#define MAX_POINTS 17 + +#define TMRMODE_NONE 0 +#define TMRMODE_ABS 1 +#define TMRMODE_THR 2 +#define TMRMODE_THR_REL 3 +#define TMRMODE_THR_TRG 4 + +#define COUNTDOWN_SILENT 0 +#define COUNTDOWN_BEEPS 1 +#define COUNTDOWN_VOICE 2 + +#if defined(CPUARM) || defined(CPUM2560) +PACK(typedef struct t_TimerData { + int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw + uint16_t start; + uint8_t countdownBeep:2; + uint8_t minuteBeep:1; + uint8_t persistent:1; + uint8_t spare:4; + uint16_t value; +}) TimerData; +#else +PACK(typedef struct t_TimerData { + int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw + uint16_t start:12; + uint16_t countdownBeep:1; + uint16_t minuteBeep:1; + uint16_t spare:2; +}) TimerData; +#endif + +enum Protocols { + PROTO_PPM, +#if !defined(CPUARM) + PROTO_PPM16, + PROTO_PPMSIM, +#endif +#if defined(PXX) || defined(DSM2) || defined(IRPROTOS) + PROTO_PXX, +#endif +#if defined(DSM2) || defined(IRPROTOS) + PROTO_DSM2_LP45, + PROTO_DSM2_DSM2, + PROTO_DSM2_DSMX, +#endif +#if defined(IRPROTOS) + // we will need 4 bytes for proto :( + PROTO_SILV, + PROTO_TRAC09, + PROTO_PICZ, + PROTO_SWIFT, +#endif + PROTO_MAX, + PROTO_NONE +}; + +enum RFProtocols { + RF_PROTO_OFF = -1, + RF_PROTO_X16, + RF_PROTO_D8, + RF_PROTO_LR12, + RF_PROTO_LAST = RF_PROTO_LR12 +}; + +enum DSM2Protocols { + DSM2_PROTO_LP45, + DSM2_PROTO_DSM2, + DSM2_PROTO_DSMX, +}; + +enum ModuleTypes { + MODULE_TYPE_NONE = 0, + MODULE_TYPE_PPM, + MODULE_TYPE_XJT, +#if defined(DSM2) + MODULE_TYPE_DSM2, +#endif + MODULE_TYPE_COUNT +}; + +enum FailsafeModes { + FAILSAFE_HOLD, + FAILSAFE_CUSTOM, + FAILSAFE_NOPULSES, + FAILSAFE_LAST = FAILSAFE_NOPULSES +}; + +#if defined(FRSKY) || !defined(PCBSTD) + #define TELEMETRY_DATA FrSkyData frsky; +#elif defined(MAVLINK) + #define TELEMETRY_DATA MavlinkData mavlink; +#else + #define TELEMETRY_DATA +#endif + +#if defined(CPUARM) || defined(PCBGRUVIN9X) || defined(PCBMEGA2560) + #define BeepANACenter uint16_t +#else + #define BeepANACenter uint8_t +#endif + +PACK(typedef struct t_ModelHeader { + char name[LEN_MODEL_NAME]; // must be first for eeLoadModelName + uint8_t modelId; + MODELDATA_BITMAP +}) ModelHeader; + +#if defined (CPUARM) + #define ARM_FIELD(x) x; + #define AVR_FIELD(x) +#else + #define ARM_FIELD(x) + #define AVR_FIELD(x) x; +#endif + +PACK(typedef struct t_ModelData { + ModelHeader header; + TimerData timers[MAX_TIMERS]; + uint8_t protocol:3; // not used on Taranis + uint8_t thrTrim:1; // Enable Throttle Trim + AVR_FIELD(int8_t ppmNCH:4) + ARM_FIELD(int8_t spare2:4) + uint8_t trimInc:3; // Trim Increments + uint8_t disableThrottleWarning:1; + ARM_FIELD(uint8_t displayText:1) + AVR_FIELD(uint8_t pulsePol:1) + uint8_t extendedLimits:1; + uint8_t extendedTrims:1; + uint8_t throttleReversed:1; + AVR_FIELD(int8_t ppmDelay) + BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7 + MixData mixData[MAX_MIXERS]; + LimitData limitData[NUM_CHNOUT]; + ExpoData expoData[MAX_EXPOS]; + + CURVDATA curves[MAX_CURVES]; + int8_t points[NUM_POINTS]; + + CustomSwData customSw[NUM_CSW]; + CustomFnData funcSw[NUM_CFN]; + SwashRingData swashR; + PhaseData phaseData[MAX_PHASES]; + + AVR_FIELD(int8_t ppmFrameLength) // 0=22.5ms (10ms-30ms) 0.5ms increments + uint8_t thrTraceSrc; + + swstate_t switchWarningStates; + + MODEL_GVARS_DATA + + TELEMETRY_DATA + + ROTARY_ENCODER_ARRAY_EXTRA + + MODELDATA_EXTRA + +}) ModelData; + +extern EEGeneral g_eeGeneral; +extern ModelData g_model; + +#define TOTAL_EEPROM_USAGE (sizeof(ModelData)*MAX_MODELS + sizeof(EEGeneral)) + +#endif +/*eof*/ diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 37aad7040..8fabf48f8 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -337,6 +337,14 @@ void Open9xSim::refreshDiplay() bmp->render(); bmf->setImage(bmp); + + // Recalc RPM based on Blades setting during simulator - T.Foley + // Final value will change as user adjusts blades, spur or gear live in simulator + frskyData.hub.rpm = 303; + frskyData.hub.rpm *= (uint8_t)60; + frskyData.hub.rpm /= (g_model.frsky.blades+1); + float gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); + frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); } } diff --git a/radio/src/simu.cpp~ b/radio/src/simu.cpp~ new file mode 100644 index 000000000..37aad7040 --- /dev/null +++ b/radio/src/simu.cpp~ @@ -0,0 +1,425 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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 "fx.h" +#include "FXExpression.h" +#include "FXPNGImage.h" +#include +#include "fxkeys.h" +#include "opentx.h" +#include +#include + +#define W2 LCD_W*2 +#define H2 LCD_H*2 + +int g_snapshot_idx = 0; + +class Open9xSim: public FXMainWindow +{ + FXDECLARE(Open9xSim) +public: + Open9xSim(){}; + Open9xSim(FXApp* a); + long onKeypress(FXObject*,FXSelector,void*); + long onTimeout(FXObject*,FXSelector,void*); + void makeSnapshot(const FXDrawable* drawable); + void doEvents(); + void refreshDiplay(); + +private: + FXImage *bmp; + FXImageFrame *bmf; + bool firstTime; + +public: + FXSlider *sliders[8]; + FXKnob *knobs[NUM_POTS]; +}; +// Message Map +FXDEFMAP(Open9xSim) Open9xSimMap[]={ + + //________Message_Type_________ID_____________________Message_Handler_______ + FXMAPFUNC(SEL_TIMEOUT, 2, Open9xSim::onTimeout), + FXMAPFUNC(SEL_KEYPRESS, 0, Open9xSim::onKeypress), + }; + +FXIMPLEMENT(Open9xSim,FXMainWindow,Open9xSimMap,ARRAYNUMBER(Open9xSimMap)) + +Open9xSim::Open9xSim(FXApp* a) +:FXMainWindow(a,"OpenTXSimu",NULL,NULL,DECOR_ALL,20,90,0,0) +{ + firstTime=true; + for(int i=0; i<(LCD_W*LCD_H/8); i++) displayBuf[i]=0;//rand(); + bmp = new FXPPMImage(getApp(),NULL,IMAGE_OWNED|IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP, W2, H2); + + FXHorizontalFrame *hf11=new FXHorizontalFrame(this,LAYOUT_CENTER_X); + FXHorizontalFrame *hf1=new FXHorizontalFrame(this,LAYOUT_FILL_X); + + //rh lv rv lh + for(int i=0; i<4; i++){ + switch(i) + { +#define L LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FIX_X|LAYOUT_FIX_Y +#undef X0 +#define X0 10 +#define Y0 10 + case 0: + sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_HORIZONTAL,X0+0,Y0+100,100,20); + break; + case 1: + sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_VERTICAL,X0+100,Y0+0,20,100); + break; + case 2: + sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_VERTICAL,X0+120,Y0+0,20,100); + break; + case 3: + sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_HORIZONTAL,X0+140,Y0+100,100,20); + break; + default:; + } + sliders[i]->setRange(-1024, 1024); + sliders[i]->setTickDelta(7); + sliders[i]->setValue(0); + } + + for(int i=0; isetRange(-1024, 1024); + knobs[i]->setValue(0); + } + + bmf = new FXImageFrame(this,bmp); + + getApp()->addTimeout(this,2,100); +} + +void Open9xSim::makeSnapshot(const FXDrawable* drawable) +{ + // Construct and create an FXImage object + FXPNGImage snapshot(getApp(), NULL, 0, drawable->getWidth(), drawable->getHeight()); + snapshot.create(); + + // Create a window device context and lock it onto the image + FXDCWindow dc(&snapshot); + + // Draw from the widget to this + dc.drawArea(drawable, 0, 0, drawable->getWidth(), drawable->getHeight(), 0, 0); + + // Release lock + dc.end(); + + // Grab pixels from server side back to client side + snapshot.restore(); + + // Save recovered pixels to a file + FXFileStream stream; + char buf[100]; + + do { + stream.close(); + sprintf(buf,"snapshot_%02d.png", ++g_snapshot_idx); + } while (stream.open(buf, FXStreamLoad)); + + if (stream.open(buf, FXStreamSave)) { + snapshot.savePixels(stream); + stream.close(); + printf("Snapshot written: %s\n", buf); + } + else { + printf("Cannot create snapshot %s\n", buf); + } +} +void Open9xSim::doEvents() +{ + getApp()->runOneEvent(false); +} + +long Open9xSim::onKeypress(FXObject*,FXSelector,void*v) +{ + FXEvent *evt=(FXEvent*)v; + // printf("keypress %x\n", evt->code); + if (evt->code=='s'){ + makeSnapshot(bmf); + } + return 0; +} + +long Open9xSim::onTimeout(FXObject*,FXSelector,void*) +{ + if(hasFocus()) { + static int keys1[]={ +#if defined(PCBTARANIS) + KEY_Page_Up, KEY_MENU, + KEY_Page_Down, KEY_PAGE, + KEY_Return, KEY_ENTER, + KEY_BackSpace, KEY_EXIT, + KEY_Up, KEY_PLUS, + KEY_Down, KEY_MINUS, +#else + KEY_Return, KEY_MENU, + KEY_BackSpace, KEY_EXIT, + KEY_Right, KEY_RIGHT, + KEY_Left, KEY_LEFT, + KEY_Up, KEY_UP, + KEY_Down, KEY_DOWN, +#endif +#if defined(ROTARY_ENCODER_NAVIGATION) + KEY_F, BTN_REa, +#endif + }; + +#if defined(PCBSKY9X) + Coproc_temp = 23; + Coproc_maxtemp = 28; +#endif + +#if defined(PCBSKY9X) + temperature = 31; + maxTemperature = 42; +#endif + + for (unsigned int i=0; igetKeyState(keys1[i])); + } + +#ifdef __APPLE__ + // gruvin: Can't use Function keys on the Mac -- too many other app conflicts. + // The ordering of these keys, Q/W,E/R,T/Y,U/I matches the on screen + // order of trim sliders + static FXuint trimKeys[] = { KEY_E, KEY_R, KEY_U, KEY_I, KEY_R, KEY_E, KEY_Y, KEY_T, KEY_Q, KEY_W }; +#else + static FXuint trimKeys[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8 }; +#endif + + for (unsigned i=0; igetKeyState(trimKeys[i])); + } + +#if defined(ROTARY_ENCODER_NAVIGATION) + static bool rotencAction = false; + if (getApp()->getKeyState(KEY_G)) { + if (!rotencAction) g_rotenc[0] += ROTARY_ENCODER_GRANULARITY; + rotencAction = true; + } + else if (getApp()->getKeyState(KEY_D)) { + if (!rotencAction) g_rotenc[0] -= ROTARY_ENCODER_GRANULARITY; + rotencAction = true; + } + else { + rotencAction = false; + } +#endif + +#define SWITCH_KEY(key, swtch, states) \ + static bool state##key = 0; \ + static int8_t state_##swtch = 2; \ + static int8_t inc_##swtch = 1; \ + if (getApp()->getKeyState(KEY_##key)) { \ + if (!state##key) { \ + state_##swtch = (state_##swtch+inc_##swtch); \ + if (state_##swtch == 1+states) inc_##swtch = -1; \ + else if (state_##swtch == 2) inc_##swtch = 1; \ + state##key = true; \ + } \ + } \ + else { \ + state##key = false; \ + } \ + simuSetSwitch(swtch, state_##swtch-states); + +#if defined(PCBTARANIS) + SWITCH_KEY(A, 0, 3); + SWITCH_KEY(B, 1, 3); + SWITCH_KEY(C, 2, 3); + SWITCH_KEY(D, 3, 3); + SWITCH_KEY(E, 4, 3); + SWITCH_KEY(F, 5, 2); + SWITCH_KEY(G, 6, 3); + SWITCH_KEY(H, 7, 2); +#else + SWITCH_KEY(1, 0, 2); + SWITCH_KEY(2, 1, 2); + SWITCH_KEY(3, 2, 2); + SWITCH_KEY(4, 3, 3); + SWITCH_KEY(5, 4, 2); + SWITCH_KEY(6, 5, 2); + SWITCH_KEY(7, 6, 2); +#endif + } + + per10ms(); + refreshDiplay(); + getApp()->addTimeout(this,2,5); + return 0; +} + +#if defined(PCBTARANIS) +#define BL_COLOR FXRGB(47,123,227) +#else +#define BL_COLOR FXRGB(150,200,152) +#endif + +void Open9xSim::refreshDiplay() +{ + if (lcd_refresh) { + lcd_refresh = false; + FXColor offColor = IS_BACKLIGHT_ON() ? BL_COLOR : FXRGB(200,200,200); +#if !defined(PCBTARANIS) + FXColor onColor = FXRGB(0,0,0); +#endif + for (int x=0;xsetPixel(2*x, 2*y, color); + bmp->setPixel(2*x+1, 2*y, color); + bmp->setPixel(2*x, 2*y+1, color); + bmp->setPixel(2*x+1, 2*y+1, color); + } +#else + if (lcd_buf[x+(y/8)*LCD_W] & (1<<(y%8))) { + bmp->setPixel(2*x, 2*y, onColor); + bmp->setPixel(2*x+1, 2*y, onColor); + bmp->setPixel(2*x, 2*y+1, onColor); + bmp->setPixel(2*x+1, 2*y+1, onColor); + } +#endif + else { + bmp->setPixel(2*x, 2*y, offColor); + bmp->setPixel(2*x+1, 2*y, offColor); + bmp->setPixel(2*x, 2*y+1, offColor); + bmp->setPixel(2*x+1, 2*y+1, offColor); + } + } + } + + bmp->render(); + bmf->setImage(bmp); + } +} + +Open9xSim *th9xSim; +void doFxEvents() +{ + //puts("doFxEvents"); + th9xSim->getApp()->runOneEvent(false); + th9xSim->refreshDiplay(); +} + +int main(int argc,char **argv) +{ + // Each FOX GUI program needs one, and only one, application object. + // The application objects coordinates some common stuff shared between + // all the widgets; for example, it dispatches events, keeps track of + // all the windows, and so on. + // We pass the "name" of the application, and its "vendor", the name + // and vendor are used to search the registry database (which stores + // persistent information e.g. fonts and colors). + FXApp application("Open9xSim", "thus"); + + // Here we initialize the application. We pass the command line arguments + // because FOX may sometimes need to filter out some of the arguments. + // This opens up the display as well, and reads the registry database + // so that persistent settings are now available. + application.init(argc,argv); + + // This creates the main window. We pass in the title to be displayed + // above the window, and possibly some icons for when its iconified. + // The decorations determine stuff like the borders, close buttons, + // drag handles, and so on the Window Manager is supposed to give this + // window. + //FXMainWindow *main=new FXMainWindow(&application,"Hello",NULL,NULL,DECOR_ALL); + th9xSim = new Open9xSim(&application); + application.create(); + + // Pretty self-explanatory:- this shows the window, and places it in the + // middle of the screen. +#ifndef __APPLE__ + th9xSim->show(PLACEMENT_SCREEN); +#else + th9xSim->show(); // Otherwise the main window gets centred across my two monitors, split down the middle. +#endif + +#if defined(FRSKY) && !defined(FRSKY_SPORT) + frskyStreaming = 1; +#endif + + printf("Model size = %d\n", (int)sizeof(g_model)); + + StartEepromThread(argc >= 2 ? argv[1] : "eeprom.bin"); + StartMainThread(); + +#if defined(PCBTARANIS) + simuSetSwitch(0, 0); + simuSetSwitch(1, 0); +#endif + + return application.run(); +} + +uint16_t anaIn(uint8_t chan) +{ + if (chansliders[chan]->getValue(); + else if (chanknobs[chan-NUM_STICKS]->getValue(); +#if defined(PCBTARANIS) + else if (chan == 8) + return 1000; +#elif defined(PCBSKY9X) + else if (chan == 7) + return 1500; + else if (chan == 8) + return 100; +#elif defined(PCBGRUVIN9X) + else if (chan == 7) + return 150; +#else + else if (chan == 7) + return 1500; +#endif + else + return 0; +} diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp index f2e7f7905..fc6e6ed4a 100644 --- a/radio/src/telemetry/frsky.cpp +++ b/radio/src/telemetry/frsky.cpp @@ -175,7 +175,15 @@ void parseTelemHubByte(uint8_t byte) switch ((uint8_t)structPos) { case offsetof(FrskySerialData, rpm): - frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley + // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing + // + frskyData.hub.rpm *= (uint8_t)60; + frskyData.hub.rpm /= (g_model.frsky.blades+1); + float gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); + frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); + if (frskyData.hub.rpm > frskyData.hub.maxRpm) frskyData.hub.maxRpm = frskyData.hub.rpm; break; diff --git a/radio/src/telemetry/frsky.cpp~ b/radio/src/telemetry/frsky.cpp~ new file mode 100644 index 000000000..35d3bf5cc --- /dev/null +++ b/radio/src/telemetry/frsky.cpp~ @@ -0,0 +1,926 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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" + +// Enumerate FrSky packet codes +#define LINKPKT 0xfe +#define USRPKT 0xfd +#define A11PKT 0xfc +#define A12PKT 0xfb +#define A21PKT 0xfa +#define A22PKT 0xf9 +#define ALRM_REQUEST 0xf8 +#define RSSI1PKT 0xf7 +#define RSSI2PKT 0xf6 +#define RSSI_REQUEST 0xf1 + +#define START_STOP 0x7e +#define BYTESTUFF 0x7d +#define STUFF_MASK 0x20 + +#if defined(TELEMETREZ) +#define PRIVATE 0x1B +#endif + +uint8_t frskyRxBuffer[FRSKY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) +uint8_t frskyTxBuffer[FRSKY_TX_PACKET_SIZE]; // Ditto for transmit buffer +#if !defined(CPUARM) +uint8_t frskyTxBufferCount = 0; +#endif +uint8_t frskyStreaming = 0; +#if defined(WS_HOW_HIGH) +uint8_t frskyUsrStreaming = 0; +#endif +uint8_t link_counter = 0; +FrskyData frskyData; + +#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) +void checkMinMaxAltitude() +{ + if (TELEMETRY_ALT_BP > frskyData.hub.maxAltitude) + frskyData.hub.maxAltitude = TELEMETRY_ALT_BP; + if (TELEMETRY_ALT_BP < frskyData.hub.minAltitude) + frskyData.hub.minAltitude = TELEMETRY_ALT_BP; +} +#endif + +#if defined(VARIO) && !defined(FRSKY_SPORT) && (defined(FRSKY_HUB) || defined(WS_HOW_HIGH)) +void evalVario(int16_t altitude_bp, uint16_t altitude_ap) +{ + int32_t varioAltitude_cm = (int32_t)altitude_bp * 100 + (altitude_bp > 0 ? altitude_ap : -altitude_ap); + uint8_t varioAltitudeQueuePointer = frskyData.hub.varioAltitudeQueuePointer + 1; + if (varioAltitudeQueuePointer >= VARIO_QUEUE_LENGTH) + varioAltitudeQueuePointer = 0; + frskyData.hub.varioAltitudeQueuePointer = varioAltitudeQueuePointer; + frskyData.hub.varioSpeed -= frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] ; + frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] = varioAltitude_cm - frskyData.hub.varioAltitude_cm; + frskyData.hub.varioAltitude_cm = varioAltitude_cm; + frskyData.hub.varioSpeed += frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] ; +} +#else +#define evalVario(...) +#endif + +#if defined(FRSKY_HUB) +typedef enum { + TS_IDLE = 0, // waiting for 0x5e frame marker + TS_DATA_ID, // waiting for dataID + TS_DATA_LOW, // waiting for data low byte + TS_DATA_HIGH, // waiting for data high byte + TS_XOR = 0x80 // decode stuffed byte +} TS_STATE; + +void parseTelemHubByte(uint8_t byte) +{ + static int8_t structPos; + static uint8_t lowByte; + static TS_STATE state = TS_IDLE; + + if (byte == 0x5e) { + state = TS_DATA_ID; + return; + } + if (state == TS_IDLE) { + return; + } + if (state & TS_XOR) { + byte = byte ^ 0x60; + state = (TS_STATE)(state - TS_XOR); + } + if (byte == 0x5d) { + state = (TS_STATE)(state | TS_XOR); + return; + } + if (state == TS_DATA_ID) { + if (byte > 0x3f) { + state = TS_IDLE; + } + else { + structPos = byte*2; + state = TS_DATA_LOW; + } + return; + } + if (state == TS_DATA_LOW) { + lowByte = byte; + state = TS_DATA_HIGH; + return; + } + + state = TS_IDLE; + +#if defined(GPS) + if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLatitude_bp)) { + if (lowByte || byte) + frskyData.hub.gpsFix = 1; + else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLatitude_bp > 1) + frskyData.hub.gpsFix = 0; + } + else if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLongitude_bp)) { + if (lowByte || byte) + frskyData.hub.gpsFix = 1; + else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLongitude_bp > 1) + frskyData.hub.gpsFix = 0; + } + + if ((uint8_t)structPos == offsetof(FrskySerialData, gpsAltitude_bp) || + ((uint8_t)structPos >= offsetof(FrskySerialData, gpsAltitude_ap) && (uint8_t)structPos <= offsetof(FrskySerialData, gpsLatitudeNS) && (uint8_t)structPos != offsetof(FrskySerialData, baroAltitude_bp) && (uint8_t)structPos != offsetof(FrskySerialData, baroAltitude_ap))) { + // If we don't have a fix, we may discard the value + if (frskyData.hub.gpsFix <= 0) + return; + } +#endif + +#if 0 + uint16_t previousValue = *((uint16_t *)(((uint8_t*)&frskyData.hub) + structPos)); +#endif + + ((uint8_t*)&frskyData.hub)[structPos] = lowByte; + ((uint8_t*)&frskyData.hub)[structPos+1] = byte; + + switch ((uint8_t)structPos) { + + case offsetof(FrskySerialData, rpm): + //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley + // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing + // + frskyData.hub.rpm *= (uint8_t)60; + frskyData.hub.rpm /= (g_model.frsky.blades+1); + float gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); + frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); + if (frskyData.hub.rpm > frskyData.hub.maxRpm) + frskyData.hub.maxRpm = frskyData.hub.rpm; + break; + + case offsetof(FrskySerialData, temperature1): + if (frskyData.hub.temperature1 > frskyData.hub.maxTemperature1) + frskyData.hub.maxTemperature1 = frskyData.hub.temperature1; + break; + + case offsetof(FrskySerialData, temperature2): + if (frskyData.hub.temperature2 > frskyData.hub.maxTemperature2) + frskyData.hub.maxTemperature2 = frskyData.hub.temperature2; + break; + + case offsetof(FrskySerialData, current): + if (frskyData.hub.current > frskyData.hub.maxCurrent) + frskyData.hub.maxCurrent = frskyData.hub.current; + break; + + case offsetof(FrskySerialData, currentConsumption): + // we receive data from openXsensor. stops the calculation of consumption and power + frskyData.hub.openXsensor = 1; + break; + + case offsetof(FrskySerialData, volts_ap): +#if defined(FAS_BSS) + frskyData.hub.vfas = (frskyData.hub.volts_bp * 10 + frskyData.hub.volts_ap); +#else + frskyData.hub.vfas = ((frskyData.hub.volts_bp * 100 + frskyData.hub.volts_ap * 10) * 21) / 110; +#endif + /* TODO later if (!frskyData.hub.minVfas || frskyData.hub.minVfas > frskyData.hub.vfas) + frskyData.hub.minVfas = frskyData.hub.vfas; */ + break; + + case offsetof(FrskySerialData, baroAltitude_bp): + // First received barometer altitude => Altitude offset + if (!frskyData.hub.baroAltitudeOffset) + frskyData.hub.baroAltitudeOffset = -frskyData.hub.baroAltitude_bp; + if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI) { + evalVario(frskyData.hub.baroAltitude_bp, 0); + } + frskyData.hub.baroAltitude_bp += frskyData.hub.baroAltitudeOffset; + checkMinMaxAltitude(); + break; + + case offsetof(FrskySerialData, baroAltitude_ap): + if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI_PLUS) { + evalVario(frskyData.hub.baroAltitude_bp-frskyData.hub.baroAltitudeOffset, frskyData.hub.baroAltitude_ap); + } + break; + +#if defined(GPS) + case offsetof(FrskySerialData, gpsAltitude_ap): + if (!frskyData.hub.gpsAltitudeOffset) + frskyData.hub.gpsAltitudeOffset = -frskyData.hub.gpsAltitude_bp; + frskyData.hub.gpsAltitude_bp += frskyData.hub.gpsAltitudeOffset; + if (!frskyData.hub.baroAltitudeOffset) { + if (frskyData.hub.gpsAltitude_bp > frskyData.hub.maxAltitude) + frskyData.hub.maxAltitude = frskyData.hub.gpsAltitude_bp; + if (frskyData.hub.gpsAltitude_bp < frskyData.hub.minAltitude) + frskyData.hub.minAltitude = frskyData.hub.gpsAltitude_bp; + } + if (!frskyData.hub.pilotLatitude && !frskyData.hub.pilotLongitude) { + // First received GPS position => Pilot GPS position + getGpsPilotPosition(); + } + else if (frskyData.hub.gpsDistNeeded || g_menuStack[g_menuStackPtr] == menuTelemetryFrsky) { + getGpsDistance(); + } + break; + + case offsetof(FrskySerialData, gpsSpeed_bp): + // Speed => Max speed + if (frskyData.hub.gpsSpeed_bp > frskyData.hub.maxGpsSpeed) + frskyData.hub.maxGpsSpeed = frskyData.hub.gpsSpeed_bp; + break; +#endif + + case offsetof(FrskySerialData, volts): + // Voltage => Cell number + Cell voltage + { + uint8_t battnumber = ((frskyData.hub.volts & 0x00F0) >> 4); + if (battnumber < 12) { + if (frskyData.hub.cellsCount < battnumber+1) { + frskyData.hub.cellsCount = battnumber+1; + } + uint8_t cellVolts = (uint8_t)(((((frskyData.hub.volts & 0xFF00) >> 8) + ((frskyData.hub.volts & 0x000F) << 8)))/10); + frskyData.hub.cellVolts[battnumber] = cellVolts; + if (!frskyData.hub.minCellVolts || cellVolts < frskyData.hub.minCellVolts || battnumber==frskyData.hub.minCellIdx) { + frskyData.hub.minCellIdx = battnumber; + frskyData.hub.minCellVolts = cellVolts; + } + } + break; + } + +#if defined(GPS) + case offsetof(FrskySerialData, hour): + frskyData.hub.hour = ((uint8_t)(frskyData.hub.hour + g_eeGeneral.timezone + 24)) % 24; + break; +#endif + + case offsetof(FrskySerialData, accelX): + case offsetof(FrskySerialData, accelY): + case offsetof(FrskySerialData, accelZ): + *(int16_t*)(&((uint8_t*)&frskyData.hub)[structPos]) /= 10; + break; + +#if 0 + case offsetof(FrskySerialData, gpsAltitude_bp): + case offsetof(FrskySerialData, fuelLevel): + case offsetof(FrskySerialData, gpsLongitude_bp): + case offsetof(FrskySerialData, gpsLatitude_bp): + case offsetof(FrskySerialData, gpsCourse_bp): + case offsetof(FrskySerialData, day): + case offsetof(FrskySerialData, year): + case offsetof(FrskySerialData, sec): + case offsetof(FrskySerialData, gpsSpeed_ap): + case offsetof(FrskySerialData, gpsLongitude_ap): + case offsetof(FrskySerialData, gpsLatitude_ap): + case offsetof(FrskySerialData, gpsCourse_ap): + case offsetof(FrskySerialData, gpsLongitudeEW): + case offsetof(FrskySerialData, gpsLatitudeNS): + case offsetof(FrskySerialData, varioSpeed): + case offsetof(FrskySerialData, power): /* because sent by openXsensor */ + case offsetof(FrskySerialData, vfas): + case offsetof(FrskySerialData, volts_bp): + break; + + default: + *((uint16_t *)(((uint8_t*)&frskyData.hub) + structPos)) = previousValue; + break; +#endif + } +} +#endif + +#if defined(WS_HOW_HIGH) +void parseTelemWSHowHighByte(uint8_t byte) +{ + if (frskyUsrStreaming < (FRSKY_TIMEOUT10ms*3 - 10)) { + ((uint8_t*)&frskyData.hub)[offsetof(FrskySerialData, baroAltitude_bp)] = byte; + checkMinMaxAltitude(); + if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI) { + evalVario(frskyData.hub.baroAltitude_bp, 0); + } + } + else { + // At least 100mS passed since last data received + ((uint8_t*)&frskyData.hub)[offsetof(FrskySerialData, baroAltitude_bp)+1] = byte; + } + // baroAltitude_bp unit here is feet! + frskyUsrStreaming = FRSKY_TIMEOUT10ms*3; // reset counter +} +#endif + +void processFrskyPacket(uint8_t *packet) +{ + // What type of packet? + switch (packet[0]) + { + case LINKPKT: // A1/A2/RSSI values + { + link_counter += 32; + frskyData.analog[0].set(packet[1], g_model.frsky.channels[0].type); + frskyData.analog[1].set(packet[2], g_model.frsky.channels[1].type); + frskyData.rssi[0].set(packet[3]); + frskyData.rssi[1].set(packet[4] / 2); + frskyStreaming = FRSKY_TIMEOUT10ms; // reset counter only if valid frsky packets are being detected +#if defined(VARIO) + uint8_t varioSource = g_model.frsky.varioSource - VARIO_SOURCE_A1; + if (varioSource < 2) + frskyData.hub.varioSpeed = applyChannelRatio(varioSource, frskyData.analog[varioSource].value); +#endif + break; + } +#if defined(FRSKY_HUB) || defined (WS_HOW_HIGH) + case USRPKT: // User Data packet + uint8_t numBytes = 3 + (packet[1] & 0x07); // sanitize in case of data corruption leading to buffer overflow + for (uint8_t i=3; i>1) * (voltage>>1)) / 25; +#endif + + frskyData.hub.currentPrescale += current; + if (frskyData.hub.currentPrescale >= 3600) { + frskyData.hub.currentConsumption += 1; + frskyData.hub.currentPrescale -= 3600; + } + } + + if (frskyData.hub.power > frskyData.hub.maxPower) + frskyData.hub.maxPower = frskyData.hub.power; + } +} + +void telemetryWakeup() +{ +#if defined(PCBSKY9X) + rxPdcUsart(processSerialData); // Receive serial data here +#endif + + // Attempt to transmit any waiting Fr-Sky alarm set packets every 50ms (subject to packet buffer availability) + static uint8_t frskyTxDelay = 5; + if (frskyAlarmsSendState && (--frskyTxDelay == 0)) { + frskyTxDelay = 5; // 50ms + frskySendNextAlarm(); + } + +#ifndef SIMU +#if defined(WS_HOW_HIGH) + if (frskyUsrStreaming > 0) { + frskyUsrStreaming--; + } +#endif + + if (frskyStreaming > 0) { + frskyStreaming--; + } + else { + frskyData.rssi[0].set(0); + frskyData.rssi[1].set(0); + } +#endif + +#if defined(VARIO) + if (TELEMETRY_STREAMING() && !IS_FAI_ENABLED()) + varioWakeup(); +#endif +} + +#if 0 +// not used any more +bool FRSKY_alarmRaised(uint8_t idx) +{ + for (int i=0; i<2; i++) { + if (ALARM_LEVEL(idx, i) != alarm_off) { + if (ALARM_GREATER(idx, i)) { + if (frskyData.analog[idx].value > g_model.frsky.channels[idx].alarms_value[i]) + return true; + } + else { + if (frskyData.analog[idx].value < g_model.frsky.channels[idx].alarms_value[i]) + return true; + } + } + } + return false; +} +#endif + +#if !defined(CPUARM) +inline void FRSKY_EnableTXD(void) +{ + frskyTxBufferCount = 0; + UCSR0B |= (1 << TXEN0); // enable TX +} + +inline void FRSKY_EnableRXD(void) +{ + UCSR0B |= (1 << RXEN0); // enable RX + UCSR0B |= (1 << RXCIE0); // enable Interrupt +} +#endif + +void FRSKY_Init(void) +{ + // clear frsky variables + resetTelemetry(); + +#if defined(PCBTARANIS) + // TODO +#elif defined(PCBSKY9X) + startPdcUsartReceive() ; +#elif !defined(SIMU) + + DDRE &= ~(1 << DDE0); // set RXD0 pin as input + PORTE &= ~(1 << PORTE0); // disable pullup on RXD0 pin + +#undef BAUD +#define BAUD 9600 +#include + + UBRR0H = UBRRH_VALUE; + UBRR0L = UBRRL_VALUE; + UCSR0A &= ~(1 << U2X0); // disable double speed operation. + + // set 8N1 + UCSR0B = 0 | (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (0 << RXEN0) | (0 << TXEN0) | (0 << UCSZ02); + UCSR0C = 0 | (1 << UCSZ01) | (1 << UCSZ00); + + + while (UCSR0A & (1 << RXC0)) UDR0; // flush receive buffer + + // These should be running right from power up on a FrSky enabled '9X. + FRSKY_EnableTXD(); // enable FrSky-Telemetry reception + FRSKY_EnableRXD(); // enable FrSky-Telemetry reception +#endif +} + +void FrskyValueWithMin::set(uint8_t value) +{ + if (this->value == 0) { + this->value = value; + } + else { + sum += value; + if (link_counter == 0) { + this->value = sum / 8; + sum = 0; + } + } + + if (value && (!min || value < min)) + min = value; +} + +void FrskyValueWithMinMax::set(uint8_t value, uint8_t unit) +{ + FrskyValueWithMin::set(value); + if (unit != UNIT_VOLTS) { + this->value = value; + } + if (!max || value > max) + max = value; +} + +void resetTelemetry() +{ + memclear(&frskyData, sizeof(frskyData)); + +#if defined(FRSKY_HUB) + frskyData.hub.gpsLatitude_bp = 2; + frskyData.hub.gpsLongitude_bp = 2; + frskyData.hub.gpsFix = -1; +#endif + +#ifdef SIMU + frskyData.analog[0].set(120, UNIT_VOLTS); + frskyData.analog[1].set(240, UNIT_VOLTS); + frskyData.rssi[0].value = 75; + frskyData.rssi[1].value = 75; + frskyData.hub.fuelLevel = 75; + frskyData.hub.rpm = 12000; + +#if defined(GPS) + frskyData.hub.gpsFix = 1; + frskyData.hub.gpsLatitude_bp = 4401; + frskyData.hub.gpsLatitude_ap = 7710; + frskyData.hub.gpsLongitude_bp = 1006; + frskyData.hub.gpsLongitude_ap = 8872; + frskyData.hub.gpsSpeed_bp = (100 * 250) / 463; + getGpsPilotPosition(); + + frskyData.hub.gpsLatitude_bp = 4401; + frskyData.hub.gpsLatitude_ap = 7455; + frskyData.hub.gpsLongitude_bp = 1006; + frskyData.hub.gpsLongitude_ap = 9533; + getGpsDistance(); +#endif + + frskyData.hub.cellsCount = 6; + + frskyData.hub.gpsAltitude_bp = 50; + frskyData.hub.baroAltitude_bp = 50; + frskyData.hub.minAltitude = 10; + frskyData.hub.maxAltitude = 500; + + frskyData.hub.accelY = 100; + frskyData.hub.temperature1 = -30; + frskyData.hub.maxTemperature1 = 100; + + frskyData.hub.current = 5; + frskyData.hub.maxCurrent = 56; +#endif +} diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 98d62ab7b..3e1ef09c7 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -185,6 +185,8 @@ const pm_char STR_BAR[] PROGMEM = TR_BAR; const pm_char STR_ALARM[] PROGMEM = TR_ALARM; const pm_char STR_USRDATA[] PROGMEM = TR_USRDATA; const pm_char STR_BLADES[] PROGMEM = TR_BLADES; +const pm_char STR_SPURGEAR[] PROGMEM = TR_SPURGEAR; // T.Foley +const pm_char STR_PINIONGEAR[] PROGMEM = TR_PINIONGEAR; // T.Foley const pm_char STR_SCREEN[] PROGMEM = TR_SCREEN; const pm_char STR_SOUND_LABEL[] PROGMEM = TR_SOUND_LABEL; const pm_char STR_LENGTH[] PROGMEM = TR_LENGTH; diff --git a/radio/src/translations.cpp~ b/radio/src/translations.cpp~ new file mode 100644 index 000000000..98d62ab7b --- /dev/null +++ b/radio/src/translations.cpp~ @@ -0,0 +1,672 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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" + +#define ISTR(x) LEN_##x TR_##x + +// The non-0-terminated-strings +const pm_char STR_OPEN9X[] PROGMEM = + ISTR(OFFON) + ISTR(MMMINV) + ISTR(NCHANNELS) +#if !defined(GRAPHICS) + ISTR(VBEEPLEN) +#endif + ISTR(VBEEPMODE) +#if defined(ROTARY_ENCODERS) + ISTR(VRENAVIG) +#endif +#if defined(ROTARY_ENCODER_NAVIGATION) + ISTR(VRENCODERS) +#endif + ISTR(TRNMODE) + ISTR(TRNCHN) + ISTR(VTRIMINC) + ISTR(RETA123) + ISTR(VPROTOS) + ISTR(POSNEG) + ISTR(VBLMODE) + ISTR(VCURVEFUNC) + ISTR(VMLTPX) + ISTR(VMLTPX2) + ISTR(VMIXTRIMS) + ISTR(VCSWFUNC) + ISTR(VFSWFUNC) + ISTR(VFSWRESET) + ISTR(FUNCSOUNDS) + ISTR(VTELEMCHNS) +#if defined(FRSKY) || defined(CPUARM) + #if defined(CPUARM) + ISTR(VTELEMUNIT_IMP) + ISTR(VTELEMUNIT_NORM) + #else + ISTR(VTELEMUNIT) + #endif + ISTR(VALARM) + ISTR(VALARMFN) + ISTR(VTELPROTO) + ISTR(GPSFORMAT) + ISTR(VOLTSRC) + ISTR(VARIOSRC) + ISTR(VSCREEN) +#endif +#if defined(TEMPLATES) + ISTR(VTEMPLATES) +#endif +#if defined(HELI) + ISTR(VSWASHTYPE) +#endif + ISTR(VKEYS) + ISTR(VSWITCHES) + ISTR(VSRCRAW) + ISTR(VTMRMODES) +#if defined(CPUM2560) || defined(CPUARM) + ISTR(DATETIME) +#endif +#if defined(CPUARM) + ISTR(VLCD) + ISTR(VUNITSSYSTEM) + ISTR(VBEEPCOUNTDOWN) +#endif +#if defined(PXX) + ISTR(COUNTRYCODES) + ISTR(VFAILSAFE) +#endif +#if defined(PCBTARANIS) + ISTR(VTRAINERMODES) +#endif +#if defined(MAVLINK) + ISTR(MAVLINK_BAUDS) + ISTR(MAVLINK_AC_MODES) + ISTR(MAVLINK_AP_MODES) +#endif + ; + +// The 0-terminated-strings +const pm_char STR_POPUPS[] PROGMEM = TR_POPUPS; +const pm_char STR_MENUWHENDONE[] PROGMEM = TR_MENUWHENDONE; +const pm_char STR_FREE[] PROGMEM = TR_FREE; +const pm_char STR_DELETEMODEL[] PROGMEM = TR_DELETEMODEL; +const pm_char STR_COPYINGMODEL[] PROGMEM = TR_COPYINGMODEL; +const pm_char STR_MOVINGMODEL[] PROGMEM = TR_MOVINGMODEL; +const pm_char STR_LOADINGMODEL[] PROGMEM = TR_LOADINGMODEL; +const pm_char STR_NAME[] PROGMEM = TR_NAME; +const pm_char STR_BITMAP[] PROGMEM = TR_BITMAP; +const pm_char STR_TIMER[] PROGMEM = TR_TIMER; +const pm_char STR_ELIMITS[] PROGMEM = TR_ELIMITS; +const pm_char STR_ETRIMS[] PROGMEM = TR_ETRIMS; +const pm_char STR_TRIMINC[] PROGMEM = TR_TRIMINC; +const pm_char STR_TTRACE[] PROGMEM = TR_TTRACE; +const pm_char STR_TTRIM[] PROGMEM = TR_TTRIM; +const pm_char STR_BEEPCTR[] PROGMEM = TR_BEEPCTR; +const pm_char STR_PROTO[] PROGMEM = TR_PROTO; +const pm_char STR_PPMFRAME[] PROGMEM = TR_PPMFRAME; +const pm_char STR_MS[] PROGMEM = TR_MS; +const pm_char STR_SWITCH[] PROGMEM = TR_SWITCH; +const pm_char STR_TRIMS[] PROGMEM = TR_TRIMS; +const pm_char STR_FADEIN[] PROGMEM = TR_FADEIN; +const pm_char STR_FADEOUT[] PROGMEM = TR_FADEOUT; +const pm_char STR_DEFAULT[] PROGMEM = TR_DEFAULT; +const pm_char STR_CHECKTRIMS[] PROGMEM = TR_CHECKTRIMS; +#ifdef HELI +const pm_char STR_SWASHTYPE[] PROGMEM = TR_SWASHTYPE; +const pm_char STR_COLLECTIVE[] PROGMEM = TR_COLLECTIVE; +const pm_char STR_SWASHRING[] PROGMEM = TR_SWASHRING; +const pm_char STR_ELEDIRECTION[] PROGMEM = TR_ELEDIRECTION; +const pm_char STR_AILDIRECTION[] PROGMEM = TR_AILDIRECTION; +const pm_char STR_COLDIRECTION[] PROGMEM = TR_COLDIRECTION; +#endif +const pm_char STR_MODE[] PROGMEM = TR_MODE; +#if defined(AUDIO) && defined(BUZZER) +const pm_char STR_SPEAKER[] PROGMEM = TR_SPEAKER; +const pm_char STR_BUZZER[] PROGMEM = TR_BUZZER; +#endif +const pm_char STR_NOFREEEXPO[] PROGMEM = TR_NOFREEEXPO; +const pm_char STR_NOFREEMIXER[] PROGMEM = TR_NOFREEMIXER; +const pm_char STR_INSERTMIX[] PROGMEM = TR_INSERTMIX; +const pm_char STR_EDITMIX[] PROGMEM = TR_EDITMIX; +const pm_char STR_SOURCE[] PROGMEM = TR_SOURCE; +const pm_char STR_WEIGHT[] PROGMEM = TR_WEIGHT; +const pm_char STR_EXPO[] PROGMEM = TR_EXPO; +const pm_char STR_SIDE[] PROGMEM = TR_SIDE; +const pm_char STR_DIFFERENTIAL[] PROGMEM = TR_DIFFERENTIAL; +const pm_char STR_OFFSET[] PROGMEM = TR_OFFSET; +const pm_char STR_TRIM[] PROGMEM = TR_TRIM; +const pm_char STR_DREX[] PROGMEM = TR_DREX; +const pm_char STR_CURVE[] PROGMEM = TR_CURVE; +const pm_char STR_FLMODE[] PROGMEM = TR_FLMODE; +const pm_char STR_MIXWARNING[] PROGMEM = TR_MIXWARNING; +const pm_char STR_OFF[] PROGMEM = TR_OFF; +const pm_char STR_MULTPX[] PROGMEM = TR_MULTPX; +const pm_char STR_DELAYDOWN[] PROGMEM = TR_DELAYDOWN; +const pm_char STR_DELAYUP[] PROGMEM = TR_DELAYUP; +const pm_char STR_SLOWDOWN[] PROGMEM = TR_SLOWDOWN; +const pm_char STR_SLOWUP[] PROGMEM = TR_SLOWUP; +const pm_char STR_MIXER[] PROGMEM = TR_MIXER; +const pm_char STR_CV[] PROGMEM = TR_CV; +const pm_char STR_GV[] PROGMEM = TR_GV; +const pm_char STR_ACHANNEL[] PROGMEM = TR_ACHANNEL; +const pm_char STR_RANGE[] PROGMEM = TR_RANGE; +const pm_char STR_BAR[] PROGMEM = TR_BAR; +const pm_char STR_ALARM[] PROGMEM = TR_ALARM; +const pm_char STR_USRDATA[] PROGMEM = TR_USRDATA; +const pm_char STR_BLADES[] PROGMEM = TR_BLADES; +const pm_char STR_SCREEN[] PROGMEM = TR_SCREEN; +const pm_char STR_SOUND_LABEL[] PROGMEM = TR_SOUND_LABEL; +const pm_char STR_LENGTH[] PROGMEM = TR_LENGTH; +#if defined(AUDIO) +const pm_char STR_SPKRPITCH[] PROGMEM = TR_SPKRPITCH; +#endif +#if defined(HAPTIC) +const pm_char STR_HAPTIC_LABEL[] PROGMEM = TR_HAPTIC_LABEL; +const pm_char STR_HAPTICSTRENGTH[] PROGMEM = TR_HAPTICSTRENGTH; +#endif +const pm_char STR_CONTRAST[] PROGMEM = TR_CONTRAST; +const pm_char STR_ALARMS_LABEL[] PROGMEM = TR_ALARMS_LABEL; +#if defined(BATTGRAPH) || defined(PCBTARANIS) +const pm_char STR_BATTERY_RANGE[] PROGMEM = TR_BATTERY_RANGE; +#endif +const pm_char STR_BATTERYWARNING[] PROGMEM = TR_BATTERYWARNING; +const pm_char STR_INACTIVITYALARM[] PROGMEM = TR_INACTIVITYALARM; +const pm_char STR_MEMORYWARNING[] PROGMEM = TR_MEMORYWARNING; +const pm_char STR_ALARMWARNING[] PROGMEM = TR_ALARMWARNING; +#if defined(ROTARY_ENCODERS) +const pm_char STR_RENAVIG[] PROGMEM = TR_RENAVIG; +#endif +const pm_char STR_THROTTLEREVERSE[] PROGMEM = TR_THROTTLEREVERSE; +const pm_char STR_MINUTEBEEP[] PROGMEM = TR_MINUTEBEEP; +const pm_char STR_BEEPCOUNTDOWN[] PROGMEM = TR_BEEPCOUNTDOWN; +const pm_char STR_PERSISTENT[] PROGMEM = TR_PERSISTENT; +const pm_char STR_BACKLIGHT_LABEL[] PROGMEM = TR_BACKLIGHT_LABEL; +const pm_char STR_BLDELAY[] PROGMEM = TR_BLDELAY; + +#if defined(PWM_BACKLIGHT) +const pm_char STR_BLONBRIGHTNESS[] PROGMEM = TR_BLONBRIGHTNESS; +const pm_char STR_BLOFFBRIGHTNESS[] PROGMEM = TR_BLOFFBRIGHTNESS; +#endif + +const pm_char STR_SPLASHSCREEN[] PROGMEM = TR_SPLASHSCREEN; +const pm_char STR_THROTTLEWARNING[] PROGMEM = TR_THROTTLEWARNING; +const pm_char STR_SWITCHWARNING[] PROGMEM = TR_SWITCHWARNING; +#ifdef FRSKY +const pm_char STR_TIMEZONE[] PROGMEM = TR_TIMEZONE; +const pm_char STR_GPSCOORD[] PROGMEM = TR_GPSCOORD; +const pm_char STR_VARIO[] PROGMEM = TR_VARIO; +#endif +const pm_char STR_RXCHANNELORD[] PROGMEM = TR_RXCHANNELORD; +const pm_char STR_SLAVE[] PROGMEM = TR_SLAVE; +const pm_char STR_MODESRC[] PROGMEM = TR_MODESRC; +const pm_char STR_MULTIPLIER[] PROGMEM = TR_MULTIPLIER; +const pm_char STR_CAL[] PROGMEM = TR_CAL; +const pm_char STR_VTRIM[] PROGMEM = TR_VTRIM; +const pm_char STR_BG[] PROGMEM = TR_BG; +const pm_char STR_MENUTOSTART[] PROGMEM = TR_MENUTOSTART; +const pm_char STR_SETMIDPOINT[] PROGMEM = TR_SETMIDPOINT; +const pm_char STR_MOVESTICKSPOTS[] PROGMEM = TR_MOVESTICKSPOTS; +const pm_char STR_RXBATT[] PROGMEM = TR_RXBATT; +const pm_char STR_TX[] PROGMEM = TR_TXnRX; +const pm_char STR_ACCEL[] PROGMEM = TR_ACCEL; +const pm_char STR_NODATA[] PROGMEM = TR_NODATA; +const pm_char STR_TM1TM2[] PROGMEM = TR_TM1TM2; +const pm_char STR_THRTHP[] PROGMEM = TR_THRTHP; +const pm_char STR_TOT[] PROGMEM = TR_TOT; +const pm_char STR_TMR1LATMAXUS[] PROGMEM = TR_TMR1LATMAXUS; +const pm_char STR_TMR1LATMINUS[] PROGMEM = TR_TMR1LATMINUS; +const pm_char STR_TMR1JITTERUS[] PROGMEM = TR_TMR1JITTERUS; +const pm_char STR_TMIXMAXMS[] PROGMEM = TR_TMIXMAXMS; +const pm_char STR_FREESTACKMINB[] PROGMEM = TR_FREESTACKMINB; +const pm_char STR_MENUTORESET[] PROGMEM = TR_MENUTORESET; +const pm_char STR_PPM[] PROGMEM = TR_PPM; +const pm_char STR_CH[] PROGMEM = TR_CH; +const pm_char STR_MODEL[] PROGMEM = TR_MODEL; +const pm_char STR_FP[] PROGMEM = TR_FP; +const pm_char STR_MIX[] PROGMEM = TR_MIX; +const pm_char STR_EEPROMLOWMEM[] PROGMEM = TR_EEPROMLOWMEM; +const pm_char STR_ALERT[] PROGMEM = TR_ALERT; +const pm_char STR_PRESSANYKEYTOSKIP[] PROGMEM = TR_PRESSANYKEYTOSKIP; +const pm_char STR_THROTTLENOTIDLE[] PROGMEM = TR_THROTTLENOTIDLE; +const pm_char STR_ALARMSDISABLED[] PROGMEM = TR_ALARMSDISABLED; +const pm_char STR_PRESSANYKEY[] PROGMEM = TR_PRESSANYKEY; +const pm_char STR_BADEEPROMDATA[] PROGMEM = TR_BADEEPROMDATA; +const pm_char STR_EEPROMFORMATTING[] PROGMEM = TR_EEPROMFORMATTING; +const pm_char STR_EEPROMOVERFLOW[] PROGMEM = TR_EEPROMOVERFLOW; +const pm_char STR_TRIMS2OFFSETS[] PROGMEM = TR_TRIMS2OFFSETS; +const pm_char STR_MENURADIOSETUP[] PROGMEM = TR_MENURADIOSETUP; + +#if defined(CPUM2560) || defined(CPUARM) +const pm_char STR_MENUDATEANDTIME[] PROGMEM = TR_MENUDATEANDTIME; +#endif + +const pm_char STR_MENUTRAINER[] PROGMEM = TR_MENUTRAINER; +const pm_char STR_MENUVERSION[] PROGMEM = TR_MENUVERSION; +const pm_char STR_MENUDIAG[] PROGMEM = TR_MENUDIAG; +const pm_char STR_MENUANA[] PROGMEM = TR_MENUANA; +const pm_char STR_MENUCALIBRATION[] PROGMEM = TR_MENUCALIBRATION; + +const pm_char STR_MENUMODELSEL[] PROGMEM = TR_MENUMODELSEL; +const pm_char STR_MENUSETUP[] PROGMEM = TR_MENUSETUP; +const pm_char STR_MENUFLIGHTPHASE[] PROGMEM = TR_MENUFLIGHTPHASE; +const pm_char STR_MENUFLIGHTPHASES[] PROGMEM = TR_MENUFLIGHTPHASES; + +#ifdef HELI +const pm_char STR_MENUHELISETUP[] PROGMEM = TR_MENUHELISETUP; +#endif + +const pm_char STR_MENUINPUTS[] PROGMEM = TR_MENUINPUTS; +const pm_char STR_MENULIMITS[] PROGMEM = TR_MENULIMITS; +const pm_char STR_MENUCURVES[] PROGMEM = TR_MENUCURVES; +const pm_char STR_MENUCURVE[] PROGMEM = TR_MENUCURVE; +const pm_char STR_MENUCUSTOMSWITCH[] PROGMEM = TR_MENUCUSTOMSWITCH; +const pm_char STR_MENUCUSTOMSWITCHES[] PROGMEM = TR_MENUCUSTOMSWITCHES; +const pm_char STR_MENUCUSTOMFUNC[] PROGMEM = TR_MENUCUSTOMFUNC; + +#if defined(LUA) +const pm_char STR_MENUCUSTOMSCRIPTS[] PROGMEM = "CUSTOM SCRIPTS"; +const pm_char STR_MENUCUSTOMSCRIPT[] PROGMEM = "CUSTOM SCRIPT"; +#endif + +#if defined(FRSKY) +const pm_char STR_MENUTELEMETRY[] PROGMEM = TR_MENUTELEMETRY; +const pm_char STR_LIMIT[] PROGMEM = TR_LIMIT; +#endif + +#if defined(TEMPLATES) +const pm_char STR_MENUTEMPLATES[] PROGMEM = TR_MENUTEMPLATES; +#endif + +const pm_char STR_MENUSTAT[] PROGMEM = TR_MENUSTAT; +const pm_char STR_MENUDEBUG[] PROGMEM = TR_MENUDEBUG; +const pm_char STR_MENUGLOBALVARS[] PROGMEM = TR_MENUGLOBALVARS; + +#if defined(DSM2) || defined(PXX) +const pm_char STR_RXNUM[] PROGMEM = TR_RXNUM; +#endif + +#if defined(PXX) +const pm_char STR_SYNCMENU[] PROGMEM = TR_SYNCMENU; +const pm_char STR_INTERNALRF[] PROGMEM = TR_INTERNALRF; +const pm_char STR_EXTERNALRF[] PROGMEM = TR_EXTERNALRF; +const pm_char STR_COUNTRYCODE[] PROGMEM = TR_COUNTRYCODE; +const pm_char STR_FAILSAFE[] PROGMEM = TR_FAILSAFE; +const pm_char STR_FAILSAFESET[] PROGMEM = TR_FAILSAFESET; +#endif + +const pm_char STR_INVERT_THR[] PROGMEM = TR_INVERT_THR; +const pm_char STR_AND_SWITCH[] PROGMEM = TR_AND_SWITCH; +extern const pm_char STR_CF[] PROGMEM = TR_CF; + +#if defined(FRSKY_HUB) +const pm_char STR_MINRSSI[] PROGMEM = TR_MINRSSI; +const pm_char STR_LATITUDE[] PROGMEM = TR_LATITUDE; +const pm_char STR_LONGITUDE[] PROGMEM = TR_LONGITUDE; +#endif + +#if defined(CPUARM) || defined(CPUM2560) +const pm_char STR_SHUTDOWN[] PROGMEM = TR_SHUTDOWN; +#endif + +const pm_char STR_BATT_CALIB[] PROGMEM = TR_BATT_CALIB; + +#if defined(CPUARM) || defined(FRSKY) +const pm_char STR_VOLTAGE[] PROGMEM = TR_VOLTAGE; +const pm_char STR_CURRENT[] PROGMEM = TR_CURRENT; +#endif + +#if defined(CPUARM) +const pm_char STR_CURRENT_CALIB[] PROGMEM = TR_CURRENT_CALIB; +const pm_char STR_UNITSSYSTEM[] PROGMEM = TR_UNITSSYSTEM; +const pm_char STR_VOICELANG[] PROGMEM = TR_VOICELANG; +const pm_char STR_MODELIDUSED[] PROGMEM = TR_MODELIDUSED; +const pm_char STR_BEEP_VOLUME[] PROGMEM = INDENT TR_BEEP_VOLUME; +const pm_char STR_WAV_VOLUME[] PROGMEM = INDENT TR_WAV_VOLUME; +const pm_char STR_VARIO_VOLUME[] PROGMEM = INDENT TR_VARIO_VOLUME; +const pm_char STR_BG_VOLUME[] PROGMEM = INDENT TR_BG_VOLUME; +const pm_char STR_PERSISTENT_MAH[] PROGMEM = TR_PERSISTENT_MAH; +#endif + +#if defined(NAVIGATION_MENUS) +const pm_char STR_SELECT_MODEL[] PROGMEM = TR_SELECT_MODEL; +const pm_char STR_CREATE_MODEL[] PROGMEM = TR_CREATE_MODEL; +const pm_char STR_COPY_MODEL[] PROGMEM = TR_COPY_MODEL; +const pm_char STR_MOVE_MODEL[] PROGMEM = TR_MOVE_MODEL; +const pm_char STR_DELETE_MODEL[] PROGMEM = TR_DELETE_MODEL; +const pm_char STR_EDIT[] PROGMEM = TR_EDIT; +const pm_char STR_INSERT_BEFORE[] PROGMEM = TR_INSERT_BEFORE; +const pm_char STR_INSERT_AFTER[] PROGMEM = TR_INSERT_AFTER; +const pm_char STR_COPY[] PROGMEM = TR_COPY; +const pm_char STR_MOVE[] PROGMEM = TR_MOVE; +const pm_char STR_PASTE[] PROGMEM = TR_PASTE; +const pm_char STR_INSERT[] PROGMEM = TR_INSERT; +const pm_char STR_DELETE[] PROGMEM = TR_DELETE; +const pm_char STR_RESET_FLIGHT[] PROGMEM = TR_RESET_FLIGHT; +const pm_char STR_RESET_TIMER1[] PROGMEM = TR_RESET_TIMER1; +const pm_char STR_RESET_TIMER2[] PROGMEM = TR_RESET_TIMER2; +const pm_char STR_RESET_TELEMETRY[] PROGMEM = TR_RESET_TELEMETRY; +const pm_char STR_STATISTICS[] PROGMEM = TR_STATISTICS; +const pm_char STR_ABOUT_US[] PROGMEM = TR_ABOUT_US; +#endif + +const pm_char STR_RESET_BTN[] PROGMEM = TR_RESET_BTN; + +#if defined(SDCARD) +const pm_char STR_BACKUP_MODEL[] PROGMEM = TR_BACKUP_MODEL; +const pm_char STR_RESTORE_MODEL[] PROGMEM = TR_RESTORE_MODEL; +const pm_char STR_SDCARD_ERROR[] PROGMEM = TR_SDCARD_ERROR; +const pm_char STR_NO_SDCARD[] PROGMEM = TR_NO_SDCARD; +const pm_char STR_INCOMPATIBLE[] PROGMEM = TR_INCOMPATIBLE; +const pm_char STR_LOGS_PATH[] PROGMEM = LOGS_PATH; +const pm_char STR_LOGS_EXT[] PROGMEM = LOGS_EXT; +const pm_char STR_MODELS_PATH[] PROGMEM = MODELS_PATH; +const pm_char STR_MODELS_EXT[] PROGMEM = MODELS_EXT; +#endif + +const pm_char STR_WARNING[] PROGMEM = TR_WARNING; +const pm_char STR_EEPROMWARN[] PROGMEM = TR_EEPROMWARN; +const pm_char STR_THROTTLEWARN[] PROGMEM = TR_THROTTLEWARN; +const pm_char STR_ALARMSWARN[] PROGMEM = TR_ALARMSWARN; +const pm_char STR_SWITCHWARN[] PROGMEM = TR_SWITCHWARN; + +const pm_char STR_SPEAKER_VOLUME[] PROGMEM = TR_SPEAKER_VOLUME; +const pm_char STR_LCD[] PROGMEM = TR_LCD; +const pm_char STR_BRIGHTNESS[] PROGMEM = TR_BRIGHTNESS; +const pm_char STR_CPU_TEMP[] PROGMEM = TR_CPU_TEMP; +const pm_char STR_CPU_CURRENT[] PROGMEM = TR_CPU_CURRENT; +const pm_char STR_CPU_MAH[] PROGMEM = TR_CPU_MAH; +const pm_char STR_COPROC[] PROGMEM = TR_COPROC; +const pm_char STR_COPROC_TEMP[] PROGMEM = TR_COPROC_TEMP; +const pm_char STR_TEMPWARNING[] PROGMEM = TR_TEMPWARNING; +const pm_char STR_CAPAWARNING[] PROGMEM = TR_CAPAWARNING; +const pm_char STR_FUNC[] PROGMEM = TR_FUNC; +const pm_char STR_V1[] PROGMEM = TR_V1; +const pm_char STR_V2[] PROGMEM = TR_V2; +const pm_char STR_DURATION[] PROGMEM = TR_DURATION; +const pm_char STR_DELAY[] PROGMEM = TR_DELAY; +const pm_char STR_SD_CARD[] PROGMEM = TR_SD_CARD; +const pm_char STR_SDHC_CARD[] PROGMEM = TR_SDHC_CARD; +const pm_char STR_NO_SOUNDS_ON_SD[] PROGMEM = TR_NO_SOUNDS_ON_SD; +const pm_char STR_NO_MODELS_ON_SD[] PROGMEM = TR_NO_MODELS_ON_SD; +const pm_char STR_NO_BITMAPS_ON_SD[] PROGMEM = TR_NO_BITMAPS_ON_SD; +const pm_char STR_NO_SCRIPTS_ON_SD[] PROGMEM = "No Scripts on SD"; // TODO TR_NO_BITMAPS_ON_SD; +const pm_char STR_PLAY_FILE[] PROGMEM = TR_PLAY_FILE; +const pm_char STR_ASSIGN_BITMAP[] PROGMEM = TR_ASSIGN_BITMAP; +const pm_char STR_EXECUTE_FILE[] PROGMEM = "Execute"; +const pm_char STR_DELETE_FILE[] PROGMEM = TR_DELETE_FILE; +const pm_char STR_COPY_FILE[] PROGMEM = TR_COPY_FILE; +const pm_char STR_RENAME_FILE[] PROGMEM = TR_RENAME_FILE; +const pm_char STR_SD_INFO[] PROGMEM = TR_SD_INFO; +const pm_char STR_SD_FORMAT[] PROGMEM = TR_SD_FORMAT; +const pm_char STR_REMOVED[] PROGMEM = TR_REMOVED; +const pm_char STR_NA[] PROGMEM = TR_NA; +const pm_char STR_HARDWARE[] PROGMEM = TR_HARDWARE; +const pm_char STR_FORMATTING[] PROGMEM = TR_FORMATTING; +const pm_char STR_TEMP_CALIB[] PROGMEM = TR_TEMP_CALIB; +const pm_char STR_TIME[] PROGMEM = TR_TIME; +const pm_char STR_BAUDRATE[] PROGMEM = TR_BAUDRATE; +const pm_char STR_SD_INFO_TITLE[] PROGMEM = TR_SD_INFO_TITLE; +const pm_char STR_SD_TYPE[] PROGMEM = TR_SD_TYPE; +const pm_char STR_SD_SPEED[] PROGMEM = TR_SD_SPEED; +const pm_char STR_SD_SECTORS[] PROGMEM = TR_SD_SECTORS; +const pm_char STR_SD_SIZE[] PROGMEM = TR_SD_SIZE; +const pm_char STR_TYPE[] PROGMEM = TR_TYPE; +const pm_char STR_GLOBAL_VARS[] PROGMEM = TR_GLOBAL_VARS; +const pm_char STR_GLOBAL_VAR[] PROGMEM = TR_GLOBAL_VAR; +const pm_char STR_OWN[] PROGMEM = TR_OWN; +const pm_char STR_ROTARY_ENCODER[] PROGMEM = TR_ROTARY_ENCODER; +const pm_char STR_DATE[] PROGMEM = TR_DATE; +const pm_char STR_CHANNELS_MONITOR[] PROGMEM = TR_CHANNELS_MONITOR; +const pm_char STR_PATH_TOO_LONG[] PROGMEM = "Path too long"; +const pm_char STR_VIEW_TEXT[] PROGMEM = "View text"; + +#if LCD_W >= 212 + const pm_char STR_MODELNAME[] PROGMEM = TR_MODELNAME; + const pm_char STR_PHASENAME[] PROGMEM = TR_PHASENAME; + const pm_char STR_MIXNAME[] PROGMEM = TR_MIXNAME; + const pm_char STR_EXPONAME[] PROGMEM = TR_EXPONAME; +#endif + +#if LCD_W >= 212 + const char * STR_PHASES_HEADERS[] = TR_PHASES_HEADERS; + const char * STR_LIMITS_HEADERS[] = TR_LIMITS_HEADERS; + const char * STR_CSW_HEADERS[] = TR_CSW_HEADERS; +#endif + +#if defined(PCBTARANIS) + const pm_char STR_BYTES[] PROGMEM = TR_BYTES; + const pm_char STR_MODULE_BIND[] PROGMEM = TR_MODULE_BIND; + const pm_char STR_SET[] PROGMEM = TR_SET; + const pm_char STR_TRAINER[] PROGMEM = TR_TRAINER; + const pm_char STR_ANTENNAPROBLEM[] PROGMEM = TR_ANTENNAPROBLEM; + const pm_char STR_MODULE[] PROGMEM = TR_MODULE; + const pm_char STR_CHANNELRANGE[] PROGMEM = TR_CHANNELRANGE; + const pm_char STR_LOWALARM[] PROGMEM = TR_LOWALARM; + const pm_char STR_CRITICALALARM[] PROGMEM = TR_CRITICALALARM; + const pm_char STR_ENABLE_POPUP[] PROGMEM = "Enable Popup"; + const pm_char STR_DISABLE_POPUP[] PROGMEM = "Disable Popup"; + const pm_char STR_CURVE_PRESET[] PROGMEM = "Preset..."; + const pm_char STR_PRESET[] PROGMEM = "Preset"; + const pm_char STR_MIRROR[] PROGMEM = "Mirror"; + const pm_char STR_CLEAR[] PROGMEM = "Clear"; + const pm_char STR_RESET[] PROGMEM = "Reset"; + const pm_char STR_COPY_TRIMS_TO_OFFSET[] = "Copy Trims To Offset"; + const pm_char STR_TOP_BAR[] PROGMEM = "Top Bar"; + const pm_char STR_ALTITUDE[] PROGMEM = INDENT "Altitude"; + const pm_char STR_SCALE[] PROGMEM = "Scale"; + const pm_char STR_VIEW_CHANNELS[] PROGMEM = "View Channels"; + const pm_char STR_VIEW_NOTES[] PROGMEM = "View Notes"; +#endif + +#if MENUS_LOCK == 1 + const pm_char STR_UNLOCKED[] PROGMEM = TR_UNLOCKED; + const pm_char STR_MODS_FORBIDDEN[] PROGMEM = TR_MODS_FORBIDDEN; +#endif + +#if defined(PCBTARANIS) || defined(DSM2) + const pm_char STR_MODULE_RANGE[] PROGMEM = TR_MODULE_RANGE; +#endif + +#if defined(MAVLINK) + const pm_char STR_MAVLINK_RC_RSSI_SCALE_LABEL[] PROGMEM = TR_MAVLINK_RC_RSSI_SCALE_LABEL; + const pm_char STR_MAVLINK_PC_RSSI_EN_LABEL[] PROGMEM = TR_MAVLINK_PC_RSSI_EN_LABEL; + const pm_char STR_MAVMENUSETUP_TITLE[] PROGMEM = TR_MAVMENUSETUP_TITLE; + const pm_char STR_MAVLINK_BAUD_LABEL[] PROGMEM = TR_MAVLINK_BAUD_LABEL; + const pm_char STR_MAVLINK_INFOS[] PROGMEM = TR_MAVLINK_INFOS; + const pm_char STR_MAVLINK_MODE[] PROGMEM = TR_MAVLINK_MODE; + const pm_char STR_MAVLINK_CUR_MODE[] PROGMEM = TR_MAVLINK_CUR_MODE; + const pm_char STR_MAVLINK_ARMED[] PROGMEM = TR_MAVLINK_ARMED; + const pm_char STR_MAVLINK_BAT_MENU_TITLE[] PROGMEM = TR_MAVLINK_BAT_MENU_TITLE; + const pm_char STR_MAVLINK_BATTERY_LABEL[] PROGMEM = TR_MAVLINK_BATTERY_LABEL; + const pm_char STR_MAVLINK_RC_RSSI_LABEL[] PROGMEM = TR_MAVLINK_RC_RSSI_LABEL; + const pm_char STR_MAVLINK_PC_RSSI_LABEL[] PROGMEM = TR_MAVLINK_PC_RSSI_LABEL; + const pm_char STR_MAVLINK_NAV_MENU_TITLE[] PROGMEM = TR_MAVLINK_NAV_MENU_TITLE; + const pm_char STR_MAVLINK_COURSE[] PROGMEM = TR_MAVLINK_COURSE; + const pm_char STR_MAVLINK_HEADING[] PROGMEM = TR_MAVLINK_HEADING; + const pm_char STR_MAVLINK_BEARING[] PROGMEM = TR_MAVLINK_BEARING; + const pm_char STR_MAVLINK_ALTITUDE[] PROGMEM = TR_MAVLINK_ALTITUDE; + const pm_char STR_MAVLINK_GPS[] PROGMEM = TR_MAVLINK_GPS; + const pm_char STR_MAVLINK_NO_FIX[] PROGMEM = TR_MAVLINK_NO_FIX; + const pm_char STR_MAVLINK_SAT[] PROGMEM = TR_MAVLINK_SAT; + const pm_char STR_MAVLINK_HDOP[] PROGMEM = TR_MAVLINK_HDOP; + const pm_char STR_MAVLINK_LAT[] PROGMEM = TR_MAVLINK_LAT; + const pm_char STR_MAVLINK_LON[] PROGMEM = TR_MAVLINK_LON; +#endif + +#if !defined(CPUM64) + const pm_char STR_ABOUTUS[] PROGMEM = TR_ABOUTUS; + const pm_char STR_ABOUT_OPENTX_1[] PROGMEM = TR_ABOUT_OPENTX_1; + const pm_char STR_ABOUT_OPENTX_2[] PROGMEM = TR_ABOUT_OPENTX_2; + const pm_char STR_ABOUT_OPENTX_3[] PROGMEM = TR_ABOUT_OPENTX_3; + const pm_char STR_ABOUT_OPENTX_4[] PROGMEM = TR_ABOUT_OPENTX_4; + const pm_char STR_ABOUT_OPENTX_5[] PROGMEM = TR_ABOUT_OPENTX_5; + + const pm_char STR_ABOUT_BERTRAND_1[] PROGMEM = TR_ABOUT_BERTRAND_1; + const pm_char STR_ABOUT_BERTRAND_2[] PROGMEM = TR_ABOUT_BERTRAND_2; + const pm_char STR_ABOUT_BERTRAND_3[] PROGMEM = TR_ABOUT_BERTRAND_3; + + const pm_char STR_ABOUT_MIKE_1[] PROGMEM = TR_ABOUT_MIKE_1; + const pm_char STR_ABOUT_MIKE_2[] PROGMEM = TR_ABOUT_MIKE_2; + const pm_char STR_ABOUT_MIKE_3[] PROGMEM = TR_ABOUT_MIKE_3; + const pm_char STR_ABOUT_MIKE_4[] PROGMEM = TR_ABOUT_MIKE_4; + + const pm_char STR_ABOUT_ROMOLO_1[] PROGMEM = TR_ABOUT_ROMOLO_1; + const pm_char STR_ABOUT_ROMOLO_2[] PROGMEM = TR_ABOUT_ROMOLO_2; + const pm_char STR_ABOUT_ROMOLO_3[] PROGMEM = TR_ABOUT_ROMOLO_3; + + const pm_char STR_ABOUT_ANDRE_1[] PROGMEM = TR_ABOUT_ANDRE_1; + const pm_char STR_ABOUT_ANDRE_2[] PROGMEM = TR_ABOUT_ANDRE_2; + const pm_char STR_ABOUT_ANDRE_3[] PROGMEM = TR_ABOUT_ANDRE_3; + + const pm_char STR_ABOUT_ROB_1[] PROGMEM = TR_ABOUT_ROB_1; + const pm_char STR_ABOUT_ROB_2[] PROGMEM = TR_ABOUT_ROB_2; + + const pm_char STR_ABOUT_MARTIN_1[] PROGMEM = TR_ABOUT_MARTIN_1; + const pm_char STR_ABOUT_MARTIN_2[] PROGMEM = TR_ABOUT_MARTIN_2; + + const pm_char STR_ABOUT_HARDWARE_1[] PROGMEM = TR_ABOUT_HARDWARE_1; + const pm_char STR_ABOUT_HARDWARE_2[] PROGMEM = TR_ABOUT_HARDWARE_2; + const pm_char STR_ABOUT_HARDWARE_3[] PROGMEM = TR_ABOUT_HARDWARE_3; + + const pm_char STR_ABOUT_PARENTS_1[] PROGMEM = TR_ABOUT_PARENTS_1; + const pm_char STR_ABOUT_PARENTS_2[] PROGMEM = TR_ABOUT_PARENTS_2; + const pm_char STR_ABOUT_PARENTS_3[] PROGMEM = TR_ABOUT_PARENTS_3; + const pm_char STR_ABOUT_PARENTS_4[] PROGMEM = TR_ABOUT_PARENTS_4; +#endif + +const pm_uchar font_5x7[] PROGMEM = { +#include "font_05x07.lbm" +#if defined(TRANSLATIONS_DE) +#include "font_de_05x07.lbm" +#elif defined(TRANSLATIONS_CZ) +#include "font_cz_05x07.lbm" +#elif defined(TRANSLATIONS_ES) +#include "font_es_05x07.lbm" +#elif defined(TRANSLATIONS_FR) +#include "font_fr_05x07.lbm" +#elif defined(TRANSLATIONS_IT) +#include "font_it_05x07.lbm" +#elif defined(TRANSLATIONS_PL) +#include "font_pl_05x07.lbm" +#elif defined(TRANSLATIONS_PT) +#include "font_pt_05x07.lbm" +#elif defined(TRANSLATIONS_SE) +#include "font_se_05x07.lbm" +#endif +}; + +const pm_uchar font_10x14[] PROGMEM = { +#include "font_10x14_compressed.lbm" +#if defined(CPUARM) + #if defined(TRANSLATIONS_DE) + #include "font_de_10x14.lbm" + #elif defined(TRANSLATIONS_CZ) + #include "font_cz_10x14.lbm" + #elif defined(TRANSLATIONS_ES) + #include "font_es_10x14.lbm" + #elif defined(TRANSLATIONS_FR) + #include "font_fr_10x14.lbm" + #elif defined(TRANSLATIONS_IT) + #include "font_it_10x14.lbm" + #elif defined(TRANSLATIONS_PL) + #include "font_pl_10x14.lbm" + #elif defined(TRANSLATIONS_PT) + #include "font_pt_10x14.lbm" + #elif defined(TRANSLATIONS_SE) + #include "font_se_10x14.lbm" + #endif +#endif +}; + +#if defined(CPUARM) +const pm_uchar font_3x5[] PROGMEM = { +#include "font_03x05.lbm" +}; + +const pm_uchar font_4x6[] PROGMEM = { +#include "font_04x06.lbm" +#if defined(TRANSLATIONS_DE) +#include "font_de_04x06.lbm" +#elif defined(TRANSLATIONS_CZ) +#include "font_cz_04x06.lbm" +#elif defined(TRANSLATIONS_ES) +#include "font_es_04x06.lbm" +#elif defined(TRANSLATIONS_FR) +#include "font_fr_04x06.lbm" +#elif defined(TRANSLATIONS_IT) +#include "font_it_04x06.lbm" +#elif defined(TRANSLATIONS_PL) +#include "font_pl_04x06.lbm" +#elif defined(TRANSLATIONS_PT) +#include "font_pt_04x06.lbm" +#elif defined(TRANSLATIONS_SE) +#include "font_se_04x06.lbm" +#endif +}; + +const pm_uchar font_8x10[] PROGMEM = { +#include "font_08x10.lbm" +#if defined(TRANSLATIONS_DE) +#include "font_de_08x10.lbm" +#elif defined(TRANSLATIONS_CZ) +#include "font_cz_08x10.lbm" +#elif defined(TRANSLATIONS_ES) +#include "font_es_08x10.lbm" +#elif defined(TRANSLATIONS_FR) +#include "font_fr_08x10.lbm" +#elif defined(TRANSLATIONS_IT) +#include "font_it_08x10.lbm" +#elif defined(TRANSLATIONS_PL) +#include "font_pl_08x10.lbm" +#elif defined(TRANSLATIONS_PT) +#include "font_pt_08x10.lbm" +#elif defined(TRANSLATIONS_SE) +#include "font_se_08x10.lbm" +#endif +}; + +const pm_uchar font_4x6_extra[] PROGMEM = { +#include "font_04x06_extra.lbm" +}; + +const pm_uchar font_5x7_extra[] PROGMEM = { +#include "font_05x07_extra.lbm" +}; + +const pm_uchar font_10x14_extra[] PROGMEM = { +#include "font_10x14_extra.lbm" +}; + +#endif + diff --git a/radio/src/translations.h b/radio/src/translations.h index 4a3e0600a..b49bb005d 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -343,6 +343,8 @@ extern const pm_char STR_BAR[]; extern const pm_char STR_ALARM[]; extern const pm_char STR_USRDATA[]; extern const pm_char STR_BLADES[]; +extern const pm_char STR_SPURGEAR[]; // T.Foley +extern const pm_char STR_PINIONGEAR[]; // T.Foley extern const pm_char STR_SCREEN[]; extern const pm_char STR_SOUND_LABEL[]; extern const pm_char STR_LENGTH[]; diff --git a/radio/src/translations.h~ b/radio/src/translations.h~ new file mode 100644 index 000000000..4a3e0600a --- /dev/null +++ b/radio/src/translations.h~ @@ -0,0 +1,754 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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 translations_h +#define translations_h + +#if defined(TRANSLATIONS_FR) +#include "translations/fr.h" +#define LEN_SPECIAL_CHARS 3 +#elif defined(TRANSLATIONS_IT) +#include "translations/it.h" +#define LEN_SPECIAL_CHARS 1 +#elif defined(TRANSLATIONS_SE) +#include "translations/se.h" +#define LEN_SPECIAL_CHARS 6 +#elif defined(TRANSLATIONS_DE) +#include "translations/de.h" +#define LEN_SPECIAL_CHARS 6 +#elif defined(TRANSLATIONS_CZ) +#include "translations/cz.h" +#define LEN_SPECIAL_CHARS 0 +#elif defined(TRANSLATIONS_ES) +#include "translations/es.h" +#define LEN_SPECIAL_CHARS 0 +#elif defined(TRANSLATIONS_PL) +#include "translations/pl.h" +#define LEN_SPECIAL_CHARS 0 +#elif defined(TRANSLATIONS_PT) +#include "translations/pt.h" +#define LEN_SPECIAL_CHARS 0 +#else +#include "translations/en.h" +#define LEN_SPECIAL_CHARS 0 +#endif + +#define PSIZE(x) ( sizeof(x) - 1 ) +#define EOFS(x) ( OFS_##x + sizeof(TR_##x) ) + +#if LCD_W >= 212 + #define TR(x,y) y +#else + #define TR(x,y) x +#endif + +// The non-0-terminated-strings + +extern const pm_char STR_OPEN9X[]; + +#define OFS_OFFON 0 +#define OFS_MMMINV (OFS_OFFON + sizeof(TR_OFFON)) +#define OFS_NCHANNELS (OFS_MMMINV + sizeof(TR_MMMINV)) +#if defined(GRAPHICS) +#define OFS_VBEEPMODE (OFS_NCHANNELS + sizeof(TR_NCHANNELS)) +#else +#define OFS_VBEEPLEN (OFS_NCHANNELS + sizeof(TR_NCHANNELS)) +#define OFS_VBEEPMODE (OFS_VBEEPLEN + sizeof(TR_VBEEPLEN)) +#endif +#if defined(ROTARY_ENCODERS) +#define OFS_VRENAVIG (OFS_VBEEPMODE + sizeof(TR_VBEEPMODE)) +#define OFS_VRENCODERS (OFS_VRENAVIG + sizeof(TR_VRENAVIG)) +#define OFS_TRNMODE (OFS_VRENCODERS + sizeof(TR_VRENCODERS)) +#elif defined(ROTARY_ENCODER_NAVIGATION) +#define OFS_VRENCODERS (OFS_VBEEPMODE + sizeof(TR_VBEEPMODE)) +#define OFS_TRNMODE (OFS_VRENCODERS + sizeof(TR_VRENCODERS)) +#else +#define OFS_TRNMODE (OFS_VBEEPMODE + sizeof(TR_VBEEPMODE)) +#endif +#define OFS_TRNCHN (OFS_TRNMODE + sizeof(TR_TRNMODE)) +#define OFS_VTRIMINC (OFS_TRNCHN + sizeof(TR_TRNCHN)) +#define OFS_RETA123 (OFS_VTRIMINC + sizeof(TR_VTRIMINC)) +#define OFS_VPROTOS (OFS_RETA123 + sizeof(TR_RETA123)) +#define OFS_POSNEG (OFS_VPROTOS + sizeof(TR_VPROTOS)) +#define OFS_VBLMODE (OFS_POSNEG + sizeof(TR_POSNEG)) +#define OFS_VCURVEFUNC (OFS_VBLMODE + sizeof(TR_VBLMODE)) +#define OFS_VMLTPX (OFS_VCURVEFUNC + sizeof(TR_VCURVEFUNC)) +#define OFS_VMLTPX2 (OFS_VMLTPX + sizeof(TR_VMLTPX)) +#define OFS_VMIXTRIMS (OFS_VMLTPX2 + sizeof(TR_VMLTPX2)) +#define OFS_VCSWFUNC (OFS_VMIXTRIMS + sizeof(TR_VMIXTRIMS)) +#define OFS_VFSWFUNC (OFS_VCSWFUNC + sizeof(TR_VCSWFUNC)) +#define OFS_VFSWRESET (OFS_VFSWFUNC + sizeof(TR_VFSWFUNC)) +#define OFS_FUNCSOUNDS (OFS_VFSWRESET + sizeof(TR_VFSWRESET)) +#define OFS_VTELEMCHNS (OFS_FUNCSOUNDS + sizeof(TR_FUNCSOUNDS)) +#if defined(FRSKY) || defined(CPUARM) + #if defined(CPUARM) + #define OFS_VTELEMUNIT_IMP (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS)) + #define OFS_VTELEMUNIT_NORM (OFS_VTELEMUNIT_IMP + sizeof(TR_VTELEMUNIT_IMP)) + #define OFS_VALARM (OFS_VTELEMUNIT_NORM + sizeof(TR_VTELEMUNIT_NORM)) + #else + #define OFS_VTELEMUNIT (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS)) + #define OFS_VALARM (OFS_VTELEMUNIT + sizeof(TR_VTELEMUNIT)) + #endif + #define OFS_VALARMFN (OFS_VALARM + sizeof(TR_VALARM)) + #define OFS_VTELPROTO (OFS_VALARMFN + sizeof(TR_VALARMFN)) + #define OFS_GPSFORMAT (OFS_VTELPROTO + sizeof(TR_VTELPROTO)) + #define OFS_VOLTSRC (OFS_GPSFORMAT + sizeof(TR_GPSFORMAT)) + #define OFS_VARIOSRC (OFS_VOLTSRC + sizeof(TR_VOLTSRC)) + #define OFS_VSCREEN (OFS_VARIOSRC + sizeof(TR_VARIOSRC)) + #define OFS_VTEMPLATES (OFS_VSCREEN + sizeof(TR_VSCREEN)) +#else + #define OFS_VTEMPLATES (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS)) +#endif +#if defined(TEMPLATES) + #define OFS_VSWASHTYPE (OFS_VTEMPLATES + sizeof(TR_VTEMPLATES)) +#else + #define OFS_VSWASHTYPE (OFS_VTEMPLATES) +#endif +#if defined(HELI) + #define OFS_VKEYS (OFS_VSWASHTYPE + sizeof(TR_VSWASHTYPE)) +#else + #define OFS_VKEYS (OFS_VSWASHTYPE) +#endif +#define OFS_VSWITCHES (OFS_VKEYS + sizeof(TR_VKEYS)) +#define OFS_VSRCRAW (OFS_VSWITCHES + sizeof(TR_VSWITCHES)) +#define OFS_VTMRMODES (OFS_VSRCRAW + sizeof(TR_VSRCRAW)) +#define OFS_DATETIME (OFS_VTMRMODES + sizeof(TR_VTMRMODES)) +#if defined(CPUM2560) || defined(CPUARM) + #define OFS_VLCD (OFS_DATETIME + sizeof(TR_DATETIME)) +#else + #define OFS_VLCD (OFS_DATETIME) +#endif +#if defined(CPUARM) + #define OFS_VUNITSSYSTEM (OFS_VLCD + sizeof(TR_VLCD)) + #define OFS_VBEEPCOUNTDOWN (OFS_VUNITSSYSTEM + sizeof(TR_VUNITSSYSTEM)) + #define OFS_COUNTRYCODES (OFS_VBEEPCOUNTDOWN + sizeof(TR_VBEEPCOUNTDOWN)) +#else + #define OFS_COUNTRYCODES (OFS_VLCD) +#endif +#if defined(PXX) + #define OFS_VFAILSAFE (OFS_COUNTRYCODES + sizeof(TR_COUNTRYCODES)) +#else + #define OFS_VFAILSAFE (OFS_COUNTRYCODES) +#endif +#if defined(PXX) + #define OFS_VTRAINERMODES (OFS_VFAILSAFE + sizeof(TR_VFAILSAFE)) +#else + #define OFS_VTRAINERMODES (OFS_VFAILSAFE) +#endif +#if defined(PCBTARANIS) + #define OFS_MAVLINK_BAUDS (OFS_VTRAINERMODES + sizeof(TR_VTRAINERMODES)) +#else + #define OFS_MAVLINK_BAUDS (OFS_VTRAINERMODES) +#endif +#if defined(MAVLINK) + #define OFS_MAVLINK_AC_MODES (OFS_MAVLINK_BAUDS + sizeof(TR_MAVLINK_BAUDS)) + #define OFS_MAVLINK_AP_MODES (OFS_MAVLINK_AC_MODES + sizeof(TR_MAVLINK_AC_MODES)) + #define OFS_SPARE (OFS_MAVLINK_AP_MODES + sizeof(TR_MAVLINK_AP_MODES)) +#else + #define OFS_SPARE (OFS_MAVLINK_BAUDS) +#endif + +#define STR_OFFON (STR_OPEN9X + OFS_OFFON) +#define STR_MMMINV (STR_OPEN9X + OFS_MMMINV) +#define STR_NCHANNELS (STR_OPEN9X + OFS_NCHANNELS) +#if !defined(GRAPHICS) +#define STR_VBEEPLEN (STR_OPEN9X + OFS_VBEEPLEN) +#endif +#define STR_VBEEPMODE (STR_OPEN9X + OFS_VBEEPMODE) +#define STR_TRNMODE (STR_OPEN9X + OFS_TRNMODE) +#define STR_TRNCHN (STR_OPEN9X + OFS_TRNCHN) +#define STR_VTRIMINC (STR_OPEN9X + OFS_VTRIMINC) +#define STR_RETA123 (STR_OPEN9X + OFS_RETA123) +#define STR_VPROTOS (STR_OPEN9X + OFS_VPROTOS) +#define STR_POSNEG (STR_OPEN9X + OFS_POSNEG) +#define STR_VBLMODE (STR_OPEN9X + OFS_VBLMODE) +#define STR_VCURVEFUNC (STR_OPEN9X + OFS_VCURVEFUNC) +#define STR_VSIDE STR_VCURVEFUNC +#define LEN_VSIDE LEN_VCURVEFUNC +#define STR_VMLTPX (STR_OPEN9X + OFS_VMLTPX) +#define STR_VMLTPX2 (STR_OPEN9X + OFS_VMLTPX2) +#define STR_VMIXTRIMS (STR_OPEN9X + OFS_VMIXTRIMS) +#define STR_VCSWFUNC (STR_OPEN9X + OFS_VCSWFUNC) +#define STR_VFSWFUNC (STR_OPEN9X + OFS_VFSWFUNC) +#define STR_VFSWRESET (STR_OPEN9X + OFS_VFSWRESET) +#define STR_FUNCSOUNDS (STR_OPEN9X + OFS_FUNCSOUNDS) +#define STR_VTELEMCHNS (STR_OPEN9X + OFS_VTELEMCHNS) + +#if defined(FRSKY) || defined(CPUARM) + #if defined(CPUARM) + #define STR_VTELEMUNIT (STR_OPEN9X + (g_eeGeneral.imperial ? OFS_VTELEMUNIT_IMP : OFS_VTELEMUNIT_NORM)) + #else + #define STR_VTELEMUNIT (STR_OPEN9X + OFS_VTELEMUNIT) + #endif +#define STR_VALARM (STR_OPEN9X + OFS_VALARM) +#define STR_VALARMFN (STR_OPEN9X + OFS_VALARMFN) +#define STR_VTELPROTO (STR_OPEN9X + OFS_VTELPROTO) +#define STR_GPSFORMAT (STR_OPEN9X + OFS_GPSFORMAT) +#define STR_VOLTSRC (STR_OPEN9X + OFS_VOLTSRC) +#define STR_VARIOSRC (STR_OPEN9X + OFS_VARIOSRC) +#define STR_VSCREEN (STR_OPEN9X + OFS_VSCREEN) +#define STR_TELEMCHNS (STR_OPEN9X + OFS_TELEMCHNS) +#endif + +#ifdef TEMPLATES +#define STR_VTEMPLATES (STR_OPEN9X + OFS_VTEMPLATES) +#endif + +#ifdef HELI +#define STR_VSWASHTYPE (STR_OPEN9X + OFS_VSWASHTYPE) +#endif + +#define STR_VKEYS (STR_OPEN9X + OFS_VKEYS) +#define STR_VSWITCHES (STR_OPEN9X + OFS_VSWITCHES) +#define STR_VSRCRAW (STR_OPEN9X + OFS_VSRCRAW) +#define STR_VTMRMODES (STR_OPEN9X + OFS_VTMRMODES) + +#if defined(ROTARY_ENCODERS) + #define STR_VRENAVIG (STR_OPEN9X + OFS_VRENAVIG) +#endif + +#if defined(ROTARY_ENCODER_NAVIGATION) + #define STR_VRENCODERS (STR_OPEN9X + OFS_VRENCODERS) +#endif + +#if defined(CPUM2560) || defined(CPUARM) +#define STR_DATETIME (STR_OPEN9X + OFS_DATETIME) +#endif + +#if defined(CPUARM) + #define STR_VLCD (STR_OPEN9X + OFS_VLCD) + #define STR_VUNITSSYSTEM (STR_OPEN9X + OFS_VUNITSSYSTEM) + #define STR_VBEEPCOUNTDOWN (STR_OPEN9X + OFS_VBEEPCOUNTDOWN) +#endif + +#if defined(PXX) + #define STR_COUNTRYCODES (STR_OPEN9X + OFS_COUNTRYCODES) + #define STR_VFAILSAFE (STR_OPEN9X + OFS_VFAILSAFE) +#endif + +#if defined(PCBTARANIS) + #define STR_VTRAINERMODES (STR_OPEN9X + OFS_VTRAINERMODES) +#endif + +#if defined(MAVLINK) + #define STR_MAVLINK_BAUDS (STR_OPEN9X + OFS_MAVLINK_BAUDS) + #define STR_MAVLINK_AC_MODES (STR_OPEN9X + OFS_MAVLINK_AC_MODES) + #define STR_MAVLINK_AP_MODES (STR_OPEN9X + OFS_MAVLINK_AP_MODES) +#endif + +// The 0-terminated-strings +#define NO_INDENT(x) (x)+LEN_INDENT + +extern const pm_char STR_POPUPS[]; +#define STR_EXIT (STR_POPUPS + OFS_EXIT) +extern const pm_char STR_MENUWHENDONE[]; +extern const pm_char STR_FREE[]; +#define LEN_FREE PSIZE(TR_FREE) +extern const pm_char STR_DELETEMODEL[]; +extern const pm_char STR_COPYINGMODEL[]; +extern const pm_char STR_MOVINGMODEL[]; +extern const pm_char STR_LOADINGMODEL[]; +extern const pm_char STR_NAME[]; +extern const pm_char STR_BITMAP[]; +extern const pm_char STR_TIMER[]; +extern const pm_char STR_ELIMITS[]; +extern const pm_char STR_ETRIMS[]; +extern const pm_char STR_TRIMINC[]; +extern const pm_char STR_TTRACE[]; +extern const pm_char STR_TTRIM[]; +extern const pm_char STR_BEEPCTR[]; +extern const pm_char STR_PROTO[]; +extern const pm_char STR_PPMFRAME[]; +extern const pm_char STR_MS[]; +extern const pm_char STR_SWITCH[]; +extern const pm_char STR_TRIMS[]; +extern const pm_char STR_FADEIN[]; +extern const pm_char STR_FADEOUT[]; +extern const pm_char STR_DEFAULT[]; +extern const pm_char STR_CHECKTRIMS[]; +extern const pm_char STR_SWASHTYPE[]; +extern const pm_char STR_COLLECTIVE[]; +extern const pm_char STR_SWASHRING[]; +extern const pm_char STR_ELEDIRECTION[]; +extern const pm_char STR_AILDIRECTION[]; +extern const pm_char STR_COLDIRECTION[]; +extern const pm_char STR_MODE[]; +#if defined(AUDIO) && defined(BUZZER) +extern const pm_char STR_SPEAKER[]; +extern const pm_char STR_BUZZER[]; +#else +#define STR_SPEAKER STR_MODE +#define STR_BUZZER STR_MODE +#endif +extern const pm_char STR_NOFREEEXPO[]; +extern const pm_char STR_NOFREEMIXER[]; +extern const pm_char STR_INSERTMIX[]; +extern const pm_char STR_EDITMIX[]; +extern const pm_char STR_SOURCE[]; +extern const pm_char STR_WEIGHT[]; +extern const pm_char STR_EXPO[]; +extern const pm_char STR_SIDE[]; +extern const pm_char STR_DIFFERENTIAL[]; +extern const pm_char STR_OFFSET[]; +extern const pm_char STR_TRIM[]; +extern const pm_char STR_DREX[]; +extern const pm_char STR_CURVE[]; +extern const pm_char STR_FLMODE[]; +extern const pm_char STR_MIXWARNING[]; +extern const pm_char STR_OFF[]; +extern const pm_char STR_MULTPX[]; +extern const pm_char STR_DELAYDOWN[]; +extern const pm_char STR_DELAYUP[]; +extern const pm_char STR_SLOWDOWN[]; +extern const pm_char STR_SLOWUP[]; +extern const pm_char STR_MIXER[]; +extern const pm_char STR_CV[]; +extern const pm_char STR_GV[]; +extern const pm_char STR_ACHANNEL[]; +extern const pm_char STR_RANGE[]; +extern const pm_char STR_BAR[]; +extern const pm_char STR_ALARM[]; +extern const pm_char STR_USRDATA[]; +extern const pm_char STR_BLADES[]; +extern const pm_char STR_SCREEN[]; +extern const pm_char STR_SOUND_LABEL[]; +extern const pm_char STR_LENGTH[]; +extern const pm_char STR_SPKRPITCH[]; +extern const pm_char STR_HAPTIC_LABEL[]; +extern const pm_char STR_HAPTICSTRENGTH[]; +extern const pm_char STR_CONTRAST[]; +extern const pm_char STR_ALARMS_LABEL[]; +#if defined(BATTGRAPH) || defined(PCBTARANIS) +extern const pm_char STR_BATTERY_RANGE[]; +#endif +extern const pm_char STR_BATTERYWARNING[]; +extern const pm_char STR_INACTIVITYALARM[]; +extern const pm_char STR_MEMORYWARNING[]; +extern const pm_char STR_ALARMWARNING[]; +extern const pm_char STR_RENAVIG[]; +extern const pm_char STR_THROTTLEREVERSE[]; +extern const pm_char STR_MINUTEBEEP[]; +extern const pm_char STR_BEEPCOUNTDOWN[]; +extern const pm_char STR_PERSISTENT[]; +extern const pm_char STR_BACKLIGHT_LABEL[]; +extern const pm_char STR_BLDELAY[]; +#if defined(PWM_BACKLIGHT) +extern const pm_char STR_BLONBRIGHTNESS[]; +extern const pm_char STR_BLOFFBRIGHTNESS[]; +#endif +extern const pm_char STR_SPLASHSCREEN[]; +extern const pm_char STR_THROTTLEWARNING[]; +extern const pm_char STR_SWITCHWARNING[]; +extern const pm_char STR_TIMEZONE[]; +extern const pm_char STR_GPSCOORD[]; +extern const pm_char STR_VARIO[]; +extern const pm_char STR_RXCHANNELORD[]; +extern const pm_char STR_SLAVE[]; +extern const pm_char STR_MODESRC[]; +extern const pm_char STR_MULTIPLIER[]; +#define LEN_MULTIPLIER PSIZE(TR_MULTIPLIER) +extern const pm_char STR_CAL[]; +extern const pm_char STR_VTRIM[]; +extern const pm_char STR_BG[]; +extern const pm_char STR_MENUTOSTART[]; +extern const pm_char STR_SETMIDPOINT[]; +extern const pm_char STR_MOVESTICKSPOTS[]; +extern const pm_char STR_RXBATT[]; +extern const pm_char STR_TX[]; +#define STR_RX (STR_TX+OFS_RX) +extern const pm_char STR_ACCEL[]; +extern const pm_char STR_NODATA[]; +extern const pm_char STR_TM1TM2[]; +extern const pm_char STR_THRTHP[]; +extern const pm_char STR_TOT[]; +extern const pm_char STR_TMR1LATMAXUS[]; +extern const pm_char STR_TMR1LATMINUS[]; +extern const pm_char STR_TMR1JITTERUS[]; +extern const pm_char STR_TMIXMAXMS[]; +extern const pm_char STR_FREESTACKMINB[]; +extern const pm_char STR_MENUTORESET[]; +extern const pm_char STR_PPM[]; +extern const pm_char STR_CH[]; +extern const pm_char STR_MODEL[]; +extern const pm_char STR_FP[]; +#if defined(CPUARM) +extern const pm_char STR_MIX[]; +#endif +extern const pm_char STR_EEPROMLOWMEM[]; +extern const pm_char STR_ALERT[]; +extern const pm_char STR_PRESSANYKEYTOSKIP[]; +extern const pm_char STR_THROTTLENOTIDLE[]; +extern const pm_char STR_ALARMSDISABLED[]; +extern const pm_char STR_PRESSANYKEY[]; +#define LEN_PRESSANYKEY PSIZE(TR_PRESSANYKEY) +extern const pm_char STR_BADEEPROMDATA[]; +extern const pm_char STR_EEPROMFORMATTING[]; +extern const pm_char STR_EEPROMOVERFLOW[]; +extern const pm_char STR_TRIMS2OFFSETS[]; +extern const pm_char STR_MENURADIOSETUP[]; +extern const pm_char STR_MENUDATEANDTIME[]; +extern const pm_char STR_MENUTRAINER[]; +extern const pm_char STR_MENUVERSION[]; +extern const pm_char STR_MENUDIAG[]; +extern const pm_char STR_MENUANA[]; +extern const pm_char STR_MENUCALIBRATION[]; +extern const pm_char STR_MENUMODELSEL[]; +extern const pm_char STR_MENUSETUP[]; +extern const pm_char STR_MENUFLIGHTPHASE[]; +extern const pm_char STR_MENUFLIGHTPHASES[]; +extern const pm_char STR_MENUHELISETUP[]; +extern const pm_char STR_MENUINPUTS[]; +extern const pm_char STR_MENULIMITS[]; +extern const pm_char STR_MENUCURVES[]; +extern const pm_char STR_MENUCURVE[]; +extern const pm_char STR_MENUCUSTOMSWITCH[]; +extern const pm_char STR_MENUCUSTOMSWITCHES[]; +extern const pm_char STR_MENUCUSTOMFUNC[]; +extern const pm_char STR_MENUCUSTOMSCRIPTS[]; +extern const pm_char STR_MENUCUSTOMSCRIPT[]; +extern const pm_char STR_MENUTELEMETRY[]; +extern const pm_char STR_MENUTEMPLATES[]; +extern const pm_char STR_MENUSTAT[]; +extern const pm_char STR_MENUDEBUG[]; +extern const pm_char STR_MENUGLOBALVARS[]; +extern const pm_char STR_INVERT_THR[]; +extern const pm_char STR_AND_SWITCH[]; +extern const pm_char STR_CF[]; + +#if defined(DSM2) || defined(PXX) +extern const pm_char STR_RXNUM[]; +#endif + +#if defined(PXX) +extern const pm_char STR_SYNCMENU[]; +extern const pm_char STR_INTERNALRF[]; +extern const pm_char STR_EXTERNALRF[]; +extern const pm_char STR_FAILSAFE[]; +extern const pm_char STR_FAILSAFESET[]; +extern const pm_char STR_COUNTRYCODE[]; +#endif + +#if defined(FRSKY) +extern const pm_char STR_LIMIT[]; +#endif + +#ifdef FRSKY_HUB +extern const pm_char STR_MINRSSI[]; +extern const pm_char STR_LATITUDE[]; +extern const pm_char STR_LONGITUDE[]; +#endif + +#if defined(CPUARM) || defined(CPUM2560) +extern const pm_char STR_SHUTDOWN[]; +#endif + +extern const pm_char STR_BATT_CALIB[]; + +#if defined(CPUARM) || defined(FRSKY) +extern const pm_char STR_VOLTAGE[]; +extern const pm_char STR_CURRENT[]; +#endif + +#if defined(CPUARM) + extern const pm_char STR_CURRENT_CALIB[]; + #define LEN_CALIB_FIELDS (PSIZE(TR_BATT_CALIB) > PSIZE(TR_CURRENT_CALIB) ? PSIZE(TR_BATT_CALIB) : PSIZE(TR_CURRENT_CALIB)) + extern const pm_char STR_UNITSSYSTEM[]; + extern const pm_char STR_VOICELANG[]; + extern const pm_char STR_MODELIDUSED[]; + extern const pm_char STR_BEEP_VOLUME[]; + extern const pm_char STR_WAV_VOLUME[]; + extern const pm_char STR_VARIO_VOLUME[]; + extern const pm_char STR_BG_VOLUME[]; + extern const pm_char STR_PERSISTENT_MAH[]; +#else + #define LEN_CALIB_FIELDS PSIZE(TR_BATT_CALIB) +#endif + +#if defined(NAVIGATION_MENUS) + extern const pm_char STR_SELECT_MODEL[]; + extern const pm_char STR_CREATE_MODEL[]; + extern const pm_char STR_COPY_MODEL[]; + extern const pm_char STR_MOVE_MODEL[]; + extern const pm_char STR_DELETE_MODEL[]; + extern const pm_char STR_EDIT[]; + extern const pm_char STR_INSERT_BEFORE[]; + extern const pm_char STR_INSERT_AFTER[]; + extern const pm_char STR_COPY[]; + extern const pm_char STR_MOVE[]; + extern const pm_char STR_PASTE[]; + extern const pm_char STR_INSERT[]; + extern const pm_char STR_DELETE[]; + extern const pm_char STR_RESET_FLIGHT[]; + extern const pm_char STR_RESET_TIMER1[]; + extern const pm_char STR_RESET_TIMER2[]; + extern const pm_char STR_RESET_TELEMETRY[]; + extern const pm_char STR_STATISTICS[]; + extern const pm_char STR_ABOUT_US[]; +#endif + +extern const pm_char STR_RESET_BTN[]; + +#if defined(SDCARD) + extern const pm_char STR_BACKUP_MODEL[]; + extern const pm_char STR_RESTORE_MODEL[]; + extern const pm_char STR_SDCARD_ERROR[]; + extern const pm_char STR_NO_SDCARD[]; + extern const pm_char STR_INCOMPATIBLE[]; + extern const pm_char STR_LOGS_PATH[]; + extern const pm_char STR_LOGS_EXT[]; + extern const pm_char STR_MODELS_PATH[]; + extern const pm_char STR_MODELS_EXT[]; + #define STR_UPDATE_LIST STR_DELAYDOWN +#endif + +extern const pm_uchar font_5x7[]; +extern const pm_uchar font_10x14[]; + +#if defined(CPUARM) +extern const pm_uchar font_3x5[]; +extern const pm_uchar font_4x6[]; +extern const pm_uchar font_8x10[]; +extern const pm_uchar font_5x7_extra[]; +extern const pm_uchar font_10x14_extra[]; +extern const pm_uchar font_4x6_extra[]; +#endif + +extern const pm_char STR_WARNING[]; +extern const pm_char STR_EEPROMWARN[]; +extern const pm_char STR_THROTTLEWARN[]; +extern const pm_char STR_ALARMSWARN[]; +extern const pm_char STR_SWITCHWARN[]; + +extern const pm_char STR_SPEAKER_VOLUME[]; +extern const pm_char STR_LCD[]; +extern const pm_char STR_BRIGHTNESS[]; +extern const pm_char STR_CPU_TEMP[]; +extern const pm_char STR_CPU_CURRENT[]; +extern const pm_char STR_CPU_MAH[]; +extern const pm_char STR_COPROC[]; +extern const pm_char STR_COPROC_TEMP[]; +extern const pm_char STR_CAPAWARNING[]; +extern const pm_char STR_TEMPWARNING[]; +extern const pm_char STR_FUNC[]; +extern const pm_char STR_V1[]; +extern const pm_char STR_V2[]; +extern const pm_char STR_DURATION[]; +extern const pm_char STR_DELAY[]; +extern const pm_char STR_SD_CARD[]; +extern const pm_char STR_SDHC_CARD[]; +extern const pm_char STR_NO_SOUNDS_ON_SD[]; +extern const pm_char STR_NO_MODELS_ON_SD[]; +extern const pm_char STR_NO_BITMAPS_ON_SD[]; +extern const pm_char STR_NO_SCRIPTS_ON_SD[]; +extern const pm_char STR_PLAY_FILE[]; +extern const pm_char STR_ASSIGN_BITMAP[]; +extern const pm_char STR_EXECUTE_FILE[]; +extern const pm_char STR_DELETE_FILE[]; +extern const pm_char STR_COPY_FILE[]; +extern const pm_char STR_RENAME_FILE[]; +extern const pm_char STR_REMOVED[]; +extern const pm_char STR_SD_INFO[]; +extern const pm_char STR_SD_FORMAT[]; +extern const pm_char STR_NA[]; +extern const pm_char STR_HARDWARE[]; +extern const pm_char STR_FORMATTING[]; +extern const pm_char STR_TEMP_CALIB[]; +extern const pm_char STR_TIME[]; +extern const pm_char STR_BAUDRATE[]; +extern const pm_char STR_SD_INFO_TITLE[]; +extern const pm_char STR_SD_TYPE[]; +extern const pm_char STR_SD_SPEED[]; +extern const pm_char STR_SD_SECTORS[]; +extern const pm_char STR_SD_SIZE[]; +extern const pm_char STR_TYPE[]; +extern const pm_char STR_GLOBAL_VARS[]; +extern const pm_char STR_GLOBAL_VAR[]; +extern const pm_char STR_OWN[]; +extern const pm_char STR_ROTARY_ENCODER[]; +extern const pm_char STR_DATE[]; +extern const pm_char STR_CHANNELS_MONITOR[]; +extern const pm_char STR_PATH_TOO_LONG[]; +extern const pm_char STR_VIEW_TEXT[]; + +#if defined(VOICE) && defined(CPUARM) + struct LanguagePack { + const char *id; + const char *name; + void (*playNumber)(getvalue_t number, uint8_t unit, uint8_t att, uint8_t id); + void (*playDuration)(int16_t seconds, uint8_t id); + }; + extern LanguagePack * languagePacks[]; + extern LanguagePack * currentLanguagePack; + extern uint8_t currentLanguagePackIdx; + #define LANGUAGE_PACK_DECLARE(lng, name) LanguagePack lng ## LanguagePack = { #lng, name, lng ## _ ## playNumber, lng ## _ ## playDuration } + #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) LANGUAGE_PACK_DECLARE(lng, name); LanguagePack * currentLanguagePack = & lng ## LanguagePack; uint8_t currentLanguagePackIdx + inline PLAY_FUNCTION(playNumber, getvalue_t number, uint8_t unit, uint8_t att) { currentLanguagePack->playNumber(number, unit, att, id); } + inline PLAY_FUNCTION(playDuration, int16_t seconds) { currentLanguagePack->playDuration(seconds, id); } +#elif defined(VOICE) + PLAY_FUNCTION(playNumber, getvalue_t number, uint8_t unit, uint8_t att); + PLAY_FUNCTION(playDuration, int16_t seconds); + #define LANGUAGE_PACK_DECLARE(lng, name) + #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) +#else + #define LANGUAGE_PACK_DECLARE(lng, name) + #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) +#endif + +#if LCD_W >= 212 + extern const pm_char STR_MODELNAME[]; + extern const pm_char STR_PHASENAME[]; + extern const pm_char STR_MIXNAME[]; + extern const pm_char STR_EXPONAME[]; +#else + #define STR_MODELNAME STR_NAME + #define STR_PHASENAME STR_NAME + #define STR_MIXNAME STR_NAME + #define STR_EXPONAME STR_NAME +#endif + +#if LCD_W >= 212 + extern const char * STR_PHASES_HEADERS[]; + extern const char * STR_LIMITS_HEADERS[]; + extern const char * STR_CSW_HEADERS[]; +#endif + +#if defined(PCBTARANIS) + extern const pm_char STR_BYTES[]; + extern const pm_char STR_MODULE_BIND[]; + extern const pm_char STR_SET[]; + extern const pm_char STR_TRAINER[]; + extern const pm_char STR_ANTENNAPROBLEM[]; + extern const pm_char STR_MODULE[]; + extern const pm_char STR_CHANNELRANGE[]; + extern const pm_char STR_LOWALARM[]; + extern const pm_char STR_CRITICALALARM[]; + extern const pm_char STR_ENABLE_POPUP[]; + extern const pm_char STR_DISABLE_POPUP[]; + extern const pm_char STR_CURVE_PRESET[]; + extern const pm_char STR_PRESET[]; + extern const pm_char STR_MIRROR[]; + extern const pm_char STR_CLEAR[]; + extern const pm_char STR_RESET[]; + extern const pm_char STR_COPY_TRIMS_TO_OFFSET[]; + extern const pm_char STR_TOP_BAR[]; + extern const pm_char STR_ALTITUDE[]; + extern const pm_char STR_SCALE[]; + extern const pm_char STR_VIEW_CHANNELS[]; + extern const pm_char STR_VIEW_NOTES[]; +#endif + +#if MENUS_LOCK == 1 + extern const pm_char STR_UNLOCKED[]; + extern const pm_char STR_MODS_FORBIDDEN[]; +#endif + +#if defined(PCBTARANIS) || defined(DSM2) + extern const pm_char STR_MODULE_RANGE[]; +#endif + +#if defined(MAVLINK) + extern const pm_char STR_MAVLINK_RC_RSSI_SCALE_LABEL[]; + extern const pm_char STR_MAVLINK_PC_RSSI_EN_LABEL[]; + extern const pm_char STR_MAVMENUSETUP_TITLE[]; + extern const pm_char STR_MAVLINK_BAUD_LABEL[]; + extern const pm_char STR_MAVLINK_INFOS[]; + extern const pm_char STR_MAVLINK_MODE[]; + extern const pm_char STR_MAVLINK_CUR_MODE[]; + extern const pm_char STR_MAVLINK_ARMED[]; + extern const pm_char STR_MAVLINK_BAT_MENU_TITLE[]; + extern const pm_char STR_MAVLINK_BATTERY_LABEL[]; + extern const pm_char STR_MAVLINK_RC_RSSI_LABEL[]; + extern const pm_char STR_MAVLINK_PC_RSSI_LABEL[]; + extern const pm_char STR_MAVLINK_NAV_MENU_TITLE[]; + extern const pm_char STR_MAVLINK_COURSE[]; + extern const pm_char STR_MAVLINK_HEADING[]; + extern const pm_char STR_MAVLINK_BEARING[]; + extern const pm_char STR_MAVLINK_ALTITUDE[]; + extern const pm_char STR_MAVLINK_GPS[]; + extern const pm_char STR_MAVLINK_NO_FIX[]; + extern const pm_char STR_MAVLINK_SAT[]; + extern const pm_char STR_MAVLINK_HDOP[]; + extern const pm_char STR_MAVLINK_LAT[]; + extern const pm_char STR_MAVLINK_LON[]; +#endif + +#if !defined(CPUM64) + extern const pm_char STR_ABOUTUS[]; + extern const pm_char STR_ABOUT_OPENTX_1[]; + extern const pm_char STR_ABOUT_OPENTX_2[]; + extern const pm_char STR_ABOUT_OPENTX_3[]; + extern const pm_char STR_ABOUT_OPENTX_4[]; + extern const pm_char STR_ABOUT_OPENTX_5[]; + + extern const pm_char STR_ABOUT_BERTRAND_1[]; + extern const pm_char STR_ABOUT_BERTRAND_2[]; + extern const pm_char STR_ABOUT_BERTRAND_3[]; + + extern const pm_char STR_ABOUT_MIKE_1[]; + extern const pm_char STR_ABOUT_MIKE_2[]; + extern const pm_char STR_ABOUT_MIKE_3[]; + extern const pm_char STR_ABOUT_MIKE_4[]; + + extern const pm_char STR_ABOUT_ROMOLO_1[]; + extern const pm_char STR_ABOUT_ROMOLO_2[]; + extern const pm_char STR_ABOUT_ROMOLO_3[]; + + extern const pm_char STR_ABOUT_ANDRE_1[]; + extern const pm_char STR_ABOUT_ANDRE_2[]; + extern const pm_char STR_ABOUT_ANDRE_3[]; + + extern const pm_char STR_ABOUT_ROB_1[]; + extern const pm_char STR_ABOUT_ROB_2[]; + + extern const pm_char STR_ABOUT_MARTIN_1[]; + extern const pm_char STR_ABOUT_MARTIN_2[]; + + extern const pm_char STR_ABOUT_HARDWARE_1[]; + extern const pm_char STR_ABOUT_HARDWARE_2[]; + extern const pm_char STR_ABOUT_HARDWARE_3[]; + + extern const pm_char STR_ABOUT_PARENTS_1[]; + extern const pm_char STR_ABOUT_PARENTS_2[]; + extern const pm_char STR_ABOUT_PARENTS_3[]; + extern const pm_char STR_ABOUT_PARENTS_4[]; +#endif + +#define CHR_SHORT TR_CHR_SHORT +#define CHR_LONG TR_CHR_LONG +#define CHR_TOGGLE TR_CHR_TOGGLE +#define CHR_HOUR TR_CHR_HOUR + +#endif diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 62876daf9..86c4f48cf 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -447,6 +447,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA "UsrData" #define TR_BLADES INDENT"Blades" +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Screen " #define TR_SOUND_LABEL "Sound" #define TR_LENGTH INDENT"Length" diff --git a/radio/src/translations/en.h~ b/radio/src/translations/en.h~ new file mode 100644 index 000000000..62876daf9 --- /dev/null +++ b/radio/src/translations/en.h~ @@ -0,0 +1,765 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * 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. + * + */ + +// NON ZERO TERMINATED STRINGS +#define LEN_OFFON "\003" +#define TR_OFFON "OFF""ON\0" + +#define LEN_MMMINV "\003" +#define TR_MMMINV "---""INV" + +#define LEN_NCHANNELS "\004" +#define TR_NCHANNELS "\0014CH\0016CH\0018CH10CH12CH14CH16CH" + +#define LEN_VBEEPMODE "\005" +#define TR_VBEEPMODE "Quiet""Alarm""NoKey""All " + +#define LEN_VBEEPLEN "\005" +#define TR_VBEEPLEN "0====""=0===""==0==""===0=""====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 ") + +#define LEN_TRNMODE "\003" +#define TR_TRNMODE "OFF"" +="" :=" + +#define LEN_TRNCHN "\003" +#define TR_TRNCHN "CH1CH2CH3CH4" + +#define LEN_DATETIME "\005" +#define TR_DATETIME "DATE:""TIME:" + +#define LEN_VLCD "\006" +#define TR_VLCD "NormalOptrex" + +#define LEN_COUNTRYCODES TR("\002", "\007") +#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europe\0") + +#define LEN_VTRIMINC TR("\006","\013") +#define TR_VTRIMINC TR("Expo ""ExFine""Fine ""Medium""Coarse","Exponential""Extra Fine ""Fine ""Medium ""Coarse ") + +#define LEN_VBEEPCOUNTDOWN "\006" +#define TR_VBEEPCOUNTDOWN "SilentBeeps\0Voice\0" + +#define LEN_RETA123 "\001" + +#if defined(PCBGRUVIN9X) + #if ROTARY_ENCODERS > 2 + #define TR_RETA123 "RETA123abcd" + #else + #define TR_RETA123 "RETA123ab" + #endif +#elif defined(PCBTARANIS) + #define TR_RETA123 "RETA12LR" +#else + #define TR_RETA123 "RETA123" +#endif + +#define LEN_VPROTOS "\006" + +#if defined(PXX) + #define TR_PXX "PXX\0 " +#elif defined(DSM2) || defined(IRPROTOS) + #define TR_PXX "[PXX]\0" +#else + #define TR_PXX +#endif + +#if defined(DSM2) + #define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 " +#elif defined(IRPROTOS) + #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]" +#else + #define TR_DSM2 +#endif + +#if defined(IRPROTOS) + #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0" +#else + #define TR_IRPROTOS +#endif + +#if defined(CPUARM) + #define TR_XPPM +#else + #define TR_XPPM "PPM16\0""PPMsim" +#endif + +#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS + +#define LEN_POSNEG "\003" +#define TR_POSNEG "POS""NEG" + +#define LEN_VCURVEFUNC "\003" +#define TR_VCURVEFUNC "---""x>0""x<0""|x|""f>0""f<0""|f|" + +#define LEN_VMLTPX "\010" +#define TR_VMLTPX "Add\0 ""Multiply""Replace\0" + +#define LEN_VMLTPX2 "\002" +#define TR_VMLTPX2 "+=""*="":=" + +#define LEN_VMIXTRIMS "\003" +#define TR_VMIXTRIMS "OFF""ON\0""Rud""Ele""Thr""Ail" + +#define LEN_VCSWFUNC "\005" +#define TR_VCSWFUNC "---\0 ""a{x\0 ""a>x\0 ""ax""|a|b\0 ""a" + +#define LEN_VTELPROTO "\007" +#define TR_VTELPROTO "None\0 ""Hub\0 ""WSHHigh" + +#define LEN_VOLTSRC "\003" +#define TR_VOLTSRC "---""A1\0""A2\0""FAS""Cel" + +#define LEN_VARIOSRC "\005" +#if defined(FRSKY_SPORT) + #define TR_VARIOSRC "Vario""A1\0 ""A2\0" +#else + #define TR_VARIOSRC "Alti\0""Alti+""Vario""A1\0 ""A2\0" +#endif + +#define LEN_VSCREEN "\004" +#define TR_VSCREEN "Nums""Bars" + +#define LEN_GPSFORMAT "\004" +#define TR_GPSFORMAT "HMS NMEA" + +#define LEN2_VTEMPLATES 13 +#define LEN_VTEMPLATES "\015" +#define TR_VTEMPLATES "Clear Mixes\0\0""Simple 4-CH \0""Sticky-T-Cut\0""V-Tail \0""Elevon\\Delta\0""eCCPM \0""Heli Setup \0""Servo Test \0" + +#define LEN_VSWASHTYPE "\004" +#define TR_VSWASHTYPE "---\0""120\0""120X""140\0""90\0" + +#define LEN_VKEYS "\005" +#define TR_VKEYS TR(" Menu"" Exit"" Down"" Up""Right"" Left", " Menu"" Exit""Enter"" Page"" Plus""Minus") + +#define LEN_VRENCODERS "\003" +#define TR_VRENCODERS "REa""REb" + +#define LEN_VSWITCHES "\003" +#define LEN_VSRCRAW "\004" + +#if defined(PCBTARANIS) + #define TR_POTS_VSRCRAW "S1\0 ""S2\0 ""LS\0 ""RS\0 " + #define TR_SW_VSRCRAW "SA\0 ""SB\0 ""SC\0 ""SD\0 ""SE\0 ""SF\0 ""SG\0 ""SH\0 " +#elif defined(EXTRA_3POS) + #define TR_POTS_VSRCRAW "P1\0 ""P2\0 " + #define TR_SW_VSRCRAW "3P1\0""3P2\0" + #define TR_9X_3POS_SWITCHES "ID0""ID1""ID2""ID3""ID4""ID5" +#else + #define TR_POTS_VSRCRAW "P1\0 ""P2\0 ""P3\0 " + #define TR_SW_VSRCRAW "3POS" + #define TR_9X_3POS_SWITCHES "ID0""ID1""ID2" +#endif + +#if defined(CPUARM) + #define TR_CUSTOMSW "CS1""CS2""CS3""CS4""CS5""CS6""CS7""CS8""CS9""CSA""CSB""CSC""CSD""CSE""CSF""CSG""CSH""CSI""CSJ""CSK""CSL""CSM""CSN""CSO""CSP""CSQ""CSR""CSS""CST""CSU""CSV""CSW" +#elif defined(PCBGRUVIN9X) || defined(CPUM2561) || defined(CPUM128) + #define TR_CUSTOMSW "CS1""CS2""CS3""CS4""CS5""CS6""CS7""CS8""CS9""CSA""CSB""CSC""CSD""CSE""CSF" +#else + #define TR_CUSTOMSW "CS1""CS2""CS3""CS4""CS5""CS6""CS7""CS8""CS9""CSA""CSB""CSC" +#endif + +#if defined(PCBTARANIS) + #define TR_VSWITCHES "SA\300""SA-""SA\301""SB\300""SB-""SB\301""SC\300""SC-""SC\301""SD\300""SD-""SD\301""SE\300""SE-""SE\301""SF\300""SF\301""SG\300""SG-""SG\301""SH\300""SH\301" TR_CUSTOMSW "One" +#else + #define TR_VSWITCHES TR_9X_3POS_SWITCHES "THR""RUD""ELE""AIL""GEA""TRN" TR_CUSTOMSW "One" +#endif + +#if defined(PCBSKY9X) + #define TR_ROTARY_ENCODERS_VSRCRAW "REnc" +#elif defined(PCBGRUVIN9X) && ROTARY_ENCODERS > 2 + #define TR_ROTARY_ENCODERS_VSRCRAW "REa ""REb ""REc ""REd " +#elif defined(PCBGRUVIN9X) && ROTARY_ENCODERS <= 2 + #define TR_ROTARY_ENCODERS_VSRCRAW "REa ""REb " +#else + #define TR_ROTARY_ENCODERS_VSRCRAW +#endif + +#if defined(HELI) + #define TR_CYC_VSRCRAW "CYC1""CYC2""CYC3" +#else + #define TR_CYC_VSRCRAW "[C1]""[C2]""[C3]" +#endif + +#define TR_VSRCRAW "---\0""Rud\0""Ele\0""Thr\0""Ail\0" TR_POTS_VSRCRAW TR_ROTARY_ENCODERS_VSRCRAW "MAX\0" TR_CYC_VSRCRAW "TrmR" "TrmE" "TrmT" "TrmA" TR_SW_VSRCRAW + +#define LEN_VTMRMODES "\003" +#define TR_VTMRMODES "OFF""ABS""THs""TH%""THt" + +#define LEN_VTRAINERMODES "\006" +#define TR_VTRAINERMODES "Master""Slave\0" + +#define LEN_VFAILSAFE "\011" +#define TR_VFAILSAFE "Hold\0 ""Custom\0 ""No pulses" + +#if defined(MAVLINK) + #define LEN_MAVLINK_BAUDS "\006" + #define TR_MAVLINK_BAUDS "4800 ""9600 ""14400 ""19200 ""38400 ""57600 ""76800 ""115200" + #define LEN_MAVLINK_AC_MODES "\011" + #define TR_MAVLINK_AC_MODES "Stabilize""Acro ""Alt Hold ""Auto ""Guided ""Loiter ""RTL ""Circle ""Pos Hold ""Land ""OF Loiter""Toy A ""Toy M ""INVALID " + #define LEN_MAVLINK_AP_MODES "\015" + #define TR_MAVLINK_AP_MODES "Manual ""Circle ""Stabilize ""Training ""Fly by Wire A""Fly by Wire A""Auto ""RTL ""Loiter ""Guided ""Initialising ""INVALID " +#endif + +// ZERO TERMINATED STRINGS +#define INDENT "\001" +#define LEN_INDENT 1 +#define INDENT_WIDTH (FW/2) + +#if defined(PCBTARANIS) + #define TR_ENTER "[ENTER]" +#else + #define TR_ENTER "[MENU]" +#endif + +#define TR_POPUPS TR_ENTER "\010[EXIT]" +#define OFS_EXIT sizeof(TR_ENTER) + +#define TR_MENUWHENDONE CENTER "\006" TR_ENTER " WHEN DONE" +#define TR_FREE "free" +#define TR_DELETEMODEL "DELETE MODEL" +#define TR_COPYINGMODEL "Copying model..." +#define TR_MOVINGMODEL "Moving model..." +#define TR_LOADINGMODEL "Loading model..." +#define TR_NAME "Name" +#define TR_MODELNAME "Model Name" +#define TR_PHASENAME "Mode Name" +#define TR_MIXNAME "Mix Name" +#if defined(PCBTARANIS) + #define TR_EXPONAME "Line Name" +#else + #define TR_EXPONAME "Expo Name" +#endif +#define TR_BITMAP "Model Image" +#define TR_TIMER TR("Timer","Timer ") +#define TR_ELIMITS TR("E.Limits","Extended Limits") +#define TR_ETRIMS TR("E.Trims","Extended Trims") +#define TR_TRIMINC "Trim Step" +#define TR_TTRACE TR("T-Source","Throttle Source") +#define TR_TTRIM TR("T-Trim","Throttle Trim") +#define TR_BEEPCTR TR("Ctr Beep","Center Beep") +#define TR_PROTO TR(INDENT "Proto", INDENT "Protocol") +#define TR_PPMFRAME TR("PPM frame", INDENT "PPM frame") +#define TR_MS "ms" +#define TR_SWITCH "Switch" +#define TR_TRIMS "Trims" +#define TR_FADEIN "Fade In" +#define TR_FADEOUT "Fade Out" +#define TR_DEFAULT "(default)" +#define TR_CHECKTRIMS CENTER "\006Check\012Trims" +#define OFS_CHECKTRIMS CENTER_OFS+(9*FW) +#define TR_SWASHTYPE "Swash Type" +#define TR_COLLECTIVE TR("Collective","Collective source") +#define TR_SWASHRING "Swash Ring" +#define TR_ELEDIRECTION TR("ELE Direction","Long. cyc. direction") +#define TR_AILDIRECTION TR("AIL Direction","Lateral cyc. direction") +#define TR_COLDIRECTION TR("PIT Direction","Coll. pitch direction") +#define TR_MODE INDENT"Mode" +#define TR_NOFREEEXPO "No free expo!" +#define TR_NOFREEMIXER "No free mixer!" +#define TR_INSERTMIX "INSERT MIX " +#define TR_EDITMIX "EDIT MIX " +#define TR_SOURCE INDENT"Source" +#define TR_WEIGHT "Weight" +#define TR_EXPO TR("Expo","Exponential") +#define TR_SIDE "Side" +#define TR_DIFFERENTIAL "Differ" +#define TR_OFFSET INDENT"Offset" +#define TR_TRIM "Trim" +#define TR_DREX "DRex" +#define TR_CURVE "Curve" +#define TR_FLMODE TR("Mode","Modes") +#define TR_MIXWARNING "Warning" +#define TR_OFF "OFF" +#define TR_MULTPX "Multpx" +#define TR_DELAYDOWN "Delay Dn" +#define TR_DELAYUP "Delay Up" +#define TR_SLOWDOWN "Slow Dn" +#define TR_SLOWUP "Slow Up" +#define TR_MIXER "MIXER" +#define TR_CV "CV" +#define TR_GV "GV" +#define TR_ACHANNEL "A\004channel" +#define TR_RANGE INDENT"Range" +#define TR_BAR "Bar" +#define TR_ALARM INDENT"Alarm" +#define TR_USRDATA "UsrData" +#define TR_BLADES INDENT"Blades" +#define TR_SCREEN "Screen " +#define TR_SOUND_LABEL "Sound" +#define TR_LENGTH INDENT"Length" +#define TR_SPKRPITCH INDENT"Pitch" +#define TR_HAPTIC_LABEL "Haptic" +#define TR_HAPTICSTRENGTH INDENT"Strength" +#define TR_CONTRAST "Contrast" +#define TR_ALARMS_LABEL "Alarms" +#define TR_BATTERY_RANGE TR("Battery range","Battery meter range") +#define TR_BATTERYWARNING INDENT"Battery Low" +#define TR_INACTIVITYALARM INDENT"Inactivity" +#define TR_MEMORYWARNING INDENT"Memory Low" +#define TR_ALARMWARNING INDENT"Sound Off" +#define TR_RENAVIG "RotEnc Navig" +#define TR_THROTTLEREVERSE TR("T-Reverse", "Throttle reverse") +#define TR_MINUTEBEEP TR(INDENT"Minute",INDENT"Minute call") +#define TR_BEEPCOUNTDOWN INDENT"Countdown" +#define TR_PERSISTENT TR(INDENT"Persist.",INDENT"Persistent") +#define TR_BACKLIGHT_LABEL "Backlight" +#define TR_BLDELAY INDENT"Duration" +#define TR_BLONBRIGHTNESS INDENT"ON Brightness" +#define TR_BLOFFBRIGHTNESS INDENT"OFF Brightness" +#define TR_SPLASHSCREEN "Splash screen" +#define TR_THROTTLEWARNING TR("T-Warning","Throttle Warning") +#define TR_SWITCHWARNING TR("S-Warning","Switch Warning") +#define TR_TIMEZONE TR("Time Zone","GPS Time zone") +#define TR_RXCHANNELORD TR("Rx Channel Ord","Default channel order") +#define TR_SLAVE "Slave" +#define TR_MODESRC "Mode\006% Source" +#define TR_MULTIPLIER "Multiplier" +#define TR_CAL "Cal" +#define TR_VTRIM "Trim- +" +#define TR_BG "BG:" +#define TR_MENUTOSTART CENTER "\006" TR_ENTER " TO START" +#define TR_SETMIDPOINT TR(CENTER "\003SET STICKS MIDPOINT",CENTER "\003CENTER STICKS/SLIDERS") +#define TR_MOVESTICKSPOTS CENTER "\006MOVE STICKS/POTS" +#define TR_RXBATT "Rx Batt:" +#define TR_TXnRX "Tx:\0Rx:" +#define OFS_RX 4 +#define TR_ACCEL "Acc:" +#define TR_NODATA CENTER "NO DATA" +#define TR_TM1TM2 "TM1\032TM2" +#define TR_THRTHP "THR\032TH%" +#define TR_TOT "TOT" +#define TR_TMR1LATMAXUS "Tmr1Lat max\006us" +#define STR_US (STR_TMR1LATMAXUS+12) +#define TR_TMR1LATMINUS "Tmr1Lat min\006us" +#define TR_TMR1JITTERUS "Tmr1 Jitter\006us" + +#if defined(CPUARM) + #define TR_TMIXMAXMS "Tmix max" + #define TR_FREESTACKMINB "Free Stack" +#else + #define TR_TMIXMAXMS "Tmix max\014ms" + #define TR_FREESTACKMINB "Free Stack\010b" +#endif + +#define TR_MENUTORESET CENTER TR_ENTER " to reset" +#define TR_PPM "PPM" +#define TR_CH "CH" +#define TR_MODEL "MODEL" +#define TR_FP "FM" +#define TR_MIX "MIX" +#define TR_EEPROMLOWMEM "EEPROM low mem" +#define TR_ALERT "\016ALERT" +#define TR_PRESSANYKEYTOSKIP "Press any key to skip" +#define TR_THROTTLENOTIDLE "Throttle not idle" +#define TR_ALARMSDISABLED "Alarms Disabled" +#define TR_PRESSANYKEY TR("\010Press any Key", "Press any Key") +#define TR_BADEEPROMDATA "Bad EEprom Data" +#define TR_EEPROMFORMATTING "Formatting EEPROM" +#define TR_EEPROMOVERFLOW "EEPROM overflow" +#define TR_MENURADIOSETUP "RADIO SETUP" +#define TR_MENUDATEANDTIME "DATE AND TIME" +#define TR_MENUTRAINER "TRAINER" +#define TR_MENUVERSION "VERSION" +#define TR_MENUDIAG TR("SWITCHES","SWITCH TEST") +#define TR_MENUANA TR("ANAS","ANALOG INPUTS") +#define TR_MENUCALIBRATION "CALIBRATION" +#define TR_TRIMS2OFFSETS "\006Trims => Offsets" +#define TR_MENUMODELSEL TR("MODELSEL","MODEL SELECTION") +#define TR_MENUSETUP TR("SETUP","MODEL SETUP") +#define TR_MENUFLIGHTPHASE "FLIGHT MODE" +#define TR_MENUFLIGHTPHASES "FLIGHT MODES" +#define TR_MENUHELISETUP "HELI SETUP" + +#if defined(PCBTARANIS) + #define TR_MENUINPUTS "INPUTS" + #define TR_MENULIMITS "SERVOS" +#elif defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... + #define TR_MENUINPUTS "STICKS" + #define TR_MENULIMITS "SERVOS" +#else + #define TR_MENUINPUTS "DR/EXPO" + #define TR_MENULIMITS "LIMITS" +#endif + +#define TR_MENUCURVES "CURVES" +#define TR_MENUCURVE "CURVE" +#define TR_MENUCUSTOMSWITCH "CUSTOM SWITCH" +#define TR_MENUCUSTOMSWITCHES "CUSTOM SWITCHES" +#define TR_MENUCUSTOMFUNC "CUSTOM FUNCTIONS" +#define TR_MENUTELEMETRY "TELEMETRY" +#define TR_MENUTEMPLATES "TEMPLATES" +#define TR_MENUSTAT "STATS" +#define TR_MENUDEBUG "DEBUG" +#define TR_RXNUM TR("RxNum", INDENT"Receiver No.") +#define TR_SYNCMENU "[Sync]" +#define TR_LIMIT INDENT"Limit" +#define TR_MINRSSI "Min Rssi" +#define TR_LATITUDE "Latitude" +#define TR_LONGITUDE "Longitude" +#define TR_GPSCOORD TR("GPS Coords", "GPS coordinate format") +#define TR_VARIO TR("Vario", "Variometer") +#define TR_SHUTDOWN "SHUTTING DOWN" +#define TR_BATT_CALIB "Battery Calib" +#define TR_CURRENT_CALIB "Current Calib" +#define TR_VOLTAGE INDENT"Voltage" +#define TR_CURRENT INDENT"Current" +#define TR_SELECT_MODEL "Select Model" +#define TR_CREATE_MODEL "Create Model" +#define TR_COPY_MODEL "Copy Model" +#define TR_MOVE_MODEL "Move Model" +#define TR_BACKUP_MODEL "Backup Model" +#define TR_DELETE_MODEL "Delete Model" +#define TR_RESTORE_MODEL "Restore Model" +#define TR_SDCARD_ERROR "SDCARD Error" +#define TR_NO_SDCARD "No SDCARD" +#define TR_INCOMPATIBLE "Incompatible" +#define TR_WARNING "WARNING" +#define TR_EEPROMWARN "EEPROM" +#define TR_THROTTLEWARN "THROTTLE" +#define TR_ALARMSWARN "ALARMS" +#define TR_SWITCHWARN "SWITCH" +#define TR_INVERT_THR TR("Invert Thr?","Invert Throttle?") +#define TR_SPEAKER_VOLUME INDENT "Volume" +#define TR_LCD "LCD" +#define TR_BRIGHTNESS INDENT "Brightness" +#define TR_CPU_TEMP "CPU Temp.\016>" +#define TR_CPU_CURRENT "Current\022>" +#define TR_CPU_MAH "Consumpt." +#define TR_COPROC "CoProc." +#define TR_COPROC_TEMP "MB Temp. \016>" +#define TR_CAPAWARNING INDENT "Capacity Low" +#define TR_TEMPWARNING INDENT "Overheat" +#define TR_FUNC "Func" +#define TR_V1 "V1" +#define TR_V2 "V2" +#define TR_DURATION "Duration" +#define TR_DELAY "Delay" +#define TR_SD_CARD "SD CARD" +#define TR_SDHC_CARD "SD-HC CARD" +#define TR_NO_SOUNDS_ON_SD "No Sounds on SD" +#define TR_NO_MODELS_ON_SD "No Models on SD" +#define TR_NO_BITMAPS_ON_SD "No Bitmaps on SD" +#define TR_PLAY_FILE "Play" +#define TR_DELETE_FILE "Delete" +#define TR_COPY_FILE "Copy" +#define TR_RENAME_FILE "Rename" +#define TR_ASSIGN_BITMAP "Assign Bitmap" +#define TR_REMOVED " removed" +#define TR_SD_INFO "Information" +#define TR_SD_FORMAT "Format" +#define TR_NA "N/A" +#define TR_HARDWARE "HARDWARE" +#define TR_FORMATTING "Formatting..." +#define TR_TEMP_CALIB "Temp. Calib" +#define TR_TIME "Time" +#define TR_BAUDRATE "BT Baudrate" +#define TR_SD_INFO_TITLE "SD INFO" +#define TR_SD_TYPE "Type:" +#define TR_SD_SPEED "Speed:" +#define TR_SD_SECTORS "Sectors:" +#define TR_SD_SIZE "Size:" +#define TR_TYPE "Type" +#define TR_GLOBAL_VARS "Global Variables" +#define TR_GLOBAL_VAR "Global Variable" +#define TR_MENUGLOBALVARS "GLOBAL VARIABLES" +#define TR_OWN "Own" +#define TR_DATE "Date" +#define TR_ROTARY_ENCODER "R.Encs" +#define TR_CHANNELS_MONITOR "CHANNEL MONITOR" +#define TR_INTERNALRF "Internal RF" +#define TR_EXTERNALRF "External RF" +#define TR_FAILSAFE INDENT "Failsafe mode" +#define TR_FAILSAFESET "FAILSAFE SETTINGS" +#define TR_COUNTRYCODE "Country Code" +#define TR_VOICELANG "Voice Language" +#define TR_UNITSSYSTEM "Units" +#define TR_EDIT "Edit" +#define TR_INSERT_BEFORE "Insert Before" +#define TR_INSERT_AFTER "Insert After" +#define TR_COPY "Copy" +#define TR_MOVE "Move" +#define TR_PASTE "Paste" +#define TR_DELETE "Delete" +#define TR_INSERT "Insert" +#define TR_RESET_FLIGHT "Reset Flight" +#define TR_RESET_TIMER1 "Reset Timer1" +#define TR_RESET_TIMER2 "Reset Timer2" +#define TR_RESET_TELEMETRY "Reset Telemetry" +#define TR_STATISTICS "Statistics" +#define TR_ABOUT_US "About" +#define TR_AND_SWITCH "AND Switch" +#define TR_CF "CF" +#define TR_SPEAKER INDENT"Speaker" +#define TR_BUZZER INDENT"Buzzer" +#define TR_BYTES "bytes" +#define TR_MODULE_BIND "[Bind]" +#define TR_MODULE_RANGE "[Range]" +#define TR_RESET_BTN "[Reset]" +#define TR_SET "[Set]" +#define TR_TRAINER "Trainer" +#define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!" +#define TR_MODELIDUSED TR("ID already used","Model ID already used") +#define TR_MODULE INDENT "Module" +#define TR_CHANNELRANGE INDENT "Channel Range" +#define TR_LOWALARM INDENT "Low Alarm" +#define TR_CRITICALALARM INDENT "Critical Alarm" +#define TR_PERSISTENT_MAH INDENT "Store mAh" + +#if defined(MAVLINK) + #define TR_MAVLINK_RC_RSSI_SCALE_LABEL "Max RSSI" + #define TR_MAVLINK_PC_RSSI_EN_LABEL "PC RSSI EN" + #define TR_MAVMENUSETUP_TITLE "Mavlink Setup" + #define TR_MAVLINK_BAUD_LABEL "Baudrate" + #define TR_MAVLINK_INFOS "INFOS" + #define TR_MAVLINK_MODE "MODE" + #define TR_MAVLINK_CUR_MODE "Current Mode" + #define TR_MAVLINK_ARMED "Armed" + #define TR_MAVLINK_BAT_MENU_TITLE "BAT RSSI" + #define TR_MAVLINK_BATTERY_LABEL "Flight Battery status" + #define TR_MAVLINK_RC_RSSI_LABEL "RC RSSI" + #define TR_MAVLINK_PC_RSSI_LABEL "PC RSSI" + #define TR_MAVLINK_NAV_MENU_TITLE "NAV" + #define TR_MAVLINK_COURSE "Course" + #define TR_MAVLINK_HEADING "Heading" + #define TR_MAVLINK_BEARING "Bearing" + #define TR_MAVLINK_ALTITUDE "Altitude" + #define TR_MAVLINK_GPS "GPS" + #define TR_MAVLINK_NO_FIX "NO Fix" + #define TR_MAVLINK_SAT "SAT" + #define TR_MAVLINK_HDOP "HDOP" + #define TR_MAVLINK_LAT "LAT" + #define TR_MAVLINK_LON "LON" +#endif + + + +// Taranis column headers +#define TR_PHASES_HEADERS { " Name ", " Switch ", " Trims ", " Fade In ", " Fade Out " } +#define TR_LIMITS_HEADERS { " Name ", " Subtrim ", " Min ", " Max ", " Direction ", " Curve ", " PPM Center ", " Subtrim mode " } +#define TR_CSW_HEADERS { " Function ", " V1 ", " V2 ", " AND Switch ", " Duration ", " Delay " } + +// About screen +#define TR_ABOUTUS TR(" ABOUT ", "ABOUT") + +#define TR_ABOUT_OPENTX_1 TR("OpenTX\001is\001open\001source,\001non", "OpenTX is open source, non-") +#define TR_ABOUT_OPENTX_2 TR("commercial,\001wo\001warranties.", "commercial and comes with no") +#define TR_ABOUT_OPENTX_3 TR("It\001was\001developed\001for\001free.", "warranties. It was developed") +#define TR_ABOUT_OPENTX_4 TR("Support through donations", "for free. Support through") +#define TR_ABOUT_OPENTX_5 TR("is welcome!", "donations is welcome!") + +#define TR_ABOUT_BERTRAND_1 "Bertrand Songis" +#define TR_ABOUT_BERTRAND_2 "OpenTX main author" +#define TR_ABOUT_BERTRAND_3 "Companion9x co-author" + +#define TR_ABOUT_MIKE_1 "Mike Blandford" +#define TR_ABOUT_MIKE_2 "Code and drivers guru" +#define TR_ABOUT_MIKE_3 TR("Arguably,\001one\001of\001the\001best", "Arguably, one of the best") +#define TR_ABOUT_MIKE_4 "Inspirational" + +#define TR_ABOUT_ROMOLO_1 "Romolo Manfredini" +#define TR_ABOUT_ROMOLO_2 "Companion9x co-author" +#define TR_ABOUT_ROMOLO_3 "" + +#define TR_ABOUT_ANDRE_1 "Andre Bernet" +#define TR_ABOUT_ANDRE_2 "Functionality, usability," +#define TR_ABOUT_ANDRE_3 "debugging, documentation" + +#define TR_ABOUT_ROB_1 "Rob Thomson" +#define TR_ABOUT_ROB_2 "openrcforums webmaster" + +#define TR_ABOUT_MARTIN_1 "Martin Hotar" +#define TR_ABOUT_MARTIN_2 "Graphics designer" + +#if defined(PCBTARANIS) + #define TR_ABOUT_HARDWARE_1 "FrSky" + #define TR_ABOUT_HARDWARE_2 "Hardware designer/producer" + #define TR_ABOUT_HARDWARE_3 "Firmware contributor" +#else + #define TR_ABOUT_HARDWARE_1 "Brent Nelson" + #define TR_ABOUT_HARDWARE_2 "Sky9x designer/producer" + #define TR_ABOUT_HARDWARE_3 "" +#endif + +#define TR_ABOUT_PARENTS_1 "Parent projects" +#define TR_ABOUT_PARENTS_2 TR("Ersky9x (Mike Blandford)", "Ersky9x (Mike Blandford)") +#define TR_ABOUT_PARENTS_3 "ER9X (Erez Raviv)" +#define TR_ABOUT_PARENTS_4 "TH9X (Thomas Husterer)" + +#define TR_CHR_SHORT 's' +#define TR_CHR_LONG 'l' +#define TR_CHR_TOGGLE 't' +#define TR_CHR_HOUR 'h' + +#define TR_BEEP_VOLUME "Beep Volume" +#define TR_WAV_VOLUME "Wav Volume" +#define TR_VARIO_VOLUME "Vario Volume" +#define TR_BG_VOLUME "Bg Volume" + +#define TR_TOP_BAR "Top Bar" +#define TR_ALTITUDE INDENT "Altitude" +#define TR_MODS_FORBIDDEN "Modifications forbidden!" +#define TR_UNLOCKED "Unlocked" + From ccc4096106cbd9c06e90edc53d8475a499e234a8 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:25:50 -0500 Subject: [PATCH 10/43] Update README.txt --- README.txt | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 345e6aef7..70103f756 100644 --- a/README.txt +++ b/README.txt @@ -1 +1,29 @@ -Test +Add Gear Ratio to RPM Telemetry Calculation and allow for Blades to equal 1 + +Jan 16 2014 +- Switched to 'next' branch +- Need to solve issue with frsky_sport.cpp and calc compile error + + +Jan 15 2014 +•Fully working in Simulator now, new options for Spur and Pinion are in Telemetry setup screen for the model. Pinion is forced to stay equal to or smaller than spur (to prevent divide by zero). +•Tested on Taranis Rev A (eeprom is modified so backup everything before experimenting). + + +Jan 14 2014 +•The current implementation of OpenTX has a few limitations with regards to RPM sensors on Nitro Helicopters and this patch is to resolve and improve that. + +•Initial changes to make: +◦Change Minimum Blades to 1 (currently hardcoded to 2) to allow for Fan RPM Sensors (single magnet) and crank sensors. +◦Change Maximum Blades to 255 (currently limited to 5) to allow for any number of divider for both nitro or electric. +◦Add Spur Gear USRDATA option to assist with calculating head speed +◦Add Pinion Gear USRDATA option to assist with calculating head speed +◦Change RPM telemetry calculation to take into account gear ratio based upon Spur and Pinion size + + +•Future: +◦Add new telemtry calculated value "HDSP" for Headspeed to allow user to see engine RPM and calculated headspeed +◦Add more options for electric setups + + +Author - Tim Foley From 5219d9d53b97c47626a5d4d2914b586cb5189a24 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:27:27 -0500 Subject: [PATCH 11/43] Delete translations.cpp~ --- radio/src/translations.cpp~ | 672 ------------------------------------ 1 file changed, 672 deletions(-) delete mode 100644 radio/src/translations.cpp~ diff --git a/radio/src/translations.cpp~ b/radio/src/translations.cpp~ deleted file mode 100644 index 98d62ab7b..000000000 --- a/radio/src/translations.cpp~ +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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" - -#define ISTR(x) LEN_##x TR_##x - -// The non-0-terminated-strings -const pm_char STR_OPEN9X[] PROGMEM = - ISTR(OFFON) - ISTR(MMMINV) - ISTR(NCHANNELS) -#if !defined(GRAPHICS) - ISTR(VBEEPLEN) -#endif - ISTR(VBEEPMODE) -#if defined(ROTARY_ENCODERS) - ISTR(VRENAVIG) -#endif -#if defined(ROTARY_ENCODER_NAVIGATION) - ISTR(VRENCODERS) -#endif - ISTR(TRNMODE) - ISTR(TRNCHN) - ISTR(VTRIMINC) - ISTR(RETA123) - ISTR(VPROTOS) - ISTR(POSNEG) - ISTR(VBLMODE) - ISTR(VCURVEFUNC) - ISTR(VMLTPX) - ISTR(VMLTPX2) - ISTR(VMIXTRIMS) - ISTR(VCSWFUNC) - ISTR(VFSWFUNC) - ISTR(VFSWRESET) - ISTR(FUNCSOUNDS) - ISTR(VTELEMCHNS) -#if defined(FRSKY) || defined(CPUARM) - #if defined(CPUARM) - ISTR(VTELEMUNIT_IMP) - ISTR(VTELEMUNIT_NORM) - #else - ISTR(VTELEMUNIT) - #endif - ISTR(VALARM) - ISTR(VALARMFN) - ISTR(VTELPROTO) - ISTR(GPSFORMAT) - ISTR(VOLTSRC) - ISTR(VARIOSRC) - ISTR(VSCREEN) -#endif -#if defined(TEMPLATES) - ISTR(VTEMPLATES) -#endif -#if defined(HELI) - ISTR(VSWASHTYPE) -#endif - ISTR(VKEYS) - ISTR(VSWITCHES) - ISTR(VSRCRAW) - ISTR(VTMRMODES) -#if defined(CPUM2560) || defined(CPUARM) - ISTR(DATETIME) -#endif -#if defined(CPUARM) - ISTR(VLCD) - ISTR(VUNITSSYSTEM) - ISTR(VBEEPCOUNTDOWN) -#endif -#if defined(PXX) - ISTR(COUNTRYCODES) - ISTR(VFAILSAFE) -#endif -#if defined(PCBTARANIS) - ISTR(VTRAINERMODES) -#endif -#if defined(MAVLINK) - ISTR(MAVLINK_BAUDS) - ISTR(MAVLINK_AC_MODES) - ISTR(MAVLINK_AP_MODES) -#endif - ; - -// The 0-terminated-strings -const pm_char STR_POPUPS[] PROGMEM = TR_POPUPS; -const pm_char STR_MENUWHENDONE[] PROGMEM = TR_MENUWHENDONE; -const pm_char STR_FREE[] PROGMEM = TR_FREE; -const pm_char STR_DELETEMODEL[] PROGMEM = TR_DELETEMODEL; -const pm_char STR_COPYINGMODEL[] PROGMEM = TR_COPYINGMODEL; -const pm_char STR_MOVINGMODEL[] PROGMEM = TR_MOVINGMODEL; -const pm_char STR_LOADINGMODEL[] PROGMEM = TR_LOADINGMODEL; -const pm_char STR_NAME[] PROGMEM = TR_NAME; -const pm_char STR_BITMAP[] PROGMEM = TR_BITMAP; -const pm_char STR_TIMER[] PROGMEM = TR_TIMER; -const pm_char STR_ELIMITS[] PROGMEM = TR_ELIMITS; -const pm_char STR_ETRIMS[] PROGMEM = TR_ETRIMS; -const pm_char STR_TRIMINC[] PROGMEM = TR_TRIMINC; -const pm_char STR_TTRACE[] PROGMEM = TR_TTRACE; -const pm_char STR_TTRIM[] PROGMEM = TR_TTRIM; -const pm_char STR_BEEPCTR[] PROGMEM = TR_BEEPCTR; -const pm_char STR_PROTO[] PROGMEM = TR_PROTO; -const pm_char STR_PPMFRAME[] PROGMEM = TR_PPMFRAME; -const pm_char STR_MS[] PROGMEM = TR_MS; -const pm_char STR_SWITCH[] PROGMEM = TR_SWITCH; -const pm_char STR_TRIMS[] PROGMEM = TR_TRIMS; -const pm_char STR_FADEIN[] PROGMEM = TR_FADEIN; -const pm_char STR_FADEOUT[] PROGMEM = TR_FADEOUT; -const pm_char STR_DEFAULT[] PROGMEM = TR_DEFAULT; -const pm_char STR_CHECKTRIMS[] PROGMEM = TR_CHECKTRIMS; -#ifdef HELI -const pm_char STR_SWASHTYPE[] PROGMEM = TR_SWASHTYPE; -const pm_char STR_COLLECTIVE[] PROGMEM = TR_COLLECTIVE; -const pm_char STR_SWASHRING[] PROGMEM = TR_SWASHRING; -const pm_char STR_ELEDIRECTION[] PROGMEM = TR_ELEDIRECTION; -const pm_char STR_AILDIRECTION[] PROGMEM = TR_AILDIRECTION; -const pm_char STR_COLDIRECTION[] PROGMEM = TR_COLDIRECTION; -#endif -const pm_char STR_MODE[] PROGMEM = TR_MODE; -#if defined(AUDIO) && defined(BUZZER) -const pm_char STR_SPEAKER[] PROGMEM = TR_SPEAKER; -const pm_char STR_BUZZER[] PROGMEM = TR_BUZZER; -#endif -const pm_char STR_NOFREEEXPO[] PROGMEM = TR_NOFREEEXPO; -const pm_char STR_NOFREEMIXER[] PROGMEM = TR_NOFREEMIXER; -const pm_char STR_INSERTMIX[] PROGMEM = TR_INSERTMIX; -const pm_char STR_EDITMIX[] PROGMEM = TR_EDITMIX; -const pm_char STR_SOURCE[] PROGMEM = TR_SOURCE; -const pm_char STR_WEIGHT[] PROGMEM = TR_WEIGHT; -const pm_char STR_EXPO[] PROGMEM = TR_EXPO; -const pm_char STR_SIDE[] PROGMEM = TR_SIDE; -const pm_char STR_DIFFERENTIAL[] PROGMEM = TR_DIFFERENTIAL; -const pm_char STR_OFFSET[] PROGMEM = TR_OFFSET; -const pm_char STR_TRIM[] PROGMEM = TR_TRIM; -const pm_char STR_DREX[] PROGMEM = TR_DREX; -const pm_char STR_CURVE[] PROGMEM = TR_CURVE; -const pm_char STR_FLMODE[] PROGMEM = TR_FLMODE; -const pm_char STR_MIXWARNING[] PROGMEM = TR_MIXWARNING; -const pm_char STR_OFF[] PROGMEM = TR_OFF; -const pm_char STR_MULTPX[] PROGMEM = TR_MULTPX; -const pm_char STR_DELAYDOWN[] PROGMEM = TR_DELAYDOWN; -const pm_char STR_DELAYUP[] PROGMEM = TR_DELAYUP; -const pm_char STR_SLOWDOWN[] PROGMEM = TR_SLOWDOWN; -const pm_char STR_SLOWUP[] PROGMEM = TR_SLOWUP; -const pm_char STR_MIXER[] PROGMEM = TR_MIXER; -const pm_char STR_CV[] PROGMEM = TR_CV; -const pm_char STR_GV[] PROGMEM = TR_GV; -const pm_char STR_ACHANNEL[] PROGMEM = TR_ACHANNEL; -const pm_char STR_RANGE[] PROGMEM = TR_RANGE; -const pm_char STR_BAR[] PROGMEM = TR_BAR; -const pm_char STR_ALARM[] PROGMEM = TR_ALARM; -const pm_char STR_USRDATA[] PROGMEM = TR_USRDATA; -const pm_char STR_BLADES[] PROGMEM = TR_BLADES; -const pm_char STR_SCREEN[] PROGMEM = TR_SCREEN; -const pm_char STR_SOUND_LABEL[] PROGMEM = TR_SOUND_LABEL; -const pm_char STR_LENGTH[] PROGMEM = TR_LENGTH; -#if defined(AUDIO) -const pm_char STR_SPKRPITCH[] PROGMEM = TR_SPKRPITCH; -#endif -#if defined(HAPTIC) -const pm_char STR_HAPTIC_LABEL[] PROGMEM = TR_HAPTIC_LABEL; -const pm_char STR_HAPTICSTRENGTH[] PROGMEM = TR_HAPTICSTRENGTH; -#endif -const pm_char STR_CONTRAST[] PROGMEM = TR_CONTRAST; -const pm_char STR_ALARMS_LABEL[] PROGMEM = TR_ALARMS_LABEL; -#if defined(BATTGRAPH) || defined(PCBTARANIS) -const pm_char STR_BATTERY_RANGE[] PROGMEM = TR_BATTERY_RANGE; -#endif -const pm_char STR_BATTERYWARNING[] PROGMEM = TR_BATTERYWARNING; -const pm_char STR_INACTIVITYALARM[] PROGMEM = TR_INACTIVITYALARM; -const pm_char STR_MEMORYWARNING[] PROGMEM = TR_MEMORYWARNING; -const pm_char STR_ALARMWARNING[] PROGMEM = TR_ALARMWARNING; -#if defined(ROTARY_ENCODERS) -const pm_char STR_RENAVIG[] PROGMEM = TR_RENAVIG; -#endif -const pm_char STR_THROTTLEREVERSE[] PROGMEM = TR_THROTTLEREVERSE; -const pm_char STR_MINUTEBEEP[] PROGMEM = TR_MINUTEBEEP; -const pm_char STR_BEEPCOUNTDOWN[] PROGMEM = TR_BEEPCOUNTDOWN; -const pm_char STR_PERSISTENT[] PROGMEM = TR_PERSISTENT; -const pm_char STR_BACKLIGHT_LABEL[] PROGMEM = TR_BACKLIGHT_LABEL; -const pm_char STR_BLDELAY[] PROGMEM = TR_BLDELAY; - -#if defined(PWM_BACKLIGHT) -const pm_char STR_BLONBRIGHTNESS[] PROGMEM = TR_BLONBRIGHTNESS; -const pm_char STR_BLOFFBRIGHTNESS[] PROGMEM = TR_BLOFFBRIGHTNESS; -#endif - -const pm_char STR_SPLASHSCREEN[] PROGMEM = TR_SPLASHSCREEN; -const pm_char STR_THROTTLEWARNING[] PROGMEM = TR_THROTTLEWARNING; -const pm_char STR_SWITCHWARNING[] PROGMEM = TR_SWITCHWARNING; -#ifdef FRSKY -const pm_char STR_TIMEZONE[] PROGMEM = TR_TIMEZONE; -const pm_char STR_GPSCOORD[] PROGMEM = TR_GPSCOORD; -const pm_char STR_VARIO[] PROGMEM = TR_VARIO; -#endif -const pm_char STR_RXCHANNELORD[] PROGMEM = TR_RXCHANNELORD; -const pm_char STR_SLAVE[] PROGMEM = TR_SLAVE; -const pm_char STR_MODESRC[] PROGMEM = TR_MODESRC; -const pm_char STR_MULTIPLIER[] PROGMEM = TR_MULTIPLIER; -const pm_char STR_CAL[] PROGMEM = TR_CAL; -const pm_char STR_VTRIM[] PROGMEM = TR_VTRIM; -const pm_char STR_BG[] PROGMEM = TR_BG; -const pm_char STR_MENUTOSTART[] PROGMEM = TR_MENUTOSTART; -const pm_char STR_SETMIDPOINT[] PROGMEM = TR_SETMIDPOINT; -const pm_char STR_MOVESTICKSPOTS[] PROGMEM = TR_MOVESTICKSPOTS; -const pm_char STR_RXBATT[] PROGMEM = TR_RXBATT; -const pm_char STR_TX[] PROGMEM = TR_TXnRX; -const pm_char STR_ACCEL[] PROGMEM = TR_ACCEL; -const pm_char STR_NODATA[] PROGMEM = TR_NODATA; -const pm_char STR_TM1TM2[] PROGMEM = TR_TM1TM2; -const pm_char STR_THRTHP[] PROGMEM = TR_THRTHP; -const pm_char STR_TOT[] PROGMEM = TR_TOT; -const pm_char STR_TMR1LATMAXUS[] PROGMEM = TR_TMR1LATMAXUS; -const pm_char STR_TMR1LATMINUS[] PROGMEM = TR_TMR1LATMINUS; -const pm_char STR_TMR1JITTERUS[] PROGMEM = TR_TMR1JITTERUS; -const pm_char STR_TMIXMAXMS[] PROGMEM = TR_TMIXMAXMS; -const pm_char STR_FREESTACKMINB[] PROGMEM = TR_FREESTACKMINB; -const pm_char STR_MENUTORESET[] PROGMEM = TR_MENUTORESET; -const pm_char STR_PPM[] PROGMEM = TR_PPM; -const pm_char STR_CH[] PROGMEM = TR_CH; -const pm_char STR_MODEL[] PROGMEM = TR_MODEL; -const pm_char STR_FP[] PROGMEM = TR_FP; -const pm_char STR_MIX[] PROGMEM = TR_MIX; -const pm_char STR_EEPROMLOWMEM[] PROGMEM = TR_EEPROMLOWMEM; -const pm_char STR_ALERT[] PROGMEM = TR_ALERT; -const pm_char STR_PRESSANYKEYTOSKIP[] PROGMEM = TR_PRESSANYKEYTOSKIP; -const pm_char STR_THROTTLENOTIDLE[] PROGMEM = TR_THROTTLENOTIDLE; -const pm_char STR_ALARMSDISABLED[] PROGMEM = TR_ALARMSDISABLED; -const pm_char STR_PRESSANYKEY[] PROGMEM = TR_PRESSANYKEY; -const pm_char STR_BADEEPROMDATA[] PROGMEM = TR_BADEEPROMDATA; -const pm_char STR_EEPROMFORMATTING[] PROGMEM = TR_EEPROMFORMATTING; -const pm_char STR_EEPROMOVERFLOW[] PROGMEM = TR_EEPROMOVERFLOW; -const pm_char STR_TRIMS2OFFSETS[] PROGMEM = TR_TRIMS2OFFSETS; -const pm_char STR_MENURADIOSETUP[] PROGMEM = TR_MENURADIOSETUP; - -#if defined(CPUM2560) || defined(CPUARM) -const pm_char STR_MENUDATEANDTIME[] PROGMEM = TR_MENUDATEANDTIME; -#endif - -const pm_char STR_MENUTRAINER[] PROGMEM = TR_MENUTRAINER; -const pm_char STR_MENUVERSION[] PROGMEM = TR_MENUVERSION; -const pm_char STR_MENUDIAG[] PROGMEM = TR_MENUDIAG; -const pm_char STR_MENUANA[] PROGMEM = TR_MENUANA; -const pm_char STR_MENUCALIBRATION[] PROGMEM = TR_MENUCALIBRATION; - -const pm_char STR_MENUMODELSEL[] PROGMEM = TR_MENUMODELSEL; -const pm_char STR_MENUSETUP[] PROGMEM = TR_MENUSETUP; -const pm_char STR_MENUFLIGHTPHASE[] PROGMEM = TR_MENUFLIGHTPHASE; -const pm_char STR_MENUFLIGHTPHASES[] PROGMEM = TR_MENUFLIGHTPHASES; - -#ifdef HELI -const pm_char STR_MENUHELISETUP[] PROGMEM = TR_MENUHELISETUP; -#endif - -const pm_char STR_MENUINPUTS[] PROGMEM = TR_MENUINPUTS; -const pm_char STR_MENULIMITS[] PROGMEM = TR_MENULIMITS; -const pm_char STR_MENUCURVES[] PROGMEM = TR_MENUCURVES; -const pm_char STR_MENUCURVE[] PROGMEM = TR_MENUCURVE; -const pm_char STR_MENUCUSTOMSWITCH[] PROGMEM = TR_MENUCUSTOMSWITCH; -const pm_char STR_MENUCUSTOMSWITCHES[] PROGMEM = TR_MENUCUSTOMSWITCHES; -const pm_char STR_MENUCUSTOMFUNC[] PROGMEM = TR_MENUCUSTOMFUNC; - -#if defined(LUA) -const pm_char STR_MENUCUSTOMSCRIPTS[] PROGMEM = "CUSTOM SCRIPTS"; -const pm_char STR_MENUCUSTOMSCRIPT[] PROGMEM = "CUSTOM SCRIPT"; -#endif - -#if defined(FRSKY) -const pm_char STR_MENUTELEMETRY[] PROGMEM = TR_MENUTELEMETRY; -const pm_char STR_LIMIT[] PROGMEM = TR_LIMIT; -#endif - -#if defined(TEMPLATES) -const pm_char STR_MENUTEMPLATES[] PROGMEM = TR_MENUTEMPLATES; -#endif - -const pm_char STR_MENUSTAT[] PROGMEM = TR_MENUSTAT; -const pm_char STR_MENUDEBUG[] PROGMEM = TR_MENUDEBUG; -const pm_char STR_MENUGLOBALVARS[] PROGMEM = TR_MENUGLOBALVARS; - -#if defined(DSM2) || defined(PXX) -const pm_char STR_RXNUM[] PROGMEM = TR_RXNUM; -#endif - -#if defined(PXX) -const pm_char STR_SYNCMENU[] PROGMEM = TR_SYNCMENU; -const pm_char STR_INTERNALRF[] PROGMEM = TR_INTERNALRF; -const pm_char STR_EXTERNALRF[] PROGMEM = TR_EXTERNALRF; -const pm_char STR_COUNTRYCODE[] PROGMEM = TR_COUNTRYCODE; -const pm_char STR_FAILSAFE[] PROGMEM = TR_FAILSAFE; -const pm_char STR_FAILSAFESET[] PROGMEM = TR_FAILSAFESET; -#endif - -const pm_char STR_INVERT_THR[] PROGMEM = TR_INVERT_THR; -const pm_char STR_AND_SWITCH[] PROGMEM = TR_AND_SWITCH; -extern const pm_char STR_CF[] PROGMEM = TR_CF; - -#if defined(FRSKY_HUB) -const pm_char STR_MINRSSI[] PROGMEM = TR_MINRSSI; -const pm_char STR_LATITUDE[] PROGMEM = TR_LATITUDE; -const pm_char STR_LONGITUDE[] PROGMEM = TR_LONGITUDE; -#endif - -#if defined(CPUARM) || defined(CPUM2560) -const pm_char STR_SHUTDOWN[] PROGMEM = TR_SHUTDOWN; -#endif - -const pm_char STR_BATT_CALIB[] PROGMEM = TR_BATT_CALIB; - -#if defined(CPUARM) || defined(FRSKY) -const pm_char STR_VOLTAGE[] PROGMEM = TR_VOLTAGE; -const pm_char STR_CURRENT[] PROGMEM = TR_CURRENT; -#endif - -#if defined(CPUARM) -const pm_char STR_CURRENT_CALIB[] PROGMEM = TR_CURRENT_CALIB; -const pm_char STR_UNITSSYSTEM[] PROGMEM = TR_UNITSSYSTEM; -const pm_char STR_VOICELANG[] PROGMEM = TR_VOICELANG; -const pm_char STR_MODELIDUSED[] PROGMEM = TR_MODELIDUSED; -const pm_char STR_BEEP_VOLUME[] PROGMEM = INDENT TR_BEEP_VOLUME; -const pm_char STR_WAV_VOLUME[] PROGMEM = INDENT TR_WAV_VOLUME; -const pm_char STR_VARIO_VOLUME[] PROGMEM = INDENT TR_VARIO_VOLUME; -const pm_char STR_BG_VOLUME[] PROGMEM = INDENT TR_BG_VOLUME; -const pm_char STR_PERSISTENT_MAH[] PROGMEM = TR_PERSISTENT_MAH; -#endif - -#if defined(NAVIGATION_MENUS) -const pm_char STR_SELECT_MODEL[] PROGMEM = TR_SELECT_MODEL; -const pm_char STR_CREATE_MODEL[] PROGMEM = TR_CREATE_MODEL; -const pm_char STR_COPY_MODEL[] PROGMEM = TR_COPY_MODEL; -const pm_char STR_MOVE_MODEL[] PROGMEM = TR_MOVE_MODEL; -const pm_char STR_DELETE_MODEL[] PROGMEM = TR_DELETE_MODEL; -const pm_char STR_EDIT[] PROGMEM = TR_EDIT; -const pm_char STR_INSERT_BEFORE[] PROGMEM = TR_INSERT_BEFORE; -const pm_char STR_INSERT_AFTER[] PROGMEM = TR_INSERT_AFTER; -const pm_char STR_COPY[] PROGMEM = TR_COPY; -const pm_char STR_MOVE[] PROGMEM = TR_MOVE; -const pm_char STR_PASTE[] PROGMEM = TR_PASTE; -const pm_char STR_INSERT[] PROGMEM = TR_INSERT; -const pm_char STR_DELETE[] PROGMEM = TR_DELETE; -const pm_char STR_RESET_FLIGHT[] PROGMEM = TR_RESET_FLIGHT; -const pm_char STR_RESET_TIMER1[] PROGMEM = TR_RESET_TIMER1; -const pm_char STR_RESET_TIMER2[] PROGMEM = TR_RESET_TIMER2; -const pm_char STR_RESET_TELEMETRY[] PROGMEM = TR_RESET_TELEMETRY; -const pm_char STR_STATISTICS[] PROGMEM = TR_STATISTICS; -const pm_char STR_ABOUT_US[] PROGMEM = TR_ABOUT_US; -#endif - -const pm_char STR_RESET_BTN[] PROGMEM = TR_RESET_BTN; - -#if defined(SDCARD) -const pm_char STR_BACKUP_MODEL[] PROGMEM = TR_BACKUP_MODEL; -const pm_char STR_RESTORE_MODEL[] PROGMEM = TR_RESTORE_MODEL; -const pm_char STR_SDCARD_ERROR[] PROGMEM = TR_SDCARD_ERROR; -const pm_char STR_NO_SDCARD[] PROGMEM = TR_NO_SDCARD; -const pm_char STR_INCOMPATIBLE[] PROGMEM = TR_INCOMPATIBLE; -const pm_char STR_LOGS_PATH[] PROGMEM = LOGS_PATH; -const pm_char STR_LOGS_EXT[] PROGMEM = LOGS_EXT; -const pm_char STR_MODELS_PATH[] PROGMEM = MODELS_PATH; -const pm_char STR_MODELS_EXT[] PROGMEM = MODELS_EXT; -#endif - -const pm_char STR_WARNING[] PROGMEM = TR_WARNING; -const pm_char STR_EEPROMWARN[] PROGMEM = TR_EEPROMWARN; -const pm_char STR_THROTTLEWARN[] PROGMEM = TR_THROTTLEWARN; -const pm_char STR_ALARMSWARN[] PROGMEM = TR_ALARMSWARN; -const pm_char STR_SWITCHWARN[] PROGMEM = TR_SWITCHWARN; - -const pm_char STR_SPEAKER_VOLUME[] PROGMEM = TR_SPEAKER_VOLUME; -const pm_char STR_LCD[] PROGMEM = TR_LCD; -const pm_char STR_BRIGHTNESS[] PROGMEM = TR_BRIGHTNESS; -const pm_char STR_CPU_TEMP[] PROGMEM = TR_CPU_TEMP; -const pm_char STR_CPU_CURRENT[] PROGMEM = TR_CPU_CURRENT; -const pm_char STR_CPU_MAH[] PROGMEM = TR_CPU_MAH; -const pm_char STR_COPROC[] PROGMEM = TR_COPROC; -const pm_char STR_COPROC_TEMP[] PROGMEM = TR_COPROC_TEMP; -const pm_char STR_TEMPWARNING[] PROGMEM = TR_TEMPWARNING; -const pm_char STR_CAPAWARNING[] PROGMEM = TR_CAPAWARNING; -const pm_char STR_FUNC[] PROGMEM = TR_FUNC; -const pm_char STR_V1[] PROGMEM = TR_V1; -const pm_char STR_V2[] PROGMEM = TR_V2; -const pm_char STR_DURATION[] PROGMEM = TR_DURATION; -const pm_char STR_DELAY[] PROGMEM = TR_DELAY; -const pm_char STR_SD_CARD[] PROGMEM = TR_SD_CARD; -const pm_char STR_SDHC_CARD[] PROGMEM = TR_SDHC_CARD; -const pm_char STR_NO_SOUNDS_ON_SD[] PROGMEM = TR_NO_SOUNDS_ON_SD; -const pm_char STR_NO_MODELS_ON_SD[] PROGMEM = TR_NO_MODELS_ON_SD; -const pm_char STR_NO_BITMAPS_ON_SD[] PROGMEM = TR_NO_BITMAPS_ON_SD; -const pm_char STR_NO_SCRIPTS_ON_SD[] PROGMEM = "No Scripts on SD"; // TODO TR_NO_BITMAPS_ON_SD; -const pm_char STR_PLAY_FILE[] PROGMEM = TR_PLAY_FILE; -const pm_char STR_ASSIGN_BITMAP[] PROGMEM = TR_ASSIGN_BITMAP; -const pm_char STR_EXECUTE_FILE[] PROGMEM = "Execute"; -const pm_char STR_DELETE_FILE[] PROGMEM = TR_DELETE_FILE; -const pm_char STR_COPY_FILE[] PROGMEM = TR_COPY_FILE; -const pm_char STR_RENAME_FILE[] PROGMEM = TR_RENAME_FILE; -const pm_char STR_SD_INFO[] PROGMEM = TR_SD_INFO; -const pm_char STR_SD_FORMAT[] PROGMEM = TR_SD_FORMAT; -const pm_char STR_REMOVED[] PROGMEM = TR_REMOVED; -const pm_char STR_NA[] PROGMEM = TR_NA; -const pm_char STR_HARDWARE[] PROGMEM = TR_HARDWARE; -const pm_char STR_FORMATTING[] PROGMEM = TR_FORMATTING; -const pm_char STR_TEMP_CALIB[] PROGMEM = TR_TEMP_CALIB; -const pm_char STR_TIME[] PROGMEM = TR_TIME; -const pm_char STR_BAUDRATE[] PROGMEM = TR_BAUDRATE; -const pm_char STR_SD_INFO_TITLE[] PROGMEM = TR_SD_INFO_TITLE; -const pm_char STR_SD_TYPE[] PROGMEM = TR_SD_TYPE; -const pm_char STR_SD_SPEED[] PROGMEM = TR_SD_SPEED; -const pm_char STR_SD_SECTORS[] PROGMEM = TR_SD_SECTORS; -const pm_char STR_SD_SIZE[] PROGMEM = TR_SD_SIZE; -const pm_char STR_TYPE[] PROGMEM = TR_TYPE; -const pm_char STR_GLOBAL_VARS[] PROGMEM = TR_GLOBAL_VARS; -const pm_char STR_GLOBAL_VAR[] PROGMEM = TR_GLOBAL_VAR; -const pm_char STR_OWN[] PROGMEM = TR_OWN; -const pm_char STR_ROTARY_ENCODER[] PROGMEM = TR_ROTARY_ENCODER; -const pm_char STR_DATE[] PROGMEM = TR_DATE; -const pm_char STR_CHANNELS_MONITOR[] PROGMEM = TR_CHANNELS_MONITOR; -const pm_char STR_PATH_TOO_LONG[] PROGMEM = "Path too long"; -const pm_char STR_VIEW_TEXT[] PROGMEM = "View text"; - -#if LCD_W >= 212 - const pm_char STR_MODELNAME[] PROGMEM = TR_MODELNAME; - const pm_char STR_PHASENAME[] PROGMEM = TR_PHASENAME; - const pm_char STR_MIXNAME[] PROGMEM = TR_MIXNAME; - const pm_char STR_EXPONAME[] PROGMEM = TR_EXPONAME; -#endif - -#if LCD_W >= 212 - const char * STR_PHASES_HEADERS[] = TR_PHASES_HEADERS; - const char * STR_LIMITS_HEADERS[] = TR_LIMITS_HEADERS; - const char * STR_CSW_HEADERS[] = TR_CSW_HEADERS; -#endif - -#if defined(PCBTARANIS) - const pm_char STR_BYTES[] PROGMEM = TR_BYTES; - const pm_char STR_MODULE_BIND[] PROGMEM = TR_MODULE_BIND; - const pm_char STR_SET[] PROGMEM = TR_SET; - const pm_char STR_TRAINER[] PROGMEM = TR_TRAINER; - const pm_char STR_ANTENNAPROBLEM[] PROGMEM = TR_ANTENNAPROBLEM; - const pm_char STR_MODULE[] PROGMEM = TR_MODULE; - const pm_char STR_CHANNELRANGE[] PROGMEM = TR_CHANNELRANGE; - const pm_char STR_LOWALARM[] PROGMEM = TR_LOWALARM; - const pm_char STR_CRITICALALARM[] PROGMEM = TR_CRITICALALARM; - const pm_char STR_ENABLE_POPUP[] PROGMEM = "Enable Popup"; - const pm_char STR_DISABLE_POPUP[] PROGMEM = "Disable Popup"; - const pm_char STR_CURVE_PRESET[] PROGMEM = "Preset..."; - const pm_char STR_PRESET[] PROGMEM = "Preset"; - const pm_char STR_MIRROR[] PROGMEM = "Mirror"; - const pm_char STR_CLEAR[] PROGMEM = "Clear"; - const pm_char STR_RESET[] PROGMEM = "Reset"; - const pm_char STR_COPY_TRIMS_TO_OFFSET[] = "Copy Trims To Offset"; - const pm_char STR_TOP_BAR[] PROGMEM = "Top Bar"; - const pm_char STR_ALTITUDE[] PROGMEM = INDENT "Altitude"; - const pm_char STR_SCALE[] PROGMEM = "Scale"; - const pm_char STR_VIEW_CHANNELS[] PROGMEM = "View Channels"; - const pm_char STR_VIEW_NOTES[] PROGMEM = "View Notes"; -#endif - -#if MENUS_LOCK == 1 - const pm_char STR_UNLOCKED[] PROGMEM = TR_UNLOCKED; - const pm_char STR_MODS_FORBIDDEN[] PROGMEM = TR_MODS_FORBIDDEN; -#endif - -#if defined(PCBTARANIS) || defined(DSM2) - const pm_char STR_MODULE_RANGE[] PROGMEM = TR_MODULE_RANGE; -#endif - -#if defined(MAVLINK) - const pm_char STR_MAVLINK_RC_RSSI_SCALE_LABEL[] PROGMEM = TR_MAVLINK_RC_RSSI_SCALE_LABEL; - const pm_char STR_MAVLINK_PC_RSSI_EN_LABEL[] PROGMEM = TR_MAVLINK_PC_RSSI_EN_LABEL; - const pm_char STR_MAVMENUSETUP_TITLE[] PROGMEM = TR_MAVMENUSETUP_TITLE; - const pm_char STR_MAVLINK_BAUD_LABEL[] PROGMEM = TR_MAVLINK_BAUD_LABEL; - const pm_char STR_MAVLINK_INFOS[] PROGMEM = TR_MAVLINK_INFOS; - const pm_char STR_MAVLINK_MODE[] PROGMEM = TR_MAVLINK_MODE; - const pm_char STR_MAVLINK_CUR_MODE[] PROGMEM = TR_MAVLINK_CUR_MODE; - const pm_char STR_MAVLINK_ARMED[] PROGMEM = TR_MAVLINK_ARMED; - const pm_char STR_MAVLINK_BAT_MENU_TITLE[] PROGMEM = TR_MAVLINK_BAT_MENU_TITLE; - const pm_char STR_MAVLINK_BATTERY_LABEL[] PROGMEM = TR_MAVLINK_BATTERY_LABEL; - const pm_char STR_MAVLINK_RC_RSSI_LABEL[] PROGMEM = TR_MAVLINK_RC_RSSI_LABEL; - const pm_char STR_MAVLINK_PC_RSSI_LABEL[] PROGMEM = TR_MAVLINK_PC_RSSI_LABEL; - const pm_char STR_MAVLINK_NAV_MENU_TITLE[] PROGMEM = TR_MAVLINK_NAV_MENU_TITLE; - const pm_char STR_MAVLINK_COURSE[] PROGMEM = TR_MAVLINK_COURSE; - const pm_char STR_MAVLINK_HEADING[] PROGMEM = TR_MAVLINK_HEADING; - const pm_char STR_MAVLINK_BEARING[] PROGMEM = TR_MAVLINK_BEARING; - const pm_char STR_MAVLINK_ALTITUDE[] PROGMEM = TR_MAVLINK_ALTITUDE; - const pm_char STR_MAVLINK_GPS[] PROGMEM = TR_MAVLINK_GPS; - const pm_char STR_MAVLINK_NO_FIX[] PROGMEM = TR_MAVLINK_NO_FIX; - const pm_char STR_MAVLINK_SAT[] PROGMEM = TR_MAVLINK_SAT; - const pm_char STR_MAVLINK_HDOP[] PROGMEM = TR_MAVLINK_HDOP; - const pm_char STR_MAVLINK_LAT[] PROGMEM = TR_MAVLINK_LAT; - const pm_char STR_MAVLINK_LON[] PROGMEM = TR_MAVLINK_LON; -#endif - -#if !defined(CPUM64) - const pm_char STR_ABOUTUS[] PROGMEM = TR_ABOUTUS; - const pm_char STR_ABOUT_OPENTX_1[] PROGMEM = TR_ABOUT_OPENTX_1; - const pm_char STR_ABOUT_OPENTX_2[] PROGMEM = TR_ABOUT_OPENTX_2; - const pm_char STR_ABOUT_OPENTX_3[] PROGMEM = TR_ABOUT_OPENTX_3; - const pm_char STR_ABOUT_OPENTX_4[] PROGMEM = TR_ABOUT_OPENTX_4; - const pm_char STR_ABOUT_OPENTX_5[] PROGMEM = TR_ABOUT_OPENTX_5; - - const pm_char STR_ABOUT_BERTRAND_1[] PROGMEM = TR_ABOUT_BERTRAND_1; - const pm_char STR_ABOUT_BERTRAND_2[] PROGMEM = TR_ABOUT_BERTRAND_2; - const pm_char STR_ABOUT_BERTRAND_3[] PROGMEM = TR_ABOUT_BERTRAND_3; - - const pm_char STR_ABOUT_MIKE_1[] PROGMEM = TR_ABOUT_MIKE_1; - const pm_char STR_ABOUT_MIKE_2[] PROGMEM = TR_ABOUT_MIKE_2; - const pm_char STR_ABOUT_MIKE_3[] PROGMEM = TR_ABOUT_MIKE_3; - const pm_char STR_ABOUT_MIKE_4[] PROGMEM = TR_ABOUT_MIKE_4; - - const pm_char STR_ABOUT_ROMOLO_1[] PROGMEM = TR_ABOUT_ROMOLO_1; - const pm_char STR_ABOUT_ROMOLO_2[] PROGMEM = TR_ABOUT_ROMOLO_2; - const pm_char STR_ABOUT_ROMOLO_3[] PROGMEM = TR_ABOUT_ROMOLO_3; - - const pm_char STR_ABOUT_ANDRE_1[] PROGMEM = TR_ABOUT_ANDRE_1; - const pm_char STR_ABOUT_ANDRE_2[] PROGMEM = TR_ABOUT_ANDRE_2; - const pm_char STR_ABOUT_ANDRE_3[] PROGMEM = TR_ABOUT_ANDRE_3; - - const pm_char STR_ABOUT_ROB_1[] PROGMEM = TR_ABOUT_ROB_1; - const pm_char STR_ABOUT_ROB_2[] PROGMEM = TR_ABOUT_ROB_2; - - const pm_char STR_ABOUT_MARTIN_1[] PROGMEM = TR_ABOUT_MARTIN_1; - const pm_char STR_ABOUT_MARTIN_2[] PROGMEM = TR_ABOUT_MARTIN_2; - - const pm_char STR_ABOUT_HARDWARE_1[] PROGMEM = TR_ABOUT_HARDWARE_1; - const pm_char STR_ABOUT_HARDWARE_2[] PROGMEM = TR_ABOUT_HARDWARE_2; - const pm_char STR_ABOUT_HARDWARE_3[] PROGMEM = TR_ABOUT_HARDWARE_3; - - const pm_char STR_ABOUT_PARENTS_1[] PROGMEM = TR_ABOUT_PARENTS_1; - const pm_char STR_ABOUT_PARENTS_2[] PROGMEM = TR_ABOUT_PARENTS_2; - const pm_char STR_ABOUT_PARENTS_3[] PROGMEM = TR_ABOUT_PARENTS_3; - const pm_char STR_ABOUT_PARENTS_4[] PROGMEM = TR_ABOUT_PARENTS_4; -#endif - -const pm_uchar font_5x7[] PROGMEM = { -#include "font_05x07.lbm" -#if defined(TRANSLATIONS_DE) -#include "font_de_05x07.lbm" -#elif defined(TRANSLATIONS_CZ) -#include "font_cz_05x07.lbm" -#elif defined(TRANSLATIONS_ES) -#include "font_es_05x07.lbm" -#elif defined(TRANSLATIONS_FR) -#include "font_fr_05x07.lbm" -#elif defined(TRANSLATIONS_IT) -#include "font_it_05x07.lbm" -#elif defined(TRANSLATIONS_PL) -#include "font_pl_05x07.lbm" -#elif defined(TRANSLATIONS_PT) -#include "font_pt_05x07.lbm" -#elif defined(TRANSLATIONS_SE) -#include "font_se_05x07.lbm" -#endif -}; - -const pm_uchar font_10x14[] PROGMEM = { -#include "font_10x14_compressed.lbm" -#if defined(CPUARM) - #if defined(TRANSLATIONS_DE) - #include "font_de_10x14.lbm" - #elif defined(TRANSLATIONS_CZ) - #include "font_cz_10x14.lbm" - #elif defined(TRANSLATIONS_ES) - #include "font_es_10x14.lbm" - #elif defined(TRANSLATIONS_FR) - #include "font_fr_10x14.lbm" - #elif defined(TRANSLATIONS_IT) - #include "font_it_10x14.lbm" - #elif defined(TRANSLATIONS_PL) - #include "font_pl_10x14.lbm" - #elif defined(TRANSLATIONS_PT) - #include "font_pt_10x14.lbm" - #elif defined(TRANSLATIONS_SE) - #include "font_se_10x14.lbm" - #endif -#endif -}; - -#if defined(CPUARM) -const pm_uchar font_3x5[] PROGMEM = { -#include "font_03x05.lbm" -}; - -const pm_uchar font_4x6[] PROGMEM = { -#include "font_04x06.lbm" -#if defined(TRANSLATIONS_DE) -#include "font_de_04x06.lbm" -#elif defined(TRANSLATIONS_CZ) -#include "font_cz_04x06.lbm" -#elif defined(TRANSLATIONS_ES) -#include "font_es_04x06.lbm" -#elif defined(TRANSLATIONS_FR) -#include "font_fr_04x06.lbm" -#elif defined(TRANSLATIONS_IT) -#include "font_it_04x06.lbm" -#elif defined(TRANSLATIONS_PL) -#include "font_pl_04x06.lbm" -#elif defined(TRANSLATIONS_PT) -#include "font_pt_04x06.lbm" -#elif defined(TRANSLATIONS_SE) -#include "font_se_04x06.lbm" -#endif -}; - -const pm_uchar font_8x10[] PROGMEM = { -#include "font_08x10.lbm" -#if defined(TRANSLATIONS_DE) -#include "font_de_08x10.lbm" -#elif defined(TRANSLATIONS_CZ) -#include "font_cz_08x10.lbm" -#elif defined(TRANSLATIONS_ES) -#include "font_es_08x10.lbm" -#elif defined(TRANSLATIONS_FR) -#include "font_fr_08x10.lbm" -#elif defined(TRANSLATIONS_IT) -#include "font_it_08x10.lbm" -#elif defined(TRANSLATIONS_PL) -#include "font_pl_08x10.lbm" -#elif defined(TRANSLATIONS_PT) -#include "font_pt_08x10.lbm" -#elif defined(TRANSLATIONS_SE) -#include "font_se_08x10.lbm" -#endif -}; - -const pm_uchar font_4x6_extra[] PROGMEM = { -#include "font_04x06_extra.lbm" -}; - -const pm_uchar font_5x7_extra[] PROGMEM = { -#include "font_05x07_extra.lbm" -}; - -const pm_uchar font_10x14_extra[] PROGMEM = { -#include "font_10x14_extra.lbm" -}; - -#endif - From dda6069fef9b5cbafae52fd5b43df8f60565800b Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:27:36 -0500 Subject: [PATCH 12/43] Delete translations.h~ --- radio/src/translations.h~ | 754 -------------------------------------- 1 file changed, 754 deletions(-) delete mode 100644 radio/src/translations.h~ diff --git a/radio/src/translations.h~ b/radio/src/translations.h~ deleted file mode 100644 index 4a3e0600a..000000000 --- a/radio/src/translations.h~ +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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 translations_h -#define translations_h - -#if defined(TRANSLATIONS_FR) -#include "translations/fr.h" -#define LEN_SPECIAL_CHARS 3 -#elif defined(TRANSLATIONS_IT) -#include "translations/it.h" -#define LEN_SPECIAL_CHARS 1 -#elif defined(TRANSLATIONS_SE) -#include "translations/se.h" -#define LEN_SPECIAL_CHARS 6 -#elif defined(TRANSLATIONS_DE) -#include "translations/de.h" -#define LEN_SPECIAL_CHARS 6 -#elif defined(TRANSLATIONS_CZ) -#include "translations/cz.h" -#define LEN_SPECIAL_CHARS 0 -#elif defined(TRANSLATIONS_ES) -#include "translations/es.h" -#define LEN_SPECIAL_CHARS 0 -#elif defined(TRANSLATIONS_PL) -#include "translations/pl.h" -#define LEN_SPECIAL_CHARS 0 -#elif defined(TRANSLATIONS_PT) -#include "translations/pt.h" -#define LEN_SPECIAL_CHARS 0 -#else -#include "translations/en.h" -#define LEN_SPECIAL_CHARS 0 -#endif - -#define PSIZE(x) ( sizeof(x) - 1 ) -#define EOFS(x) ( OFS_##x + sizeof(TR_##x) ) - -#if LCD_W >= 212 - #define TR(x,y) y -#else - #define TR(x,y) x -#endif - -// The non-0-terminated-strings - -extern const pm_char STR_OPEN9X[]; - -#define OFS_OFFON 0 -#define OFS_MMMINV (OFS_OFFON + sizeof(TR_OFFON)) -#define OFS_NCHANNELS (OFS_MMMINV + sizeof(TR_MMMINV)) -#if defined(GRAPHICS) -#define OFS_VBEEPMODE (OFS_NCHANNELS + sizeof(TR_NCHANNELS)) -#else -#define OFS_VBEEPLEN (OFS_NCHANNELS + sizeof(TR_NCHANNELS)) -#define OFS_VBEEPMODE (OFS_VBEEPLEN + sizeof(TR_VBEEPLEN)) -#endif -#if defined(ROTARY_ENCODERS) -#define OFS_VRENAVIG (OFS_VBEEPMODE + sizeof(TR_VBEEPMODE)) -#define OFS_VRENCODERS (OFS_VRENAVIG + sizeof(TR_VRENAVIG)) -#define OFS_TRNMODE (OFS_VRENCODERS + sizeof(TR_VRENCODERS)) -#elif defined(ROTARY_ENCODER_NAVIGATION) -#define OFS_VRENCODERS (OFS_VBEEPMODE + sizeof(TR_VBEEPMODE)) -#define OFS_TRNMODE (OFS_VRENCODERS + sizeof(TR_VRENCODERS)) -#else -#define OFS_TRNMODE (OFS_VBEEPMODE + sizeof(TR_VBEEPMODE)) -#endif -#define OFS_TRNCHN (OFS_TRNMODE + sizeof(TR_TRNMODE)) -#define OFS_VTRIMINC (OFS_TRNCHN + sizeof(TR_TRNCHN)) -#define OFS_RETA123 (OFS_VTRIMINC + sizeof(TR_VTRIMINC)) -#define OFS_VPROTOS (OFS_RETA123 + sizeof(TR_RETA123)) -#define OFS_POSNEG (OFS_VPROTOS + sizeof(TR_VPROTOS)) -#define OFS_VBLMODE (OFS_POSNEG + sizeof(TR_POSNEG)) -#define OFS_VCURVEFUNC (OFS_VBLMODE + sizeof(TR_VBLMODE)) -#define OFS_VMLTPX (OFS_VCURVEFUNC + sizeof(TR_VCURVEFUNC)) -#define OFS_VMLTPX2 (OFS_VMLTPX + sizeof(TR_VMLTPX)) -#define OFS_VMIXTRIMS (OFS_VMLTPX2 + sizeof(TR_VMLTPX2)) -#define OFS_VCSWFUNC (OFS_VMIXTRIMS + sizeof(TR_VMIXTRIMS)) -#define OFS_VFSWFUNC (OFS_VCSWFUNC + sizeof(TR_VCSWFUNC)) -#define OFS_VFSWRESET (OFS_VFSWFUNC + sizeof(TR_VFSWFUNC)) -#define OFS_FUNCSOUNDS (OFS_VFSWRESET + sizeof(TR_VFSWRESET)) -#define OFS_VTELEMCHNS (OFS_FUNCSOUNDS + sizeof(TR_FUNCSOUNDS)) -#if defined(FRSKY) || defined(CPUARM) - #if defined(CPUARM) - #define OFS_VTELEMUNIT_IMP (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS)) - #define OFS_VTELEMUNIT_NORM (OFS_VTELEMUNIT_IMP + sizeof(TR_VTELEMUNIT_IMP)) - #define OFS_VALARM (OFS_VTELEMUNIT_NORM + sizeof(TR_VTELEMUNIT_NORM)) - #else - #define OFS_VTELEMUNIT (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS)) - #define OFS_VALARM (OFS_VTELEMUNIT + sizeof(TR_VTELEMUNIT)) - #endif - #define OFS_VALARMFN (OFS_VALARM + sizeof(TR_VALARM)) - #define OFS_VTELPROTO (OFS_VALARMFN + sizeof(TR_VALARMFN)) - #define OFS_GPSFORMAT (OFS_VTELPROTO + sizeof(TR_VTELPROTO)) - #define OFS_VOLTSRC (OFS_GPSFORMAT + sizeof(TR_GPSFORMAT)) - #define OFS_VARIOSRC (OFS_VOLTSRC + sizeof(TR_VOLTSRC)) - #define OFS_VSCREEN (OFS_VARIOSRC + sizeof(TR_VARIOSRC)) - #define OFS_VTEMPLATES (OFS_VSCREEN + sizeof(TR_VSCREEN)) -#else - #define OFS_VTEMPLATES (OFS_VTELEMCHNS + sizeof(TR_VTELEMCHNS)) -#endif -#if defined(TEMPLATES) - #define OFS_VSWASHTYPE (OFS_VTEMPLATES + sizeof(TR_VTEMPLATES)) -#else - #define OFS_VSWASHTYPE (OFS_VTEMPLATES) -#endif -#if defined(HELI) - #define OFS_VKEYS (OFS_VSWASHTYPE + sizeof(TR_VSWASHTYPE)) -#else - #define OFS_VKEYS (OFS_VSWASHTYPE) -#endif -#define OFS_VSWITCHES (OFS_VKEYS + sizeof(TR_VKEYS)) -#define OFS_VSRCRAW (OFS_VSWITCHES + sizeof(TR_VSWITCHES)) -#define OFS_VTMRMODES (OFS_VSRCRAW + sizeof(TR_VSRCRAW)) -#define OFS_DATETIME (OFS_VTMRMODES + sizeof(TR_VTMRMODES)) -#if defined(CPUM2560) || defined(CPUARM) - #define OFS_VLCD (OFS_DATETIME + sizeof(TR_DATETIME)) -#else - #define OFS_VLCD (OFS_DATETIME) -#endif -#if defined(CPUARM) - #define OFS_VUNITSSYSTEM (OFS_VLCD + sizeof(TR_VLCD)) - #define OFS_VBEEPCOUNTDOWN (OFS_VUNITSSYSTEM + sizeof(TR_VUNITSSYSTEM)) - #define OFS_COUNTRYCODES (OFS_VBEEPCOUNTDOWN + sizeof(TR_VBEEPCOUNTDOWN)) -#else - #define OFS_COUNTRYCODES (OFS_VLCD) -#endif -#if defined(PXX) - #define OFS_VFAILSAFE (OFS_COUNTRYCODES + sizeof(TR_COUNTRYCODES)) -#else - #define OFS_VFAILSAFE (OFS_COUNTRYCODES) -#endif -#if defined(PXX) - #define OFS_VTRAINERMODES (OFS_VFAILSAFE + sizeof(TR_VFAILSAFE)) -#else - #define OFS_VTRAINERMODES (OFS_VFAILSAFE) -#endif -#if defined(PCBTARANIS) - #define OFS_MAVLINK_BAUDS (OFS_VTRAINERMODES + sizeof(TR_VTRAINERMODES)) -#else - #define OFS_MAVLINK_BAUDS (OFS_VTRAINERMODES) -#endif -#if defined(MAVLINK) - #define OFS_MAVLINK_AC_MODES (OFS_MAVLINK_BAUDS + sizeof(TR_MAVLINK_BAUDS)) - #define OFS_MAVLINK_AP_MODES (OFS_MAVLINK_AC_MODES + sizeof(TR_MAVLINK_AC_MODES)) - #define OFS_SPARE (OFS_MAVLINK_AP_MODES + sizeof(TR_MAVLINK_AP_MODES)) -#else - #define OFS_SPARE (OFS_MAVLINK_BAUDS) -#endif - -#define STR_OFFON (STR_OPEN9X + OFS_OFFON) -#define STR_MMMINV (STR_OPEN9X + OFS_MMMINV) -#define STR_NCHANNELS (STR_OPEN9X + OFS_NCHANNELS) -#if !defined(GRAPHICS) -#define STR_VBEEPLEN (STR_OPEN9X + OFS_VBEEPLEN) -#endif -#define STR_VBEEPMODE (STR_OPEN9X + OFS_VBEEPMODE) -#define STR_TRNMODE (STR_OPEN9X + OFS_TRNMODE) -#define STR_TRNCHN (STR_OPEN9X + OFS_TRNCHN) -#define STR_VTRIMINC (STR_OPEN9X + OFS_VTRIMINC) -#define STR_RETA123 (STR_OPEN9X + OFS_RETA123) -#define STR_VPROTOS (STR_OPEN9X + OFS_VPROTOS) -#define STR_POSNEG (STR_OPEN9X + OFS_POSNEG) -#define STR_VBLMODE (STR_OPEN9X + OFS_VBLMODE) -#define STR_VCURVEFUNC (STR_OPEN9X + OFS_VCURVEFUNC) -#define STR_VSIDE STR_VCURVEFUNC -#define LEN_VSIDE LEN_VCURVEFUNC -#define STR_VMLTPX (STR_OPEN9X + OFS_VMLTPX) -#define STR_VMLTPX2 (STR_OPEN9X + OFS_VMLTPX2) -#define STR_VMIXTRIMS (STR_OPEN9X + OFS_VMIXTRIMS) -#define STR_VCSWFUNC (STR_OPEN9X + OFS_VCSWFUNC) -#define STR_VFSWFUNC (STR_OPEN9X + OFS_VFSWFUNC) -#define STR_VFSWRESET (STR_OPEN9X + OFS_VFSWRESET) -#define STR_FUNCSOUNDS (STR_OPEN9X + OFS_FUNCSOUNDS) -#define STR_VTELEMCHNS (STR_OPEN9X + OFS_VTELEMCHNS) - -#if defined(FRSKY) || defined(CPUARM) - #if defined(CPUARM) - #define STR_VTELEMUNIT (STR_OPEN9X + (g_eeGeneral.imperial ? OFS_VTELEMUNIT_IMP : OFS_VTELEMUNIT_NORM)) - #else - #define STR_VTELEMUNIT (STR_OPEN9X + OFS_VTELEMUNIT) - #endif -#define STR_VALARM (STR_OPEN9X + OFS_VALARM) -#define STR_VALARMFN (STR_OPEN9X + OFS_VALARMFN) -#define STR_VTELPROTO (STR_OPEN9X + OFS_VTELPROTO) -#define STR_GPSFORMAT (STR_OPEN9X + OFS_GPSFORMAT) -#define STR_VOLTSRC (STR_OPEN9X + OFS_VOLTSRC) -#define STR_VARIOSRC (STR_OPEN9X + OFS_VARIOSRC) -#define STR_VSCREEN (STR_OPEN9X + OFS_VSCREEN) -#define STR_TELEMCHNS (STR_OPEN9X + OFS_TELEMCHNS) -#endif - -#ifdef TEMPLATES -#define STR_VTEMPLATES (STR_OPEN9X + OFS_VTEMPLATES) -#endif - -#ifdef HELI -#define STR_VSWASHTYPE (STR_OPEN9X + OFS_VSWASHTYPE) -#endif - -#define STR_VKEYS (STR_OPEN9X + OFS_VKEYS) -#define STR_VSWITCHES (STR_OPEN9X + OFS_VSWITCHES) -#define STR_VSRCRAW (STR_OPEN9X + OFS_VSRCRAW) -#define STR_VTMRMODES (STR_OPEN9X + OFS_VTMRMODES) - -#if defined(ROTARY_ENCODERS) - #define STR_VRENAVIG (STR_OPEN9X + OFS_VRENAVIG) -#endif - -#if defined(ROTARY_ENCODER_NAVIGATION) - #define STR_VRENCODERS (STR_OPEN9X + OFS_VRENCODERS) -#endif - -#if defined(CPUM2560) || defined(CPUARM) -#define STR_DATETIME (STR_OPEN9X + OFS_DATETIME) -#endif - -#if defined(CPUARM) - #define STR_VLCD (STR_OPEN9X + OFS_VLCD) - #define STR_VUNITSSYSTEM (STR_OPEN9X + OFS_VUNITSSYSTEM) - #define STR_VBEEPCOUNTDOWN (STR_OPEN9X + OFS_VBEEPCOUNTDOWN) -#endif - -#if defined(PXX) - #define STR_COUNTRYCODES (STR_OPEN9X + OFS_COUNTRYCODES) - #define STR_VFAILSAFE (STR_OPEN9X + OFS_VFAILSAFE) -#endif - -#if defined(PCBTARANIS) - #define STR_VTRAINERMODES (STR_OPEN9X + OFS_VTRAINERMODES) -#endif - -#if defined(MAVLINK) - #define STR_MAVLINK_BAUDS (STR_OPEN9X + OFS_MAVLINK_BAUDS) - #define STR_MAVLINK_AC_MODES (STR_OPEN9X + OFS_MAVLINK_AC_MODES) - #define STR_MAVLINK_AP_MODES (STR_OPEN9X + OFS_MAVLINK_AP_MODES) -#endif - -// The 0-terminated-strings -#define NO_INDENT(x) (x)+LEN_INDENT - -extern const pm_char STR_POPUPS[]; -#define STR_EXIT (STR_POPUPS + OFS_EXIT) -extern const pm_char STR_MENUWHENDONE[]; -extern const pm_char STR_FREE[]; -#define LEN_FREE PSIZE(TR_FREE) -extern const pm_char STR_DELETEMODEL[]; -extern const pm_char STR_COPYINGMODEL[]; -extern const pm_char STR_MOVINGMODEL[]; -extern const pm_char STR_LOADINGMODEL[]; -extern const pm_char STR_NAME[]; -extern const pm_char STR_BITMAP[]; -extern const pm_char STR_TIMER[]; -extern const pm_char STR_ELIMITS[]; -extern const pm_char STR_ETRIMS[]; -extern const pm_char STR_TRIMINC[]; -extern const pm_char STR_TTRACE[]; -extern const pm_char STR_TTRIM[]; -extern const pm_char STR_BEEPCTR[]; -extern const pm_char STR_PROTO[]; -extern const pm_char STR_PPMFRAME[]; -extern const pm_char STR_MS[]; -extern const pm_char STR_SWITCH[]; -extern const pm_char STR_TRIMS[]; -extern const pm_char STR_FADEIN[]; -extern const pm_char STR_FADEOUT[]; -extern const pm_char STR_DEFAULT[]; -extern const pm_char STR_CHECKTRIMS[]; -extern const pm_char STR_SWASHTYPE[]; -extern const pm_char STR_COLLECTIVE[]; -extern const pm_char STR_SWASHRING[]; -extern const pm_char STR_ELEDIRECTION[]; -extern const pm_char STR_AILDIRECTION[]; -extern const pm_char STR_COLDIRECTION[]; -extern const pm_char STR_MODE[]; -#if defined(AUDIO) && defined(BUZZER) -extern const pm_char STR_SPEAKER[]; -extern const pm_char STR_BUZZER[]; -#else -#define STR_SPEAKER STR_MODE -#define STR_BUZZER STR_MODE -#endif -extern const pm_char STR_NOFREEEXPO[]; -extern const pm_char STR_NOFREEMIXER[]; -extern const pm_char STR_INSERTMIX[]; -extern const pm_char STR_EDITMIX[]; -extern const pm_char STR_SOURCE[]; -extern const pm_char STR_WEIGHT[]; -extern const pm_char STR_EXPO[]; -extern const pm_char STR_SIDE[]; -extern const pm_char STR_DIFFERENTIAL[]; -extern const pm_char STR_OFFSET[]; -extern const pm_char STR_TRIM[]; -extern const pm_char STR_DREX[]; -extern const pm_char STR_CURVE[]; -extern const pm_char STR_FLMODE[]; -extern const pm_char STR_MIXWARNING[]; -extern const pm_char STR_OFF[]; -extern const pm_char STR_MULTPX[]; -extern const pm_char STR_DELAYDOWN[]; -extern const pm_char STR_DELAYUP[]; -extern const pm_char STR_SLOWDOWN[]; -extern const pm_char STR_SLOWUP[]; -extern const pm_char STR_MIXER[]; -extern const pm_char STR_CV[]; -extern const pm_char STR_GV[]; -extern const pm_char STR_ACHANNEL[]; -extern const pm_char STR_RANGE[]; -extern const pm_char STR_BAR[]; -extern const pm_char STR_ALARM[]; -extern const pm_char STR_USRDATA[]; -extern const pm_char STR_BLADES[]; -extern const pm_char STR_SCREEN[]; -extern const pm_char STR_SOUND_LABEL[]; -extern const pm_char STR_LENGTH[]; -extern const pm_char STR_SPKRPITCH[]; -extern const pm_char STR_HAPTIC_LABEL[]; -extern const pm_char STR_HAPTICSTRENGTH[]; -extern const pm_char STR_CONTRAST[]; -extern const pm_char STR_ALARMS_LABEL[]; -#if defined(BATTGRAPH) || defined(PCBTARANIS) -extern const pm_char STR_BATTERY_RANGE[]; -#endif -extern const pm_char STR_BATTERYWARNING[]; -extern const pm_char STR_INACTIVITYALARM[]; -extern const pm_char STR_MEMORYWARNING[]; -extern const pm_char STR_ALARMWARNING[]; -extern const pm_char STR_RENAVIG[]; -extern const pm_char STR_THROTTLEREVERSE[]; -extern const pm_char STR_MINUTEBEEP[]; -extern const pm_char STR_BEEPCOUNTDOWN[]; -extern const pm_char STR_PERSISTENT[]; -extern const pm_char STR_BACKLIGHT_LABEL[]; -extern const pm_char STR_BLDELAY[]; -#if defined(PWM_BACKLIGHT) -extern const pm_char STR_BLONBRIGHTNESS[]; -extern const pm_char STR_BLOFFBRIGHTNESS[]; -#endif -extern const pm_char STR_SPLASHSCREEN[]; -extern const pm_char STR_THROTTLEWARNING[]; -extern const pm_char STR_SWITCHWARNING[]; -extern const pm_char STR_TIMEZONE[]; -extern const pm_char STR_GPSCOORD[]; -extern const pm_char STR_VARIO[]; -extern const pm_char STR_RXCHANNELORD[]; -extern const pm_char STR_SLAVE[]; -extern const pm_char STR_MODESRC[]; -extern const pm_char STR_MULTIPLIER[]; -#define LEN_MULTIPLIER PSIZE(TR_MULTIPLIER) -extern const pm_char STR_CAL[]; -extern const pm_char STR_VTRIM[]; -extern const pm_char STR_BG[]; -extern const pm_char STR_MENUTOSTART[]; -extern const pm_char STR_SETMIDPOINT[]; -extern const pm_char STR_MOVESTICKSPOTS[]; -extern const pm_char STR_RXBATT[]; -extern const pm_char STR_TX[]; -#define STR_RX (STR_TX+OFS_RX) -extern const pm_char STR_ACCEL[]; -extern const pm_char STR_NODATA[]; -extern const pm_char STR_TM1TM2[]; -extern const pm_char STR_THRTHP[]; -extern const pm_char STR_TOT[]; -extern const pm_char STR_TMR1LATMAXUS[]; -extern const pm_char STR_TMR1LATMINUS[]; -extern const pm_char STR_TMR1JITTERUS[]; -extern const pm_char STR_TMIXMAXMS[]; -extern const pm_char STR_FREESTACKMINB[]; -extern const pm_char STR_MENUTORESET[]; -extern const pm_char STR_PPM[]; -extern const pm_char STR_CH[]; -extern const pm_char STR_MODEL[]; -extern const pm_char STR_FP[]; -#if defined(CPUARM) -extern const pm_char STR_MIX[]; -#endif -extern const pm_char STR_EEPROMLOWMEM[]; -extern const pm_char STR_ALERT[]; -extern const pm_char STR_PRESSANYKEYTOSKIP[]; -extern const pm_char STR_THROTTLENOTIDLE[]; -extern const pm_char STR_ALARMSDISABLED[]; -extern const pm_char STR_PRESSANYKEY[]; -#define LEN_PRESSANYKEY PSIZE(TR_PRESSANYKEY) -extern const pm_char STR_BADEEPROMDATA[]; -extern const pm_char STR_EEPROMFORMATTING[]; -extern const pm_char STR_EEPROMOVERFLOW[]; -extern const pm_char STR_TRIMS2OFFSETS[]; -extern const pm_char STR_MENURADIOSETUP[]; -extern const pm_char STR_MENUDATEANDTIME[]; -extern const pm_char STR_MENUTRAINER[]; -extern const pm_char STR_MENUVERSION[]; -extern const pm_char STR_MENUDIAG[]; -extern const pm_char STR_MENUANA[]; -extern const pm_char STR_MENUCALIBRATION[]; -extern const pm_char STR_MENUMODELSEL[]; -extern const pm_char STR_MENUSETUP[]; -extern const pm_char STR_MENUFLIGHTPHASE[]; -extern const pm_char STR_MENUFLIGHTPHASES[]; -extern const pm_char STR_MENUHELISETUP[]; -extern const pm_char STR_MENUINPUTS[]; -extern const pm_char STR_MENULIMITS[]; -extern const pm_char STR_MENUCURVES[]; -extern const pm_char STR_MENUCURVE[]; -extern const pm_char STR_MENUCUSTOMSWITCH[]; -extern const pm_char STR_MENUCUSTOMSWITCHES[]; -extern const pm_char STR_MENUCUSTOMFUNC[]; -extern const pm_char STR_MENUCUSTOMSCRIPTS[]; -extern const pm_char STR_MENUCUSTOMSCRIPT[]; -extern const pm_char STR_MENUTELEMETRY[]; -extern const pm_char STR_MENUTEMPLATES[]; -extern const pm_char STR_MENUSTAT[]; -extern const pm_char STR_MENUDEBUG[]; -extern const pm_char STR_MENUGLOBALVARS[]; -extern const pm_char STR_INVERT_THR[]; -extern const pm_char STR_AND_SWITCH[]; -extern const pm_char STR_CF[]; - -#if defined(DSM2) || defined(PXX) -extern const pm_char STR_RXNUM[]; -#endif - -#if defined(PXX) -extern const pm_char STR_SYNCMENU[]; -extern const pm_char STR_INTERNALRF[]; -extern const pm_char STR_EXTERNALRF[]; -extern const pm_char STR_FAILSAFE[]; -extern const pm_char STR_FAILSAFESET[]; -extern const pm_char STR_COUNTRYCODE[]; -#endif - -#if defined(FRSKY) -extern const pm_char STR_LIMIT[]; -#endif - -#ifdef FRSKY_HUB -extern const pm_char STR_MINRSSI[]; -extern const pm_char STR_LATITUDE[]; -extern const pm_char STR_LONGITUDE[]; -#endif - -#if defined(CPUARM) || defined(CPUM2560) -extern const pm_char STR_SHUTDOWN[]; -#endif - -extern const pm_char STR_BATT_CALIB[]; - -#if defined(CPUARM) || defined(FRSKY) -extern const pm_char STR_VOLTAGE[]; -extern const pm_char STR_CURRENT[]; -#endif - -#if defined(CPUARM) - extern const pm_char STR_CURRENT_CALIB[]; - #define LEN_CALIB_FIELDS (PSIZE(TR_BATT_CALIB) > PSIZE(TR_CURRENT_CALIB) ? PSIZE(TR_BATT_CALIB) : PSIZE(TR_CURRENT_CALIB)) - extern const pm_char STR_UNITSSYSTEM[]; - extern const pm_char STR_VOICELANG[]; - extern const pm_char STR_MODELIDUSED[]; - extern const pm_char STR_BEEP_VOLUME[]; - extern const pm_char STR_WAV_VOLUME[]; - extern const pm_char STR_VARIO_VOLUME[]; - extern const pm_char STR_BG_VOLUME[]; - extern const pm_char STR_PERSISTENT_MAH[]; -#else - #define LEN_CALIB_FIELDS PSIZE(TR_BATT_CALIB) -#endif - -#if defined(NAVIGATION_MENUS) - extern const pm_char STR_SELECT_MODEL[]; - extern const pm_char STR_CREATE_MODEL[]; - extern const pm_char STR_COPY_MODEL[]; - extern const pm_char STR_MOVE_MODEL[]; - extern const pm_char STR_DELETE_MODEL[]; - extern const pm_char STR_EDIT[]; - extern const pm_char STR_INSERT_BEFORE[]; - extern const pm_char STR_INSERT_AFTER[]; - extern const pm_char STR_COPY[]; - extern const pm_char STR_MOVE[]; - extern const pm_char STR_PASTE[]; - extern const pm_char STR_INSERT[]; - extern const pm_char STR_DELETE[]; - extern const pm_char STR_RESET_FLIGHT[]; - extern const pm_char STR_RESET_TIMER1[]; - extern const pm_char STR_RESET_TIMER2[]; - extern const pm_char STR_RESET_TELEMETRY[]; - extern const pm_char STR_STATISTICS[]; - extern const pm_char STR_ABOUT_US[]; -#endif - -extern const pm_char STR_RESET_BTN[]; - -#if defined(SDCARD) - extern const pm_char STR_BACKUP_MODEL[]; - extern const pm_char STR_RESTORE_MODEL[]; - extern const pm_char STR_SDCARD_ERROR[]; - extern const pm_char STR_NO_SDCARD[]; - extern const pm_char STR_INCOMPATIBLE[]; - extern const pm_char STR_LOGS_PATH[]; - extern const pm_char STR_LOGS_EXT[]; - extern const pm_char STR_MODELS_PATH[]; - extern const pm_char STR_MODELS_EXT[]; - #define STR_UPDATE_LIST STR_DELAYDOWN -#endif - -extern const pm_uchar font_5x7[]; -extern const pm_uchar font_10x14[]; - -#if defined(CPUARM) -extern const pm_uchar font_3x5[]; -extern const pm_uchar font_4x6[]; -extern const pm_uchar font_8x10[]; -extern const pm_uchar font_5x7_extra[]; -extern const pm_uchar font_10x14_extra[]; -extern const pm_uchar font_4x6_extra[]; -#endif - -extern const pm_char STR_WARNING[]; -extern const pm_char STR_EEPROMWARN[]; -extern const pm_char STR_THROTTLEWARN[]; -extern const pm_char STR_ALARMSWARN[]; -extern const pm_char STR_SWITCHWARN[]; - -extern const pm_char STR_SPEAKER_VOLUME[]; -extern const pm_char STR_LCD[]; -extern const pm_char STR_BRIGHTNESS[]; -extern const pm_char STR_CPU_TEMP[]; -extern const pm_char STR_CPU_CURRENT[]; -extern const pm_char STR_CPU_MAH[]; -extern const pm_char STR_COPROC[]; -extern const pm_char STR_COPROC_TEMP[]; -extern const pm_char STR_CAPAWARNING[]; -extern const pm_char STR_TEMPWARNING[]; -extern const pm_char STR_FUNC[]; -extern const pm_char STR_V1[]; -extern const pm_char STR_V2[]; -extern const pm_char STR_DURATION[]; -extern const pm_char STR_DELAY[]; -extern const pm_char STR_SD_CARD[]; -extern const pm_char STR_SDHC_CARD[]; -extern const pm_char STR_NO_SOUNDS_ON_SD[]; -extern const pm_char STR_NO_MODELS_ON_SD[]; -extern const pm_char STR_NO_BITMAPS_ON_SD[]; -extern const pm_char STR_NO_SCRIPTS_ON_SD[]; -extern const pm_char STR_PLAY_FILE[]; -extern const pm_char STR_ASSIGN_BITMAP[]; -extern const pm_char STR_EXECUTE_FILE[]; -extern const pm_char STR_DELETE_FILE[]; -extern const pm_char STR_COPY_FILE[]; -extern const pm_char STR_RENAME_FILE[]; -extern const pm_char STR_REMOVED[]; -extern const pm_char STR_SD_INFO[]; -extern const pm_char STR_SD_FORMAT[]; -extern const pm_char STR_NA[]; -extern const pm_char STR_HARDWARE[]; -extern const pm_char STR_FORMATTING[]; -extern const pm_char STR_TEMP_CALIB[]; -extern const pm_char STR_TIME[]; -extern const pm_char STR_BAUDRATE[]; -extern const pm_char STR_SD_INFO_TITLE[]; -extern const pm_char STR_SD_TYPE[]; -extern const pm_char STR_SD_SPEED[]; -extern const pm_char STR_SD_SECTORS[]; -extern const pm_char STR_SD_SIZE[]; -extern const pm_char STR_TYPE[]; -extern const pm_char STR_GLOBAL_VARS[]; -extern const pm_char STR_GLOBAL_VAR[]; -extern const pm_char STR_OWN[]; -extern const pm_char STR_ROTARY_ENCODER[]; -extern const pm_char STR_DATE[]; -extern const pm_char STR_CHANNELS_MONITOR[]; -extern const pm_char STR_PATH_TOO_LONG[]; -extern const pm_char STR_VIEW_TEXT[]; - -#if defined(VOICE) && defined(CPUARM) - struct LanguagePack { - const char *id; - const char *name; - void (*playNumber)(getvalue_t number, uint8_t unit, uint8_t att, uint8_t id); - void (*playDuration)(int16_t seconds, uint8_t id); - }; - extern LanguagePack * languagePacks[]; - extern LanguagePack * currentLanguagePack; - extern uint8_t currentLanguagePackIdx; - #define LANGUAGE_PACK_DECLARE(lng, name) LanguagePack lng ## LanguagePack = { #lng, name, lng ## _ ## playNumber, lng ## _ ## playDuration } - #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) LANGUAGE_PACK_DECLARE(lng, name); LanguagePack * currentLanguagePack = & lng ## LanguagePack; uint8_t currentLanguagePackIdx - inline PLAY_FUNCTION(playNumber, getvalue_t number, uint8_t unit, uint8_t att) { currentLanguagePack->playNumber(number, unit, att, id); } - inline PLAY_FUNCTION(playDuration, int16_t seconds) { currentLanguagePack->playDuration(seconds, id); } -#elif defined(VOICE) - PLAY_FUNCTION(playNumber, getvalue_t number, uint8_t unit, uint8_t att); - PLAY_FUNCTION(playDuration, int16_t seconds); - #define LANGUAGE_PACK_DECLARE(lng, name) - #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) -#else - #define LANGUAGE_PACK_DECLARE(lng, name) - #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) -#endif - -#if LCD_W >= 212 - extern const pm_char STR_MODELNAME[]; - extern const pm_char STR_PHASENAME[]; - extern const pm_char STR_MIXNAME[]; - extern const pm_char STR_EXPONAME[]; -#else - #define STR_MODELNAME STR_NAME - #define STR_PHASENAME STR_NAME - #define STR_MIXNAME STR_NAME - #define STR_EXPONAME STR_NAME -#endif - -#if LCD_W >= 212 - extern const char * STR_PHASES_HEADERS[]; - extern const char * STR_LIMITS_HEADERS[]; - extern const char * STR_CSW_HEADERS[]; -#endif - -#if defined(PCBTARANIS) - extern const pm_char STR_BYTES[]; - extern const pm_char STR_MODULE_BIND[]; - extern const pm_char STR_SET[]; - extern const pm_char STR_TRAINER[]; - extern const pm_char STR_ANTENNAPROBLEM[]; - extern const pm_char STR_MODULE[]; - extern const pm_char STR_CHANNELRANGE[]; - extern const pm_char STR_LOWALARM[]; - extern const pm_char STR_CRITICALALARM[]; - extern const pm_char STR_ENABLE_POPUP[]; - extern const pm_char STR_DISABLE_POPUP[]; - extern const pm_char STR_CURVE_PRESET[]; - extern const pm_char STR_PRESET[]; - extern const pm_char STR_MIRROR[]; - extern const pm_char STR_CLEAR[]; - extern const pm_char STR_RESET[]; - extern const pm_char STR_COPY_TRIMS_TO_OFFSET[]; - extern const pm_char STR_TOP_BAR[]; - extern const pm_char STR_ALTITUDE[]; - extern const pm_char STR_SCALE[]; - extern const pm_char STR_VIEW_CHANNELS[]; - extern const pm_char STR_VIEW_NOTES[]; -#endif - -#if MENUS_LOCK == 1 - extern const pm_char STR_UNLOCKED[]; - extern const pm_char STR_MODS_FORBIDDEN[]; -#endif - -#if defined(PCBTARANIS) || defined(DSM2) - extern const pm_char STR_MODULE_RANGE[]; -#endif - -#if defined(MAVLINK) - extern const pm_char STR_MAVLINK_RC_RSSI_SCALE_LABEL[]; - extern const pm_char STR_MAVLINK_PC_RSSI_EN_LABEL[]; - extern const pm_char STR_MAVMENUSETUP_TITLE[]; - extern const pm_char STR_MAVLINK_BAUD_LABEL[]; - extern const pm_char STR_MAVLINK_INFOS[]; - extern const pm_char STR_MAVLINK_MODE[]; - extern const pm_char STR_MAVLINK_CUR_MODE[]; - extern const pm_char STR_MAVLINK_ARMED[]; - extern const pm_char STR_MAVLINK_BAT_MENU_TITLE[]; - extern const pm_char STR_MAVLINK_BATTERY_LABEL[]; - extern const pm_char STR_MAVLINK_RC_RSSI_LABEL[]; - extern const pm_char STR_MAVLINK_PC_RSSI_LABEL[]; - extern const pm_char STR_MAVLINK_NAV_MENU_TITLE[]; - extern const pm_char STR_MAVLINK_COURSE[]; - extern const pm_char STR_MAVLINK_HEADING[]; - extern const pm_char STR_MAVLINK_BEARING[]; - extern const pm_char STR_MAVLINK_ALTITUDE[]; - extern const pm_char STR_MAVLINK_GPS[]; - extern const pm_char STR_MAVLINK_NO_FIX[]; - extern const pm_char STR_MAVLINK_SAT[]; - extern const pm_char STR_MAVLINK_HDOP[]; - extern const pm_char STR_MAVLINK_LAT[]; - extern const pm_char STR_MAVLINK_LON[]; -#endif - -#if !defined(CPUM64) - extern const pm_char STR_ABOUTUS[]; - extern const pm_char STR_ABOUT_OPENTX_1[]; - extern const pm_char STR_ABOUT_OPENTX_2[]; - extern const pm_char STR_ABOUT_OPENTX_3[]; - extern const pm_char STR_ABOUT_OPENTX_4[]; - extern const pm_char STR_ABOUT_OPENTX_5[]; - - extern const pm_char STR_ABOUT_BERTRAND_1[]; - extern const pm_char STR_ABOUT_BERTRAND_2[]; - extern const pm_char STR_ABOUT_BERTRAND_3[]; - - extern const pm_char STR_ABOUT_MIKE_1[]; - extern const pm_char STR_ABOUT_MIKE_2[]; - extern const pm_char STR_ABOUT_MIKE_3[]; - extern const pm_char STR_ABOUT_MIKE_4[]; - - extern const pm_char STR_ABOUT_ROMOLO_1[]; - extern const pm_char STR_ABOUT_ROMOLO_2[]; - extern const pm_char STR_ABOUT_ROMOLO_3[]; - - extern const pm_char STR_ABOUT_ANDRE_1[]; - extern const pm_char STR_ABOUT_ANDRE_2[]; - extern const pm_char STR_ABOUT_ANDRE_3[]; - - extern const pm_char STR_ABOUT_ROB_1[]; - extern const pm_char STR_ABOUT_ROB_2[]; - - extern const pm_char STR_ABOUT_MARTIN_1[]; - extern const pm_char STR_ABOUT_MARTIN_2[]; - - extern const pm_char STR_ABOUT_HARDWARE_1[]; - extern const pm_char STR_ABOUT_HARDWARE_2[]; - extern const pm_char STR_ABOUT_HARDWARE_3[]; - - extern const pm_char STR_ABOUT_PARENTS_1[]; - extern const pm_char STR_ABOUT_PARENTS_2[]; - extern const pm_char STR_ABOUT_PARENTS_3[]; - extern const pm_char STR_ABOUT_PARENTS_4[]; -#endif - -#define CHR_SHORT TR_CHR_SHORT -#define CHR_LONG TR_CHR_LONG -#define CHR_TOGGLE TR_CHR_TOGGLE -#define CHR_HOUR TR_CHR_HOUR - -#endif From 8cdfe1040da261432975dfec5b98dc9c3af22a5d Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:27:45 -0500 Subject: [PATCH 13/43] Delete myeeprom.h~ --- radio/src/myeeprom.h~ | 1469 ----------------------------------------- 1 file changed, 1469 deletions(-) delete mode 100644 radio/src/myeeprom.h~ diff --git a/radio/src/myeeprom.h~ b/radio/src/myeeprom.h~ deleted file mode 100644 index bbf184de6..000000000 --- a/radio/src/myeeprom.h~ +++ /dev/null @@ -1,1469 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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 myeeprom_h -#define myeeprom_h - -#include - -#define WARN_THR_BIT 0x01 -#define WARN_BEP_BIT 0x80 -#define WARN_SW_BIT 0x02 -#define WARN_MEM_BIT 0x04 -#define WARN_BVAL_BIT 0x38 - -#define WARN_THR (!(g_eeGeneral.warnOpts & WARN_THR_BIT)) -#define WARN_BEP (!(g_eeGeneral.warnOpts & WARN_BEP_BIT)) -#define WARN_SW (!(g_eeGeneral.warnOpts & WARN_SW_BIT)) -#define WARN_MEM (!(g_eeGeneral.warnOpts & WARN_MEM_BIT)) -#define BEEP_VAL ( (g_eeGeneral.warnOpts & WARN_BVAL_BIT) >>3 ) - -#if defined(PCBTARANIS) - #define EEPROM_VER 216 -#elif defined(PCBSKY9X) - #define EEPROM_VER 216 -#elif defined(CPUM2560) || defined(CPUM2561) - #define EEPROM_VER 216 -#elif defined(CPUM128) - #define EEPROM_VER 216 -#else - #define EEPROM_VER 216 -#endif - -#ifndef PACK -#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) -#endif - -#if defined(PCBTARANIS) - #define MAX_MODELS 60 - #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 - #define MAX_PHASES 9 - #define MAX_MIXERS 64 - #define MAX_EXPOS 64 - #define NUM_CSW 32 // number of custom switches - #define NUM_CFN 32 // number of functions assigned to switches - #define MAX_SCRIPTS 3 - #define MAX_INPUTS 32 -#elif defined(CPUARM) - #define MAX_MODELS 60 - #define NUM_CHNOUT 32 // number of real output channels CH1-CH32 - #define MAX_PHASES 9 - #define MAX_MIXERS 64 - #define MAX_EXPOS 32 - #define NUM_CSW 32 // number of custom switches - #define NUM_CFN 32 // number of functions assigned to switches -#elif defined(CPUM2560) || defined(CPUM2561) - #define MAX_MODELS 30 - #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 - #define MAX_PHASES 6 - #define MAX_MIXERS 32 - #define MAX_EXPOS 16 - #define NUM_CSW 15 // number of custom switches - #define NUM_CFN 24 // number of functions assigned to switches -#elif defined(CPUM128) - #define MAX_MODELS 30 - #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 - #define MAX_PHASES 5 - #define MAX_MIXERS 32 - #define MAX_EXPOS 14 - #define NUM_CSW 15 // number of custom switches - #define NUM_CFN 24 // number of functions assigned to switches -#else - #define MAX_MODELS 16 - #define NUM_CHNOUT 16 // number of real output channels CH1-CH16 - #define MAX_PHASES 5 - #define MAX_MIXERS 32 - #define MAX_EXPOS 14 - #define NUM_CSW 12 // number of custom switches - #define NUM_CFN 16 // number of functions assigned to switches -#endif - -#define MAX_TIMERS 2 - -#if defined(PCBTARANIS) - enum CurveType { - CURVE_TYPE_STANDARD, - CURVE_TYPE_CUSTOM, - CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM - }; -PACK(typedef struct t_CurveInfo { - uint8_t type:3; - uint8_t smooth:1; - uint8_t spare:4; - int8_t points; -}) CurveInfo; - #define MAX_CURVES 32 - #define NUM_POINTS 512 - #define CURVDATA CurveInfo -#elif defined(CPUARM) - #define MAX_CURVES 16 - #define NUM_POINTS 512 - #define CURVDATA int16_t -#else - #define MAX_CURVES 8 - #define NUM_POINTS (112-MAX_CURVES) - #define CURVDATA int8_t -#endif - -#if defined(PCBTARANIS) || defined(PCBSKY9X) - #define NUM_MODULES 2 -#else - #define NUM_MODULES 1 -#endif - -typedef int16_t gvar_t; - -#if !defined(PCBSTD) - #define LEN_GVAR_NAME 6 - #define GVAR_MAX 1024 - #define GVAR_LIMIT 500 - PACK(typedef struct { - char name[LEN_GVAR_NAME]; - uint8_t popup:1; - uint8_t spare:7; - }) global_gvar_t; -#endif - -#define RESERVE_RANGE_FOR_GVARS 10 -// even we do not spend space in EEPROM for 10 GVARS, we reserve the space inside the range of values, like offset, weight, etc. - -#if defined(PCBSTD) && defined(GVARS) - #define MAX_GVARS 5 - #define MODEL_GVARS_DATA gvar_t gvars[MAX_GVARS]; - #define PHASE_GVARS_DATA - #define GVAR_VALUE(x, p) g_model.gvars[x] -#elif defined(PCBSTD) - #define MAX_GVARS 0 - #define MODEL_GVARS_DATA - #define PHASE_GVARS_DATA -#else - #if defined(CPUARM) - #define MAX_GVARS 9 - #else - #define MAX_GVARS 5 - #endif - #define MODEL_GVARS_DATA global_gvar_t gvars[MAX_GVARS]; - #define PHASE_GVARS_DATA gvar_t gvars[MAX_GVARS] - #define GVAR_VALUE(x, p) g_model.phaseData[p].gvars[x] -#endif - -PACK(typedef struct t_TrainerMix { - uint8_t srcChn:6; // 0-7 = ch1-8 - uint8_t mode:2; // off,add-mode,subst-mode - int8_t studWeight; -}) TrainerMix; - -PACK(typedef struct t_TrainerData { - int16_t calib[4]; - TrainerMix mix[4]; -}) TrainerData; - -PACK(typedef struct t_FrSkyRSSIAlarm { - int8_t level:2; - int8_t value:6; -}) FrSkyRSSIAlarm; - -#if defined(PCBTARANIS) -enum MainViews { - VIEW_TIMERS, - VIEW_INPUTS, - VIEW_SWITCHES, - VIEW_COUNT -}; -#else -enum MainViews { - VIEW_OUTPUTS_VALUES, - VIEW_OUTPUTS_BARS, - VIEW_INPUTS, - VIEW_TIMER2, - VIEW_COUNT -}; -#endif - -enum BeeperMode { - e_mode_quiet = -2, - e_mode_alarms, - e_mode_nokeys, - e_mode_all -}; - -#if defined(CPUARM) - #define EXTRA_GENERAL_FIELDS \ - uint8_t backlightBright; \ - int8_t currentCalib; \ - int8_t temperatureWarn; \ - uint8_t mAhWarn; \ - uint16_t mAhUsed; \ - uint32_t globalTimer; \ - int8_t temperatureCalib; \ - uint8_t btBaudrate; \ - uint8_t optrexDisplay; \ - uint8_t sticksGain; \ - uint8_t rotarySteps; \ - uint8_t countryCode; \ - uint8_t imperial; \ - char ttsLanguage[2]; \ - int8_t beepVolume; \ - int8_t wavVolume; \ - int8_t varioVolume; \ - int8_t backgroundVolume; -#elif defined(PXX) - #define EXTRA_GENERAL_FIELDS uint8_t countryCode; -#else - #define EXTRA_GENERAL_FIELDS -#endif - -PACK(typedef struct t_ModuleData { - int8_t rfProtocol; - uint8_t channelsStart; - int8_t channelsCount; // 0=8 channels - uint8_t failsafeMode; - int16_t failsafeChannels[NUM_CHNOUT]; - int8_t ppmDelay; - int8_t ppmFrameLength; - uint8_t ppmPulsePol; -}) ModuleData; - -#define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppmFrameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount) - -#define MAX_SCRIPT_INPUTS 10 -#define MAX_SCRIPT_OUTPUTS 6 -PACK(typedef struct t_ScriptData { - char file[10]; - char name[10]; - int8_t inputs[MAX_SCRIPT_INPUTS]; -}) ScriptData; - -#if defined(PCBTARANIS) - enum ModuleIndex { - INTERNAL_MODULE, - EXTERNAL_MODULE, - TRAINER_MODULE - }; - #define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; - #define MODELDATA_EXTRA uint8_t externalModule; uint8_t trainerMode; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][4]; - #define LIMITDATA_EXTRA char name[LEN_CHANNEL_NAME]; int8_t curve; - #define swstate_t uint16_t -#elif defined(PCBSKY9X) - #define MODELDATA_BITMAP - #define MODELDATA_EXTRA ModuleData moduleData[NUM_MODULES]; - #define LIMITDATA_EXTRA - #define swstate_t uint8_t -#else - #define MODELDATA_BITMAP - #define MODELDATA_EXTRA - #define LIMITDATA_EXTRA - #define swstate_t uint8_t -#endif - -enum BacklightMode { - e_backlight_mode_off = 0, - e_backlight_mode_keys = 1, - e_backlight_mode_sticks = 2, - e_backlight_mode_all = e_backlight_mode_keys+e_backlight_mode_sticks, - e_backlight_mode_on -}; - -#if defined(FSPLASH) || defined(XSPLASH) - #define SPLASH_MODE uint8_t splashMode:3 -#else - #define SPLASH_MODE uint8_t splashMode:1; uint8_t spare4:2 -#endif - -#define ALTERNATE_VIEW 0x10 -PACK(typedef struct t_EEGeneral { - uint8_t version; - uint16_t variant; - int16_t calibMid[NUM_STICKS+NUM_POTS]; - int16_t calibSpanNeg[NUM_STICKS+NUM_POTS]; - int16_t calibSpanPos[NUM_STICKS+NUM_POTS]; - uint16_t chkSum; - int8_t currModel; - uint8_t contrast; - uint8_t vBatWarn; - int8_t vBatCalib; - int8_t backlightMode; - TrainerData trainer; - uint8_t view; // index of view in main screen - int8_t buzzerMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all - uint8_t fai:1; - int8_t beepMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all - uint8_t alarmsFlash:1; - uint8_t disableMemoryWarning:1; - uint8_t disableAlarmWarning:1; - uint8_t stickMode:2; - int8_t timezone:5; - uint8_t spare1:1; - uint8_t inactivityTimer; - uint8_t mavbaud:3; - SPLASH_MODE; /* 3bits */ - int8_t hapticMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all - uint8_t blOffBright:4; - uint8_t blOnBright:4; - uint8_t lightAutoOff; - uint8_t templateSetup; // RETA order for receiver channels - int8_t PPM_Multiplier; - int8_t hapticLength; - uint8_t reNavigation; // not used on STOCK board - int8_t beepLength:3; - uint8_t hapticStrength:3; - uint8_t gpsFormat:1; - uint8_t unexpectedShutdown:1; - uint8_t speakerPitch; - int8_t speakerVolume; - int8_t vBatMin; - int8_t vBatMax; - - EXTRA_GENERAL_FIELDS - - swstate_t switchUnlockStates; - -}) EEGeneral; - -#if defined(PCBTARANIS) - #define LEN_MODEL_NAME 12 - #define LEN_BITMAP_NAME 10 - #define LEN_EXPOMIX_NAME 8 - #define LEN_FP_NAME 10 - #define LEN_CHANNEL_NAME 6 -#elif defined(PCBSKY9X) - #define LEN_MODEL_NAME 10 - #define LEN_EXPOMIX_NAME 6 - #define LEN_FP_NAME 6 -#else - #define LEN_MODEL_NAME 10 - #define LEN_FP_NAME 6 -#endif - -#if defined(PCBTARANIS) -enum CurveRefType { - CURVE_REF_DIFF, - CURVE_REF_EXPO, - CURVE_REF_FUNC, - CURVE_REF_CUSTOM -}; -PACK(typedef struct t_CurveRef { - uint8_t type; - int8_t value; -}) CurveRef; -#else - #define MODE_DIFFERENTIAL 0 - #define MODE_EXPO 0 - #define MODE_CURVE 1 -#endif - -#if defined(PCBTARANIS) -PACK(typedef struct t_ExpoData { - uint8_t srcRaw; - uint16_t scale; - uint8_t chn; - int8_t swtch; - uint16_t phases; - int8_t weight; - int8_t carryTrim; - char name[LEN_EXPOMIX_NAME]; - int8_t offset; - CurveRef curve; - uint8_t spare; -}) ExpoData; -#define MIN_EXPO_WEIGHT -100 -#define EXPO_VALID(ed) ((ed)->srcRaw) -#define EXPO_MODE_ENABLE(ed, v) (true) -#elif defined(CPUARM) -PACK(typedef struct t_ExpoData { - uint8_t mode; // 0=end, 1=pos, 2=neg, 3=both - uint8_t chn; - int8_t swtch; - uint16_t phases; - int8_t weight; - uint8_t curveMode; - char name[LEN_EXPOMIX_NAME]; - int8_t curveParam; -}) ExpoData; -#define MIN_EXPO_WEIGHT 0 -#define EXPO_VALID(ed) ((ed)->mode) -#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) -#elif defined(CPUM2560) || defined(CPUM2561) -PACK(typedef struct t_ExpoData { - uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both - uint8_t chn:2; - uint8_t curveMode:1; - uint8_t spare:3; - uint8_t phases; - int8_t swtch; - uint8_t weight; - int8_t curveParam; -}) ExpoData; -#define MIN_EXPO_WEIGHT 0 -#define EXPO_VALID(ed) ((ed)->mode) -#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) -#else -PACK(typedef struct t_ExpoData { - uint8_t mode:2; // 0=end, 1=pos, 2=neg, 3=both - int8_t swtch:6; - uint8_t chn:2; - uint8_t phases:5; - uint8_t curveMode:1; - uint8_t weight; // One spare bit here (used for GVARS) - int8_t curveParam; -}) ExpoData; -#define MIN_EXPO_WEIGHT 0 -#define EXPO_VALID(ed) ((ed)->mode) -#define EXPO_MODE_ENABLE(ed, v) ((v<0 && (ed->mode&1)) || (v>=0 && (ed->mode&2))) -#endif - -#if defined(CPUARM) - #define limit_min_max_t int16_t - #define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max+1000, 0, 1250) ? GET_GVAR(lim->max+1000, 0, 125, s_perout_flight_phase)*10 : lim->max+1000) - #define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min-1000, -1250, 0) ? GET_GVAR(lim->min-1000, -125, 0, s_perout_flight_phase)*10 : lim->min-1000) - #define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR(lim->offset, -100, 100, s_perout_flight_phase)*10 : lim->offset) - #define LIMIT_MAX_RESX(lim) calc1000toRESX(LIMIT_MAX(lim)) - #define LIMIT_MIN_RESX(lim) calc1000toRESX(LIMIT_MIN(lim)) - #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim)) -#else - #define limit_min_max_t int8_t - #define LIMIT_MAX(lim) (lim->max+100) - #define LIMIT_MIN(lim) (lim->min-100) - #define LIMIT_OFS(lim) (lim->offset) - #define LIMIT_MAX_RESX(lim) calc100toRESX(LIMIT_MAX(lim)) - #define LIMIT_MIN_RESX(lim) calc100toRESX(LIMIT_MIN(lim)) - #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim)) -#endif - -PACK(typedef struct t_LimitData { - limit_min_max_t min; - limit_min_max_t max; - int8_t ppmCenter; - int16_t offset:14; - uint16_t symetrical:1; - uint16_t revert:1; - - LIMITDATA_EXTRA - -}) LimitData; - -#define TRIM_OFF (1) -#define TRIM_ON (0) -#define TRIM_RUD (-1) -#define TRIM_ELE (-2) -#define TRIM_THR (-3) -#define TRIM_AIL (-4) - -#define MLTPX_ADD 0 -#define MLTPX_MUL 1 -#define MLTPX_REP 2 - -#if defined(CPUARM) -#define DELAY_STEP 10 -#define SLOW_STEP 10 -#define DELAY_MAX (25*DELAY_STEP) /* 25 seconds */ -#define SLOW_MAX (25*SLOW_STEP) /* 25 seconds */ -#if defined(PCBTARANIS) -PACK(typedef struct t_MixData { - uint8_t destCh; - uint16_t phases; - uint8_t mltpx; // multiplex method: 0 means +=, 1 means *=, 2 means := - int16_t weight; - int8_t swtch; - CurveRef curve; - uint8_t mixWarn:4; // mixer warning - uint8_t srcVariant:4; - uint8_t delayUp; - uint8_t delayDown; - uint8_t speedUp; - uint8_t speedDown; - uint8_t srcRaw; - int16_t offset; - char name[LEN_EXPOMIX_NAME]; - uint8_t spare; -}) MixData; -#else -PACK(typedef struct t_MixData { - uint8_t destCh; - uint16_t phases; - uint8_t curveMode:1; - uint8_t noExpo:1; - int8_t carryTrim:3; - uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := - uint8_t spare:1; - int16_t weight; - int8_t swtch; - int8_t curveParam; - uint8_t mixWarn:4; // mixer warning - uint8_t srcVariant:4; - uint8_t delayUp; - uint8_t delayDown; - uint8_t speedUp; - uint8_t speedDown; - uint8_t srcRaw; - int16_t offset; - char name[LEN_EXPOMIX_NAME]; -}) MixData; -#endif -#define MD_WEIGHT(md) (md->weight) -#define MD_WEIGHT_TO_UNION(md, var) var.word = md->weight -#define MD_UNION_TO_WEIGHT(var, md) md->weight = var.word -// #define MD_SETWEIGHT(md, val) md->weight = val - -PACK( union u_int8int16_t { - struct { - int8_t lo; - uint8_t hi; - } bytes_t; - int16_t word; -}); - -#define MD_OFFSET(md) (md->offset) -#define MD_OFFSET_TO_UNION(md, var) var.word = md->offset -#define MD_UNION_TO_OFFSET(var, md) md->offset = var.word -// #define MD_SETOFFSET(md, val) md->offset = val - -#else -#define DELAY_STEP 2 -#define SLOW_STEP 2 -#define DELAY_MAX 15 /* 7.5 seconds */ -#define SLOW_MAX 15 /* 7.5 seconds */ - -#if defined(CPUM2560) || defined(CPUM2561) -PACK(typedef struct t_MixData { - uint8_t destCh:4; // 0, 1..NUM_CHNOUT - uint8_t curveMode:1; // O=curve, 1=differential - uint8_t noExpo:1; - uint8_t weightMode:1; - uint8_t offsetMode:1; - uint8_t srcRaw; - int8_t weight; - int8_t swtch; - uint8_t phases; - uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := - int8_t carryTrim:3; - uint8_t mixWarn:2; // mixer warning - uint8_t spare:1; - uint8_t delayUp:4; - uint8_t delayDown:4; - uint8_t speedUp:4; - uint8_t speedDown:4; - int8_t curveParam; - int8_t offset; -}) MixData; -#else -PACK(typedef struct t_MixData { - uint8_t destCh:4; // 0, 1..NUM_CHNOUT - uint8_t curveMode:1; // O=curve, 1=differential - uint8_t noExpo:1; - uint8_t weightMode:1; - uint8_t offsetMode:1; - int8_t weight; - int8_t swtch:6; - uint8_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means := - uint8_t phases:5; - int8_t carryTrim:3; - uint8_t srcRaw:6; - uint8_t mixWarn:2; // mixer warning - uint8_t delayUp:4; - uint8_t delayDown:4; - uint8_t speedUp:4; - uint8_t speedDown:4; - int8_t curveParam; - int8_t offset; -}) MixData; -#endif -PACK( union u_gvarint_t { - struct { - int8_t lo; - uint8_t hi; - } bytes_t; - int16_t word; - - u_gvarint_t(int8_t l, uint8_t h) {bytes_t.lo=l; bytes_t.hi=h?255:0;} // hi bit is negativ sign - -private: - // prevent unwanted constructors, also saves program - u_gvarint_t() {} - u_gvarint_t(const u_gvarint_t&) {} -}); -#define MD_WEIGHT(md) (u_gvarint_t(md->weight,md->weightMode).word) - -PACK( union u_int8int16_t { - struct { - int8_t lo; - uint8_t hi; - } bytes_t; - int16_t word; -}); - -#define MD_WEIGHT_TO_UNION(md, var) var.bytes_t.lo=md->weight; var.bytes_t.hi=md->weightMode?255:0 -#define MD_UNION_TO_WEIGHT(var, md) md->weight=var.bytes_t.lo; if (var.word<0) md->weightMode=1; else md->weightMode=0 -// #define MD_SETWEIGHT(md, val) md->weight=val; if (val<0) md->weightMode=1; else md->weightMode=0 - -#define MD_OFFSET(md) (u_gvarint_t(md->offset,md->offsetMode).word) -#define MD_OFFSET_TO_UNION(md, var) var.bytes_t.lo=md->offset; var.bytes_t.hi=md->offsetMode?255:0 -#define MD_UNION_TO_OFFSET(var, md) md->offset=var.bytes_t.lo; if (var.word<0) md->offsetMode=1; else md->offsetMode=0 /* set negative sign */ -// #define MD_SETOFFSET(md, val) md->offset=val; if (val<0) md->offsetMode=1; else md->offsetMode=0 - -#endif - -#if defined(CPUARM) -#define MAX_CSW_DURATION 120 /*60s*/ -#define MAX_CSW_DELAY 120 /*60s*/ -#define MAX_CSW_ANDSW MAX_SWITCH -typedef int16_t csw_telemetry_value_t; -PACK(typedef struct t_CustomSwData { // Custom Switches data - int16_t v1; - int16_t v2; - uint8_t func; - uint8_t delay; - uint8_t duration; - int8_t andsw; -}) CustomSwData; -#else -typedef uint8_t csw_telemetry_value_t; -#define MAX_CSW_ANDSW 15 -PACK(typedef struct t_CustomSwData { // Custom Switches data - int8_t v1; //input - int8_t v2; //offset - uint8_t func:4; - uint8_t andsw:4; -}) CustomSwData; -#endif - -enum Functions { -#if defined(CPUARM) - FUNC_SAFETY_CH1, - FUNC_SAFETY_CH16=FUNC_SAFETY_CH1+15, -#else - FUNC_SAFETY_GROUP1, - FUNC_SAFETY_GROUP2, - FUNC_SAFETY_GROUP3, - FUNC_SAFETY_GROUP4, -#endif - FUNC_TRAINER, - FUNC_TRAINER_RUD, - FUNC_TRAINER_ELE, - FUNC_TRAINER_THR, - FUNC_TRAINER_AIL, - FUNC_INSTANT_TRIM, - FUNC_PLAY_SOUND, -#if !defined(PCBTARANIS) - FUNC_HAPTIC, -#endif - FUNC_RESET, - FUNC_VARIO, - FUNC_PLAY_TRACK, -#if !defined(CPUARM) - FUNC_PLAY_BOTH, -#endif - FUNC_PLAY_VALUE, -#if !defined(PCBSTD) - FUNC_LOGS, -#endif -#if defined(CPUARM) - FUNC_VOLUME, -#endif - FUNC_BACKLIGHT, -#if defined(CPUARM) - FUNC_BACKGND_MUSIC, - FUNC_BACKGND_MUSIC_PAUSE, -#endif -#if defined(GVARS) - FUNC_ADJUST_GV1, - FUNC_ADJUST_GVLAST = (FUNC_ADJUST_GV1 + (MAX_GVARS-1)), -#endif -#if defined(DEBUG) - FUNC_TEST, // should remain the last before MAX as not added in companion9x -#endif - FUNC_MAX -}; - -#if defined(GVARS) - #define IS_ADJUST_GV_FUNCTION(sd) (CFN_FUNC(sd) >= FUNC_ADJUST_GV1 && CFN_FUNC(sd) <= FUNC_ADJUST_GVLAST) -#else - #define IS_ADJUST_GV_FUNCTION(sd) (0) -#endif - -#if defined(VOICE) - #define HAS_REPEAT_PARAM(sd) (CFN_FUNC(sd) == FUNC_PLAY_SOUND || (CFN_FUNC(sd) >= FUNC_PLAY_TRACK && CFN_FUNC(sd) <= FUNC_PLAY_VALUE)) -#else - #define HAS_REPEAT_PARAM(sd) (CFN_FUNC(sd) == FUNC_PLAY_SOUND) -#endif - -enum ResetFunctionParam { - FUNC_RESET_TIMER1, - FUNC_RESET_TIMER2, - FUNC_RESET_ALL, -#if defined(FRSKY) - FUNC_RESET_TELEMETRY, -#endif -#if ROTARY_ENCODERS > 0 - FUNC_RESET_ROTENC1, -#endif -#if ROTARY_ENCODERS > 1 - FUNC_RESET_ROTENC2, -#endif - FUNC_RESET_PARAMS_COUNT, - FUNC_RESET_PARAM_LAST = FUNC_RESET_PARAMS_COUNT-1 -}; - -enum AdjustGvarFunctionParam { - FUNC_ADJUST_GVAR_CONSTANT, - FUNC_ADJUST_GVAR_SOURCE, - FUNC_ADJUST_GVAR_GVAR, - FUNC_ADJUST_GVAR_INC, -}; - -#if defined(CPUARM) -#if defined(PCBTARANIS) - #define LEN_CFN_NAME 10 -#else - #define LEN_CFN_NAME 6 -#endif -PACK(typedef struct t_CustomFnData { // Function Switches data - int8_t swtch; - uint8_t func; - PACK(union { - char name[LEN_CFN_NAME]; - struct { - int16_t val; - int16_t ext1; - int16_t ext2; - } composite; - }) param; - uint8_t mode:2; - uint8_t active:6; -}) CustomFnData; -#define CFN_EMPTY(p) (!(p)->swtch) -#define CFN_FUNC(p) ((p)->func) -#define CFN_ACTIVE(p) ((p)->active) -#define CFN_CH_NUMBER(p) (CFN_FUNC(p)) -#define CFN_PLAY_REPEAT(p) ((p)->active) -#define CFN_PLAY_REPEAT_MUL 1 -#define CFN_PLAY_REPEAT_NOSTART 0x3F -#define CFN_GVAR_MODE(p) ((p)->mode) -#define CFN_PARAM(p) ((p)->param.composite.val) -#define CFN_RESET(p) (p->active = 0, memset(&(p)->param, 0, sizeof((p)->param))) -#else -PACK(typedef struct t_CustomFnData { - int8_t swtch; // input - union { - struct { - uint8_t param:3; - uint8_t func:5; - } func_param; - - struct { - uint8_t active:1; - uint8_t param:2; - uint8_t func:5; - } func_param_enable; - - struct { - uint8_t active:1; - uint8_t func:7; - } func_safety; - } internal; - uint8_t param; -}) CustomFnData; -#define CFN_FUNC(p) ((p)->internal.func_param.func) -#define CFN_ACTIVE(p) ((p)->internal.func_param_enable.active) -#define CFN_CH_NUMBER(p) ((p)->internal.func_safety.func) -#define CFN_PLAY_REPEAT(p) ((p)->internal.func_param.param) -#define CFN_PLAY_REPEAT_MUL 10 -#define CFN_GVAR_MODE(p) ((p)->internal.func_param_enable.param) -#define CFN_PARAM(p) ((p)->param) -#define CFN_RESET(p) ((p)->internal.func_param_enable.active = 0, CFN_PARAM(p) = 0) -#endif - -enum TelemetryUnit { - UNIT_VOLTS, - UNIT_AMPS, - UNIT_METERS_PER_SECOND, - UNIT_RAW, - UNIT_KMH, - UNIT_METERS, - UNIT_DEGREES, - UNIT_PERCENT, - UNIT_MILLIAMPS, - UNIT_A1A2_MAX = UNIT_MILLIAMPS, - UNIT_MAH, - UNIT_WATTS, - UNIT_DBM, - UNIT_FEET, - UNIT_KTS, - UNIT_HOURS, - UNIT_MINUTES, - UNIT_SECONDS, - UNIT_RPMS, - UNIT_G, -}; - -#if defined(CPUARM) -PACK(typedef struct t_FrSkyChannelData { - uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. - int16_t offset:12; - uint16_t type:4; // channel unit (0=volts, ...) - uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. - uint8_t alarms_level:4; - uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) - uint8_t spare:2; - uint8_t multiplier; // 0=no multiplier, 1=*2 multiplier -}) FrSkyChannelData; -#else -PACK(typedef struct t_FrSkyChannelData { - uint8_t ratio; // 0.0 means not used, 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. - int16_t offset:12; - uint16_t type:4; // channel unit (0=volts, ...) - uint8_t alarms_value[2]; // 0.1V steps EG. 6.6 Volts = 66. 25.1V = 251, etc. - uint8_t alarms_level:4; - uint8_t alarms_greater:2; // 0=LT(<), 1=GT(>) - uint8_t multiplier:2; // 0=no multiplier, 1=*2 multiplier -}) FrSkyChannelData; -#endif - -enum TelemetrySource { - TELEM_NONE, - TELEM_TX_VOLTAGE, - TELEM_TM1, - TELEM_TM2, - TELEM_RSSI_TX, - TELEM_RSSI_RX, - TELEM_A1, - TELEM_A2, - TELEM_ALT, - TELEM_RPM, - TELEM_FUEL, - TELEM_T1, - TELEM_T2, - TELEM_SPEED, - TELEM_DIST, - TELEM_GPSALT, - TELEM_CELL, - TELEM_CELLS_SUM, - TELEM_VFAS, - TELEM_CURRENT, - TELEM_CONSUMPTION, - TELEM_POWER, - TELEM_ACCx, - TELEM_ACCy, - TELEM_ACCz, - TELEM_HDG, - TELEM_VSPD, - TELEM_MIN_A1, - TELEM_MIN_A2, - TELEM_MIN_ALT, - TELEM_MAX_ALT, - TELEM_MAX_RPM, - TELEM_MAX_T1, - TELEM_MAX_T2, - TELEM_MAX_SPEED, - TELEM_MAX_DIST, - // TODO TELEM_MIN_CELL, - // TODO TELEM_MIN_VFAS, - TELEM_MAX_CURRENT, - TELEM_MAX_POWER, - TELEM_ACC, - TELEM_GPS_TIME, - TELEM_CSW_MAX = TELEM_POWER, - TELEM_NOUSR_MAX = TELEM_A2, -#if defined(FRSKY) - TELEM_DISPLAY_MAX = TELEM_MAX_POWER, -#else - TELEM_DISPLAY_MAX = TELEM_TM2, // because used also in PlayValue -#endif - TELEM_STATUS_MAX = TELEM_GPS_TIME, -#if defined(FRSKY_SPORT) - TELEM_SWR = TELEM_RSSI_TX, - TELEM_FIRST_STREAMED_VALUE = TELEM_RSSI_RX, -#else - TELEM_FIRST_STREAMED_VALUE = TELEM_RSSI_TX, -#endif -}; - -enum VarioSource { -#if !defined(FRSKY_SPORT) - VARIO_SOURCE_ALTI, - VARIO_SOURCE_ALTI_PLUS, -#endif - VARIO_SOURCE_VARIO, - VARIO_SOURCE_A1, - VARIO_SOURCE_A2, - VARIO_SOURCE_LAST = VARIO_SOURCE_A2 -}; - -#if defined(FRSKY_HUB) - #define NUM_TELEMETRY TELEM_CSW_MAX -#elif defined(WS_HOW_HIGH) - #define NUM_TELEMETRY TELEM_ALT -#elif defined(FRSKY) - #define NUM_TELEMETRY TELEM_A2 -#elif defined(MAVLINK) - #define NUM_TELEMETRY 4 -#else - #define NUM_TELEMETRY TELEM_TM2 -#endif - -PACK(typedef struct t_FrSkyBarData { - uint8_t source; - uint8_t barMin; // minimum for bar display - uint8_t barMax; // ditto for max display (would usually = ratio) -}) FrSkyBarData; - -#if defined(PCBTARANIS) - #define NUM_LINE_ITEMS 3 -#else - #define NUM_LINE_ITEMS 2 -#endif -PACK(typedef struct t_FrSkyLineData { - uint8_t sources[NUM_LINE_ITEMS]; -}) FrSkyLineData; - -typedef union t_FrSkyScreenData { - FrSkyBarData bars[4]; - FrSkyLineData lines[4]; -} FrSkyScreenData; - -enum FrskyUsrProtocols { - USR_PROTO_NONE, - USR_PROTO_FRSKY, - USR_PROTO_WS_HOW_HIGH, - USR_PROTO_LAST = USR_PROTO_WS_HOW_HIGH, -}; - -enum FrskySource { - FRSKY_SOURCE_NONE, - FRSKY_SOURCE_A1, - FRSKY_SOURCE_A2, - FRSKY_SOURCE_FAS, - FRSKY_SOURCE_CELLS, -}; - -#if defined(CPUARM) -#define MAX_FRSKY_SCREENS 3 -PACK(typedef struct t_FrSkyData { - FrSkyChannelData channels[2]; - uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon - uint8_t voltsSource:7; - uint8_t altitudeDisplayed:1; - uint8_t blades; // How many blades for RPMs, 0=2 blades, 1=3 blades - uint8_t currentSource; - uint8_t screensType; - FrSkyScreenData screens[MAX_FRSKY_SCREENS]; - uint8_t varioSource; - int8_t varioCenterMax; - int8_t varioCenterMin; - int8_t varioMin; - int8_t varioMax; - FrSkyRSSIAlarm rssiAlarms[2]; - uint16_t mAhPersistent:1; - uint16_t storedMah:15; - int8_t fasOffset; -}) FrSkyData; -#else -#define MAX_FRSKY_SCREENS 2 -PACK(typedef struct t_FrSkyData { - FrSkyChannelData channels[2]; - uint8_t usrProto:2; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon - uint8_t blades:2; // How many blades for RPMs, 0=2 blades, 1=3 blades - uint8_t screensType:2; - uint8_t voltsSource:2; - int8_t varioMin:4; - int8_t varioMax:4; - FrSkyRSSIAlarm rssiAlarms[2]; - FrSkyScreenData screens[MAX_FRSKY_SCREENS]; - uint8_t varioSource:3; - int8_t varioCenterMin:5; - uint8_t currentSource:3; - int8_t varioCenterMax:5; - int8_t fasOffset; -}) FrSkyData; -#endif - -#if defined(MAVLINK) -PACK(typedef struct t_MavlinkData { - uint8_t rc_rssi_scale:4; - uint8_t pc_rssi_en:1; - uint8_t spare1:3; - uint8_t spare2[3]; -}) MavlinkData; -#endif - -PACK(typedef struct t_SwashRingData { // Swash Ring data - uint8_t invertELE:1; - uint8_t invertAIL:1; - uint8_t invertCOL:1; - uint8_t type:5; - uint8_t collectiveSource; - uint8_t value; -}) SwashRingData; - -#define TRIM_EXTENDED_MAX 500 -#define TRIM_EXTENDED_MIN (-TRIM_EXTENDED_MAX) -#define TRIM_MAX 125 -#define TRIM_MIN (-TRIM_MAX) - -#define ROTARY_ENCODER_MAX 1024 - -#if defined(PCBTARANIS) -#define NUM_ROTARY_ENCODERS 0 -#define NUM_ROTARY_ENCODERS_EXTRA 0 -#define ROTARY_ENCODER_ARRAY_EXTRA -#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[1]; -#elif defined(PCBSKY9X) -#define NUM_ROTARY_ENCODERS_EXTRA 0 -#define NUM_ROTARY_ENCODERS 1 -#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[1]; -#define ROTARY_ENCODER_ARRAY_EXTRA -#elif defined(PCBGRUVIN9X) && ROTARY_ENCODERS > 2 -#define NUM_ROTARY_ENCODERS_EXTRA 2 -#define NUM_ROTARY_ENCODERS (2+NUM_ROTARY_ENCODERS_EXTRA) -#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[2]; -#define ROTARY_ENCODER_ARRAY_EXTRA int16_t rotaryEncodersExtra[MAX_PHASES][NUM_ROTARY_ENCODERS_EXTRA]; -#elif defined(CPUM2560) && ROTARY_ENCODERS <= 2 -#define NUM_ROTARY_ENCODERS_EXTRA 0 -#define NUM_ROTARY_ENCODERS 2 -#define ROTARY_ENCODER_ARRAY int16_t rotaryEncoders[2]; -#define ROTARY_ENCODER_ARRAY_EXTRA -#else -#define NUM_ROTARY_ENCODERS_EXTRA 0 -#define NUM_ROTARY_ENCODERS 0 -#define ROTARY_ENCODER_ARRAY -#define ROTARY_ENCODER_ARRAY_EXTRA -#endif - -#if defined(PCBSTD) - #define TRIMS_ARRAY int8_t trim[4]; int8_t trim_ext:8 - #define TRIMS_ARRAY_SIZE 5 -#else - #define TRIMS_ARRAY int16_t trim[4] - #define TRIMS_ARRAY_SIZE 8 -#endif - -#if defined(CPUARM) -PACK(typedef struct t_PhaseData { - TRIMS_ARRAY; - int8_t swtch; // swtch of phase[0] is not used - char name[LEN_FP_NAME]; - uint8_t fadeIn; - uint8_t fadeOut; - ROTARY_ENCODER_ARRAY; - PHASE_GVARS_DATA; -}) PhaseData; -#else -PACK(typedef struct t_PhaseData { - TRIMS_ARRAY; - int8_t swtch; // swtch of phase[0] is not used - char name[LEN_FP_NAME]; - uint8_t fadeIn:4; - uint8_t fadeOut:4; - ROTARY_ENCODER_ARRAY; - PHASE_GVARS_DATA; -}) PhaseData; -#endif - -enum SwitchSources { - SWSRC_NONE = 0, - - SWSRC_FIRST_SWITCH, - -#if defined(PCBTARANIS) - SWSRC_SA0 = SWSRC_FIRST_SWITCH, - SWSRC_SA1, - SWSRC_SA2, - SWSRC_SB0, - SWSRC_SB1, - SWSRC_SB2, - SWSRC_SC0, - SWSRC_SC1, - SWSRC_SC2, - SWSRC_SD0, - SWSRC_SD1, - SWSRC_SD2, - SWSRC_SE0, - SWSRC_SE1, - SWSRC_SE2, - SWSRC_SF0, - SWSRC_SF2, - SWSRC_SG0, - SWSRC_SG1, - SWSRC_SG2, - SWSRC_SH0, - SWSRC_SH2, -#else - SWSRC_ID0 = SWSRC_FIRST_SWITCH, - SWSRC_ID1, - SWSRC_ID2, -#if defined(EXTRA_3POS) - SWSRC_ID3, - SWSRC_ID4, - SWSRC_ID5, -#endif - SWSRC_THR, - SWSRC_RUD, - SWSRC_ELE, - SWSRC_AIL, - SWSRC_GEA, - SWSRC_TRN, -#endif - - SWSRC_FIRST_CSW, - SWSRC_SW1 = SWSRC_FIRST_CSW, - SWSRC_SW2, - SWSRC_SW3, - SWSRC_SW4, - SWSRC_SW5, - SWSRC_SW6, - SWSRC_SW7, - SWSRC_SW8, - SWSRC_SW9, - SWSRC_SWA, - SWSRC_SWB, - SWSRC_SWC, - SWSRC_LAST_CSW = SWSRC_SW1+NUM_CSW-1, - - SWSRC_ON, - - SWSRC_FIRST_MOMENT_SWITCH, - SWSRC_LAST_MOMENT_SWITCH = SWSRC_FIRST_MOMENT_SWITCH+SWSRC_ON-1, - -#if !defined(PCBSTD) - SWSRC_TRAINER_SHORT, - SWSRC_TRAINER_LONG, -#endif - -#if ROTARY_ENCODERS > 0 - SWSRC_FIRST_ROTENC_SWITCH, - SWSRC_LAST_ROTENC_SWITCH = SWSRC_FIRST_ROTENC_SWITCH+(2*ROTARY_ENCODERS)-1, -#endif - - SWSRC_COUNT, - SWSRC_FIRST = -SWSRC_LAST_MOMENT_SWITCH, - SWSRC_LAST = SWSRC_COUNT-1, - - SWSRC_OFF = -SWSRC_ON, - SWSRC_TRAINER = SWSRC_SW1-1, -}; - -enum MixSources { - MIXSRC_NONE, - -#if defined(PCBTARANIS) - MIXSRC_FIRST_INPUT, - MIXSRC_LAST_INPUT = MIXSRC_FIRST_INPUT+MAX_INPUTS-1, - - MIXSRC_FIRST_LUA, - MIXSRC_LAST_LUA = MIXSRC_FIRST_LUA+(MAX_SCRIPTS*MAX_SCRIPT_OUTPUTS)-1, -#endif - - MIXSRC_Rud, - MIXSRC_Ele, - MIXSRC_Thr, - MIXSRC_Ail, - - MIXSRC_FIRST_POT, -#if defined(PCBTARANIS) - MIXSRC_S1 = MIXSRC_FIRST_POT, - MIXSRC_S2, - MIXSRC_S3, - MIXSRC_S4, - MIXSRC_LAST_POT = MIXSRC_S4, -#else - MIXSRC_P1 = MIXSRC_FIRST_POT, - MIXSRC_P2, - #if defined(EXTRA_3POS) - MIXSRC_LAST_POT = MIXSRC_P2, - #else - MIXSRC_P3, - MIXSRC_LAST_POT = MIXSRC_P3, - #endif -#endif - -#if defined(PCBSKY9X) - MIXSRC_REa, - MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REa, -#elif defined(PCBGRUVIN9X) || defined(PCBMEGA2560) - MIXSRC_REa, - MIXSRC_REb, - #if ROTARY_ENCODERS > 2 - MIXSRC_REc, - MIXSRC_REd, - MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REd, - #else - MIXSRC_LAST_ROTARY_ENCODER = MIXSRC_REb, - #endif -#endif - - MIXSRC_MAX, - - MIXSRC_CYC1, - MIXSRC_CYC2, - MIXSRC_CYC3, - - MIXSRC_TrimRud, - MIXSRC_TrimEle, - MIXSRC_TrimThr, - MIXSRC_TrimAil, - - MIXSRC_FIRST_SWITCH, - -#if defined(PCBTARANIS) - MIXSRC_SA = MIXSRC_FIRST_SWITCH, - MIXSRC_SB, - MIXSRC_SC, - MIXSRC_SD, - MIXSRC_SE, - MIXSRC_SF, - MIXSRC_SG, - MIXSRC_SH, -#else - MIXSRC_3POS = MIXSRC_FIRST_SWITCH, - #if defined(EXTRA_3POS) - MIXSRC_3POS2, - #endif - MIXSRC_THR, - MIXSRC_RUD, - MIXSRC_ELE, - MIXSRC_AIL, - MIXSRC_GEA, - MIXSRC_TRN, -#endif - MIXSRC_FIRST_CSW, - MIXSRC_SW1 = MIXSRC_FIRST_CSW, - MIXSRC_SW9 = MIXSRC_SW1 + 8, - MIXSRC_SWA, - MIXSRC_SWB, - MIXSRC_SWC, - MIXSRC_LAST_CSW = MIXSRC_FIRST_CSW+NUM_CSW-1, - - MIXSRC_FIRST_PPM, - MIXSRC_LAST_PPM = MIXSRC_FIRST_PPM + 7, - - MIXSRC_FIRST_CH, - MIXSRC_CH1 = MIXSRC_FIRST_CH, - MIXSRC_CH2, - MIXSRC_CH3, - MIXSRC_CH4, - MIXSRC_CH5, - MIXSRC_CH6, - MIXSRC_CH7, - MIXSRC_CH8, - MIXSRC_CH9, - MIXSRC_CH10, - MIXSRC_CH11, - MIXSRC_CH12, - MIXSRC_CH13, - MIXSRC_CH14, - MIXSRC_CH15, - MIXSRC_CH16, - MIXSRC_LAST_CH = MIXSRC_CH1+NUM_CHNOUT-1, - - MIXSRC_GVAR1, - MIXSRC_LAST_GVAR = MIXSRC_GVAR1+MAX_GVARS-1, - - MIXSRC_FIRST_TELEM, - MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+NUM_TELEMETRY-1 -}; - -#define MIXSRC_FIRST (MIXSRC_NONE+1) -#define MIXSRC_LAST MIXSRC_LAST_CH -#define INPUTSRC_FIRST MIXSRC_Rud -#define INPUTSRC_LAST MIXSRC_LAST_TELEM - -#define MIN_POINTS 3 -#define MAX_POINTS 17 - -#define TMRMODE_NONE 0 -#define TMRMODE_ABS 1 -#define TMRMODE_THR 2 -#define TMRMODE_THR_REL 3 -#define TMRMODE_THR_TRG 4 - -#define COUNTDOWN_SILENT 0 -#define COUNTDOWN_BEEPS 1 -#define COUNTDOWN_VOICE 2 - -#if defined(CPUARM) || defined(CPUM2560) -PACK(typedef struct t_TimerData { - int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw - uint16_t start; - uint8_t countdownBeep:2; - uint8_t minuteBeep:1; - uint8_t persistent:1; - uint8_t spare:4; - uint16_t value; -}) TimerData; -#else -PACK(typedef struct t_TimerData { - int8_t mode; // timer trigger source -> off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw - uint16_t start:12; - uint16_t countdownBeep:1; - uint16_t minuteBeep:1; - uint16_t spare:2; -}) TimerData; -#endif - -enum Protocols { - PROTO_PPM, -#if !defined(CPUARM) - PROTO_PPM16, - PROTO_PPMSIM, -#endif -#if defined(PXX) || defined(DSM2) || defined(IRPROTOS) - PROTO_PXX, -#endif -#if defined(DSM2) || defined(IRPROTOS) - PROTO_DSM2_LP45, - PROTO_DSM2_DSM2, - PROTO_DSM2_DSMX, -#endif -#if defined(IRPROTOS) - // we will need 4 bytes for proto :( - PROTO_SILV, - PROTO_TRAC09, - PROTO_PICZ, - PROTO_SWIFT, -#endif - PROTO_MAX, - PROTO_NONE -}; - -enum RFProtocols { - RF_PROTO_OFF = -1, - RF_PROTO_X16, - RF_PROTO_D8, - RF_PROTO_LR12, - RF_PROTO_LAST = RF_PROTO_LR12 -}; - -enum DSM2Protocols { - DSM2_PROTO_LP45, - DSM2_PROTO_DSM2, - DSM2_PROTO_DSMX, -}; - -enum ModuleTypes { - MODULE_TYPE_NONE = 0, - MODULE_TYPE_PPM, - MODULE_TYPE_XJT, -#if defined(DSM2) - MODULE_TYPE_DSM2, -#endif - MODULE_TYPE_COUNT -}; - -enum FailsafeModes { - FAILSAFE_HOLD, - FAILSAFE_CUSTOM, - FAILSAFE_NOPULSES, - FAILSAFE_LAST = FAILSAFE_NOPULSES -}; - -#if defined(FRSKY) || !defined(PCBSTD) - #define TELEMETRY_DATA FrSkyData frsky; -#elif defined(MAVLINK) - #define TELEMETRY_DATA MavlinkData mavlink; -#else - #define TELEMETRY_DATA -#endif - -#if defined(CPUARM) || defined(PCBGRUVIN9X) || defined(PCBMEGA2560) - #define BeepANACenter uint16_t -#else - #define BeepANACenter uint8_t -#endif - -PACK(typedef struct t_ModelHeader { - char name[LEN_MODEL_NAME]; // must be first for eeLoadModelName - uint8_t modelId; - MODELDATA_BITMAP -}) ModelHeader; - -#if defined (CPUARM) - #define ARM_FIELD(x) x; - #define AVR_FIELD(x) -#else - #define ARM_FIELD(x) - #define AVR_FIELD(x) x; -#endif - -PACK(typedef struct t_ModelData { - ModelHeader header; - TimerData timers[MAX_TIMERS]; - uint8_t protocol:3; // not used on Taranis - uint8_t thrTrim:1; // Enable Throttle Trim - AVR_FIELD(int8_t ppmNCH:4) - ARM_FIELD(int8_t spare2:4) - uint8_t trimInc:3; // Trim Increments - uint8_t disableThrottleWarning:1; - ARM_FIELD(uint8_t displayText:1) - AVR_FIELD(uint8_t pulsePol:1) - uint8_t extendedLimits:1; - uint8_t extendedTrims:1; - uint8_t throttleReversed:1; - AVR_FIELD(int8_t ppmDelay) - BeepANACenter beepANACenter; // 1<<0->A1.. 1<<6->A7 - MixData mixData[MAX_MIXERS]; - LimitData limitData[NUM_CHNOUT]; - ExpoData expoData[MAX_EXPOS]; - - CURVDATA curves[MAX_CURVES]; - int8_t points[NUM_POINTS]; - - CustomSwData customSw[NUM_CSW]; - CustomFnData funcSw[NUM_CFN]; - SwashRingData swashR; - PhaseData phaseData[MAX_PHASES]; - - AVR_FIELD(int8_t ppmFrameLength) // 0=22.5ms (10ms-30ms) 0.5ms increments - uint8_t thrTraceSrc; - - swstate_t switchWarningStates; - - MODEL_GVARS_DATA - - TELEMETRY_DATA - - ROTARY_ENCODER_ARRAY_EXTRA - - MODELDATA_EXTRA - -}) ModelData; - -extern EEGeneral g_eeGeneral; -extern ModelData g_model; - -#define TOTAL_EEPROM_USAGE (sizeof(ModelData)*MAX_MODELS + sizeof(EEGeneral)) - -#endif -/*eof*/ From 57ea7937d8c5083c92999c9bde379c6d197aa92b Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:27:54 -0500 Subject: [PATCH 14/43] Delete simu.cpp~ --- radio/src/simu.cpp~ | 425 -------------------------------------------- 1 file changed, 425 deletions(-) delete mode 100644 radio/src/simu.cpp~ diff --git a/radio/src/simu.cpp~ b/radio/src/simu.cpp~ deleted file mode 100644 index 37aad7040..000000000 --- a/radio/src/simu.cpp~ +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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 "fx.h" -#include "FXExpression.h" -#include "FXPNGImage.h" -#include -#include "fxkeys.h" -#include "opentx.h" -#include -#include - -#define W2 LCD_W*2 -#define H2 LCD_H*2 - -int g_snapshot_idx = 0; - -class Open9xSim: public FXMainWindow -{ - FXDECLARE(Open9xSim) -public: - Open9xSim(){}; - Open9xSim(FXApp* a); - long onKeypress(FXObject*,FXSelector,void*); - long onTimeout(FXObject*,FXSelector,void*); - void makeSnapshot(const FXDrawable* drawable); - void doEvents(); - void refreshDiplay(); - -private: - FXImage *bmp; - FXImageFrame *bmf; - bool firstTime; - -public: - FXSlider *sliders[8]; - FXKnob *knobs[NUM_POTS]; -}; -// Message Map -FXDEFMAP(Open9xSim) Open9xSimMap[]={ - - //________Message_Type_________ID_____________________Message_Handler_______ - FXMAPFUNC(SEL_TIMEOUT, 2, Open9xSim::onTimeout), - FXMAPFUNC(SEL_KEYPRESS, 0, Open9xSim::onKeypress), - }; - -FXIMPLEMENT(Open9xSim,FXMainWindow,Open9xSimMap,ARRAYNUMBER(Open9xSimMap)) - -Open9xSim::Open9xSim(FXApp* a) -:FXMainWindow(a,"OpenTXSimu",NULL,NULL,DECOR_ALL,20,90,0,0) -{ - firstTime=true; - for(int i=0; i<(LCD_W*LCD_H/8); i++) displayBuf[i]=0;//rand(); - bmp = new FXPPMImage(getApp(),NULL,IMAGE_OWNED|IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP, W2, H2); - - FXHorizontalFrame *hf11=new FXHorizontalFrame(this,LAYOUT_CENTER_X); - FXHorizontalFrame *hf1=new FXHorizontalFrame(this,LAYOUT_FILL_X); - - //rh lv rv lh - for(int i=0; i<4; i++){ - switch(i) - { -#define L LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_FIX_X|LAYOUT_FIX_Y -#undef X0 -#define X0 10 -#define Y0 10 - case 0: - sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_HORIZONTAL,X0+0,Y0+100,100,20); - break; - case 1: - sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_VERTICAL,X0+100,Y0+0,20,100); - break; - case 2: - sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_VERTICAL,X0+120,Y0+0,20,100); - break; - case 3: - sliders[i]=new FXSlider(hf1,NULL,0,L|SLIDER_HORIZONTAL,X0+140,Y0+100,100,20); - break; - default:; - } - sliders[i]->setRange(-1024, 1024); - sliders[i]->setTickDelta(7); - sliders[i]->setValue(0); - } - - for(int i=0; isetRange(-1024, 1024); - knobs[i]->setValue(0); - } - - bmf = new FXImageFrame(this,bmp); - - getApp()->addTimeout(this,2,100); -} - -void Open9xSim::makeSnapshot(const FXDrawable* drawable) -{ - // Construct and create an FXImage object - FXPNGImage snapshot(getApp(), NULL, 0, drawable->getWidth(), drawable->getHeight()); - snapshot.create(); - - // Create a window device context and lock it onto the image - FXDCWindow dc(&snapshot); - - // Draw from the widget to this - dc.drawArea(drawable, 0, 0, drawable->getWidth(), drawable->getHeight(), 0, 0); - - // Release lock - dc.end(); - - // Grab pixels from server side back to client side - snapshot.restore(); - - // Save recovered pixels to a file - FXFileStream stream; - char buf[100]; - - do { - stream.close(); - sprintf(buf,"snapshot_%02d.png", ++g_snapshot_idx); - } while (stream.open(buf, FXStreamLoad)); - - if (stream.open(buf, FXStreamSave)) { - snapshot.savePixels(stream); - stream.close(); - printf("Snapshot written: %s\n", buf); - } - else { - printf("Cannot create snapshot %s\n", buf); - } -} -void Open9xSim::doEvents() -{ - getApp()->runOneEvent(false); -} - -long Open9xSim::onKeypress(FXObject*,FXSelector,void*v) -{ - FXEvent *evt=(FXEvent*)v; - // printf("keypress %x\n", evt->code); - if (evt->code=='s'){ - makeSnapshot(bmf); - } - return 0; -} - -long Open9xSim::onTimeout(FXObject*,FXSelector,void*) -{ - if(hasFocus()) { - static int keys1[]={ -#if defined(PCBTARANIS) - KEY_Page_Up, KEY_MENU, - KEY_Page_Down, KEY_PAGE, - KEY_Return, KEY_ENTER, - KEY_BackSpace, KEY_EXIT, - KEY_Up, KEY_PLUS, - KEY_Down, KEY_MINUS, -#else - KEY_Return, KEY_MENU, - KEY_BackSpace, KEY_EXIT, - KEY_Right, KEY_RIGHT, - KEY_Left, KEY_LEFT, - KEY_Up, KEY_UP, - KEY_Down, KEY_DOWN, -#endif -#if defined(ROTARY_ENCODER_NAVIGATION) - KEY_F, BTN_REa, -#endif - }; - -#if defined(PCBSKY9X) - Coproc_temp = 23; - Coproc_maxtemp = 28; -#endif - -#if defined(PCBSKY9X) - temperature = 31; - maxTemperature = 42; -#endif - - for (unsigned int i=0; igetKeyState(keys1[i])); - } - -#ifdef __APPLE__ - // gruvin: Can't use Function keys on the Mac -- too many other app conflicts. - // The ordering of these keys, Q/W,E/R,T/Y,U/I matches the on screen - // order of trim sliders - static FXuint trimKeys[] = { KEY_E, KEY_R, KEY_U, KEY_I, KEY_R, KEY_E, KEY_Y, KEY_T, KEY_Q, KEY_W }; -#else - static FXuint trimKeys[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8 }; -#endif - - for (unsigned i=0; igetKeyState(trimKeys[i])); - } - -#if defined(ROTARY_ENCODER_NAVIGATION) - static bool rotencAction = false; - if (getApp()->getKeyState(KEY_G)) { - if (!rotencAction) g_rotenc[0] += ROTARY_ENCODER_GRANULARITY; - rotencAction = true; - } - else if (getApp()->getKeyState(KEY_D)) { - if (!rotencAction) g_rotenc[0] -= ROTARY_ENCODER_GRANULARITY; - rotencAction = true; - } - else { - rotencAction = false; - } -#endif - -#define SWITCH_KEY(key, swtch, states) \ - static bool state##key = 0; \ - static int8_t state_##swtch = 2; \ - static int8_t inc_##swtch = 1; \ - if (getApp()->getKeyState(KEY_##key)) { \ - if (!state##key) { \ - state_##swtch = (state_##swtch+inc_##swtch); \ - if (state_##swtch == 1+states) inc_##swtch = -1; \ - else if (state_##swtch == 2) inc_##swtch = 1; \ - state##key = true; \ - } \ - } \ - else { \ - state##key = false; \ - } \ - simuSetSwitch(swtch, state_##swtch-states); - -#if defined(PCBTARANIS) - SWITCH_KEY(A, 0, 3); - SWITCH_KEY(B, 1, 3); - SWITCH_KEY(C, 2, 3); - SWITCH_KEY(D, 3, 3); - SWITCH_KEY(E, 4, 3); - SWITCH_KEY(F, 5, 2); - SWITCH_KEY(G, 6, 3); - SWITCH_KEY(H, 7, 2); -#else - SWITCH_KEY(1, 0, 2); - SWITCH_KEY(2, 1, 2); - SWITCH_KEY(3, 2, 2); - SWITCH_KEY(4, 3, 3); - SWITCH_KEY(5, 4, 2); - SWITCH_KEY(6, 5, 2); - SWITCH_KEY(7, 6, 2); -#endif - } - - per10ms(); - refreshDiplay(); - getApp()->addTimeout(this,2,5); - return 0; -} - -#if defined(PCBTARANIS) -#define BL_COLOR FXRGB(47,123,227) -#else -#define BL_COLOR FXRGB(150,200,152) -#endif - -void Open9xSim::refreshDiplay() -{ - if (lcd_refresh) { - lcd_refresh = false; - FXColor offColor = IS_BACKLIGHT_ON() ? BL_COLOR : FXRGB(200,200,200); -#if !defined(PCBTARANIS) - FXColor onColor = FXRGB(0,0,0); -#endif - for (int x=0;xsetPixel(2*x, 2*y, color); - bmp->setPixel(2*x+1, 2*y, color); - bmp->setPixel(2*x, 2*y+1, color); - bmp->setPixel(2*x+1, 2*y+1, color); - } -#else - if (lcd_buf[x+(y/8)*LCD_W] & (1<<(y%8))) { - bmp->setPixel(2*x, 2*y, onColor); - bmp->setPixel(2*x+1, 2*y, onColor); - bmp->setPixel(2*x, 2*y+1, onColor); - bmp->setPixel(2*x+1, 2*y+1, onColor); - } -#endif - else { - bmp->setPixel(2*x, 2*y, offColor); - bmp->setPixel(2*x+1, 2*y, offColor); - bmp->setPixel(2*x, 2*y+1, offColor); - bmp->setPixel(2*x+1, 2*y+1, offColor); - } - } - } - - bmp->render(); - bmf->setImage(bmp); - } -} - -Open9xSim *th9xSim; -void doFxEvents() -{ - //puts("doFxEvents"); - th9xSim->getApp()->runOneEvent(false); - th9xSim->refreshDiplay(); -} - -int main(int argc,char **argv) -{ - // Each FOX GUI program needs one, and only one, application object. - // The application objects coordinates some common stuff shared between - // all the widgets; for example, it dispatches events, keeps track of - // all the windows, and so on. - // We pass the "name" of the application, and its "vendor", the name - // and vendor are used to search the registry database (which stores - // persistent information e.g. fonts and colors). - FXApp application("Open9xSim", "thus"); - - // Here we initialize the application. We pass the command line arguments - // because FOX may sometimes need to filter out some of the arguments. - // This opens up the display as well, and reads the registry database - // so that persistent settings are now available. - application.init(argc,argv); - - // This creates the main window. We pass in the title to be displayed - // above the window, and possibly some icons for when its iconified. - // The decorations determine stuff like the borders, close buttons, - // drag handles, and so on the Window Manager is supposed to give this - // window. - //FXMainWindow *main=new FXMainWindow(&application,"Hello",NULL,NULL,DECOR_ALL); - th9xSim = new Open9xSim(&application); - application.create(); - - // Pretty self-explanatory:- this shows the window, and places it in the - // middle of the screen. -#ifndef __APPLE__ - th9xSim->show(PLACEMENT_SCREEN); -#else - th9xSim->show(); // Otherwise the main window gets centred across my two monitors, split down the middle. -#endif - -#if defined(FRSKY) && !defined(FRSKY_SPORT) - frskyStreaming = 1; -#endif - - printf("Model size = %d\n", (int)sizeof(g_model)); - - StartEepromThread(argc >= 2 ? argv[1] : "eeprom.bin"); - StartMainThread(); - -#if defined(PCBTARANIS) - simuSetSwitch(0, 0); - simuSetSwitch(1, 0); -#endif - - return application.run(); -} - -uint16_t anaIn(uint8_t chan) -{ - if (chansliders[chan]->getValue(); - else if (chanknobs[chan-NUM_STICKS]->getValue(); -#if defined(PCBTARANIS) - else if (chan == 8) - return 1000; -#elif defined(PCBSKY9X) - else if (chan == 7) - return 1500; - else if (chan == 8) - return 100; -#elif defined(PCBGRUVIN9X) - else if (chan == 7) - return 150; -#else - else if (chan == 7) - return 1500; -#endif - else - return 0; -} From ce6e9aefc99aa025bc6ac4f66a276a87ff949a7b Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:28:49 -0500 Subject: [PATCH 15/43] Delete en.h~ --- radio/src/translations/en.h~ | 765 ----------------------------------- 1 file changed, 765 deletions(-) delete mode 100644 radio/src/translations/en.h~ diff --git a/radio/src/translations/en.h~ b/radio/src/translations/en.h~ deleted file mode 100644 index 62876daf9..000000000 --- a/radio/src/translations/en.h~ +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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. - * - */ - -// NON ZERO TERMINATED STRINGS -#define LEN_OFFON "\003" -#define TR_OFFON "OFF""ON\0" - -#define LEN_MMMINV "\003" -#define TR_MMMINV "---""INV" - -#define LEN_NCHANNELS "\004" -#define TR_NCHANNELS "\0014CH\0016CH\0018CH10CH12CH14CH16CH" - -#define LEN_VBEEPMODE "\005" -#define TR_VBEEPMODE "Quiet""Alarm""NoKey""All " - -#define LEN_VBEEPLEN "\005" -#define TR_VBEEPLEN "0====""=0===""==0==""===0=""====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 ") - -#define LEN_TRNMODE "\003" -#define TR_TRNMODE "OFF"" +="" :=" - -#define LEN_TRNCHN "\003" -#define TR_TRNCHN "CH1CH2CH3CH4" - -#define LEN_DATETIME "\005" -#define TR_DATETIME "DATE:""TIME:" - -#define LEN_VLCD "\006" -#define TR_VLCD "NormalOptrex" - -#define LEN_COUNTRYCODES TR("\002", "\007") -#define TR_COUNTRYCODES TR("US""JP""EU", "America""Japan\0 ""Europe\0") - -#define LEN_VTRIMINC TR("\006","\013") -#define TR_VTRIMINC TR("Expo ""ExFine""Fine ""Medium""Coarse","Exponential""Extra Fine ""Fine ""Medium ""Coarse ") - -#define LEN_VBEEPCOUNTDOWN "\006" -#define TR_VBEEPCOUNTDOWN "SilentBeeps\0Voice\0" - -#define LEN_RETA123 "\001" - -#if defined(PCBGRUVIN9X) - #if ROTARY_ENCODERS > 2 - #define TR_RETA123 "RETA123abcd" - #else - #define TR_RETA123 "RETA123ab" - #endif -#elif defined(PCBTARANIS) - #define TR_RETA123 "RETA12LR" -#else - #define TR_RETA123 "RETA123" -#endif - -#define LEN_VPROTOS "\006" - -#if defined(PXX) - #define TR_PXX "PXX\0 " -#elif defined(DSM2) || defined(IRPROTOS) - #define TR_PXX "[PXX]\0" -#else - #define TR_PXX -#endif - -#if defined(DSM2) - #define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 " -#elif defined(IRPROTOS) - #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]" -#else - #define TR_DSM2 -#endif - -#if defined(IRPROTOS) - #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0" -#else - #define TR_IRPROTOS -#endif - -#if defined(CPUARM) - #define TR_XPPM -#else - #define TR_XPPM "PPM16\0""PPMsim" -#endif - -#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS - -#define LEN_POSNEG "\003" -#define TR_POSNEG "POS""NEG" - -#define LEN_VCURVEFUNC "\003" -#define TR_VCURVEFUNC "---""x>0""x<0""|x|""f>0""f<0""|f|" - -#define LEN_VMLTPX "\010" -#define TR_VMLTPX "Add\0 ""Multiply""Replace\0" - -#define LEN_VMLTPX2 "\002" -#define TR_VMLTPX2 "+=""*="":=" - -#define LEN_VMIXTRIMS "\003" -#define TR_VMIXTRIMS "OFF""ON\0""Rud""Ele""Thr""Ail" - -#define LEN_VCSWFUNC "\005" -#define TR_VCSWFUNC "---\0 ""a{x\0 ""a>x\0 ""ax""|a|b\0 ""a" - -#define LEN_VTELPROTO "\007" -#define TR_VTELPROTO "None\0 ""Hub\0 ""WSHHigh" - -#define LEN_VOLTSRC "\003" -#define TR_VOLTSRC "---""A1\0""A2\0""FAS""Cel" - -#define LEN_VARIOSRC "\005" -#if defined(FRSKY_SPORT) - #define TR_VARIOSRC "Vario""A1\0 ""A2\0" -#else - #define TR_VARIOSRC "Alti\0""Alti+""Vario""A1\0 ""A2\0" -#endif - -#define LEN_VSCREEN "\004" -#define TR_VSCREEN "Nums""Bars" - -#define LEN_GPSFORMAT "\004" -#define TR_GPSFORMAT "HMS NMEA" - -#define LEN2_VTEMPLATES 13 -#define LEN_VTEMPLATES "\015" -#define TR_VTEMPLATES "Clear Mixes\0\0""Simple 4-CH \0""Sticky-T-Cut\0""V-Tail \0""Elevon\\Delta\0""eCCPM \0""Heli Setup \0""Servo Test \0" - -#define LEN_VSWASHTYPE "\004" -#define TR_VSWASHTYPE "---\0""120\0""120X""140\0""90\0" - -#define LEN_VKEYS "\005" -#define TR_VKEYS TR(" Menu"" Exit"" Down"" Up""Right"" Left", " Menu"" Exit""Enter"" Page"" Plus""Minus") - -#define LEN_VRENCODERS "\003" -#define TR_VRENCODERS "REa""REb" - -#define LEN_VSWITCHES "\003" -#define LEN_VSRCRAW "\004" - -#if defined(PCBTARANIS) - #define TR_POTS_VSRCRAW "S1\0 ""S2\0 ""LS\0 ""RS\0 " - #define TR_SW_VSRCRAW "SA\0 ""SB\0 ""SC\0 ""SD\0 ""SE\0 ""SF\0 ""SG\0 ""SH\0 " -#elif defined(EXTRA_3POS) - #define TR_POTS_VSRCRAW "P1\0 ""P2\0 " - #define TR_SW_VSRCRAW "3P1\0""3P2\0" - #define TR_9X_3POS_SWITCHES "ID0""ID1""ID2""ID3""ID4""ID5" -#else - #define TR_POTS_VSRCRAW "P1\0 ""P2\0 ""P3\0 " - #define TR_SW_VSRCRAW "3POS" - #define TR_9X_3POS_SWITCHES "ID0""ID1""ID2" -#endif - -#if defined(CPUARM) - #define TR_CUSTOMSW "CS1""CS2""CS3""CS4""CS5""CS6""CS7""CS8""CS9""CSA""CSB""CSC""CSD""CSE""CSF""CSG""CSH""CSI""CSJ""CSK""CSL""CSM""CSN""CSO""CSP""CSQ""CSR""CSS""CST""CSU""CSV""CSW" -#elif defined(PCBGRUVIN9X) || defined(CPUM2561) || defined(CPUM128) - #define TR_CUSTOMSW "CS1""CS2""CS3""CS4""CS5""CS6""CS7""CS8""CS9""CSA""CSB""CSC""CSD""CSE""CSF" -#else - #define TR_CUSTOMSW "CS1""CS2""CS3""CS4""CS5""CS6""CS7""CS8""CS9""CSA""CSB""CSC" -#endif - -#if defined(PCBTARANIS) - #define TR_VSWITCHES "SA\300""SA-""SA\301""SB\300""SB-""SB\301""SC\300""SC-""SC\301""SD\300""SD-""SD\301""SE\300""SE-""SE\301""SF\300""SF\301""SG\300""SG-""SG\301""SH\300""SH\301" TR_CUSTOMSW "One" -#else - #define TR_VSWITCHES TR_9X_3POS_SWITCHES "THR""RUD""ELE""AIL""GEA""TRN" TR_CUSTOMSW "One" -#endif - -#if defined(PCBSKY9X) - #define TR_ROTARY_ENCODERS_VSRCRAW "REnc" -#elif defined(PCBGRUVIN9X) && ROTARY_ENCODERS > 2 - #define TR_ROTARY_ENCODERS_VSRCRAW "REa ""REb ""REc ""REd " -#elif defined(PCBGRUVIN9X) && ROTARY_ENCODERS <= 2 - #define TR_ROTARY_ENCODERS_VSRCRAW "REa ""REb " -#else - #define TR_ROTARY_ENCODERS_VSRCRAW -#endif - -#if defined(HELI) - #define TR_CYC_VSRCRAW "CYC1""CYC2""CYC3" -#else - #define TR_CYC_VSRCRAW "[C1]""[C2]""[C3]" -#endif - -#define TR_VSRCRAW "---\0""Rud\0""Ele\0""Thr\0""Ail\0" TR_POTS_VSRCRAW TR_ROTARY_ENCODERS_VSRCRAW "MAX\0" TR_CYC_VSRCRAW "TrmR" "TrmE" "TrmT" "TrmA" TR_SW_VSRCRAW - -#define LEN_VTMRMODES "\003" -#define TR_VTMRMODES "OFF""ABS""THs""TH%""THt" - -#define LEN_VTRAINERMODES "\006" -#define TR_VTRAINERMODES "Master""Slave\0" - -#define LEN_VFAILSAFE "\011" -#define TR_VFAILSAFE "Hold\0 ""Custom\0 ""No pulses" - -#if defined(MAVLINK) - #define LEN_MAVLINK_BAUDS "\006" - #define TR_MAVLINK_BAUDS "4800 ""9600 ""14400 ""19200 ""38400 ""57600 ""76800 ""115200" - #define LEN_MAVLINK_AC_MODES "\011" - #define TR_MAVLINK_AC_MODES "Stabilize""Acro ""Alt Hold ""Auto ""Guided ""Loiter ""RTL ""Circle ""Pos Hold ""Land ""OF Loiter""Toy A ""Toy M ""INVALID " - #define LEN_MAVLINK_AP_MODES "\015" - #define TR_MAVLINK_AP_MODES "Manual ""Circle ""Stabilize ""Training ""Fly by Wire A""Fly by Wire A""Auto ""RTL ""Loiter ""Guided ""Initialising ""INVALID " -#endif - -// ZERO TERMINATED STRINGS -#define INDENT "\001" -#define LEN_INDENT 1 -#define INDENT_WIDTH (FW/2) - -#if defined(PCBTARANIS) - #define TR_ENTER "[ENTER]" -#else - #define TR_ENTER "[MENU]" -#endif - -#define TR_POPUPS TR_ENTER "\010[EXIT]" -#define OFS_EXIT sizeof(TR_ENTER) - -#define TR_MENUWHENDONE CENTER "\006" TR_ENTER " WHEN DONE" -#define TR_FREE "free" -#define TR_DELETEMODEL "DELETE MODEL" -#define TR_COPYINGMODEL "Copying model..." -#define TR_MOVINGMODEL "Moving model..." -#define TR_LOADINGMODEL "Loading model..." -#define TR_NAME "Name" -#define TR_MODELNAME "Model Name" -#define TR_PHASENAME "Mode Name" -#define TR_MIXNAME "Mix Name" -#if defined(PCBTARANIS) - #define TR_EXPONAME "Line Name" -#else - #define TR_EXPONAME "Expo Name" -#endif -#define TR_BITMAP "Model Image" -#define TR_TIMER TR("Timer","Timer ") -#define TR_ELIMITS TR("E.Limits","Extended Limits") -#define TR_ETRIMS TR("E.Trims","Extended Trims") -#define TR_TRIMINC "Trim Step" -#define TR_TTRACE TR("T-Source","Throttle Source") -#define TR_TTRIM TR("T-Trim","Throttle Trim") -#define TR_BEEPCTR TR("Ctr Beep","Center Beep") -#define TR_PROTO TR(INDENT "Proto", INDENT "Protocol") -#define TR_PPMFRAME TR("PPM frame", INDENT "PPM frame") -#define TR_MS "ms" -#define TR_SWITCH "Switch" -#define TR_TRIMS "Trims" -#define TR_FADEIN "Fade In" -#define TR_FADEOUT "Fade Out" -#define TR_DEFAULT "(default)" -#define TR_CHECKTRIMS CENTER "\006Check\012Trims" -#define OFS_CHECKTRIMS CENTER_OFS+(9*FW) -#define TR_SWASHTYPE "Swash Type" -#define TR_COLLECTIVE TR("Collective","Collective source") -#define TR_SWASHRING "Swash Ring" -#define TR_ELEDIRECTION TR("ELE Direction","Long. cyc. direction") -#define TR_AILDIRECTION TR("AIL Direction","Lateral cyc. direction") -#define TR_COLDIRECTION TR("PIT Direction","Coll. pitch direction") -#define TR_MODE INDENT"Mode" -#define TR_NOFREEEXPO "No free expo!" -#define TR_NOFREEMIXER "No free mixer!" -#define TR_INSERTMIX "INSERT MIX " -#define TR_EDITMIX "EDIT MIX " -#define TR_SOURCE INDENT"Source" -#define TR_WEIGHT "Weight" -#define TR_EXPO TR("Expo","Exponential") -#define TR_SIDE "Side" -#define TR_DIFFERENTIAL "Differ" -#define TR_OFFSET INDENT"Offset" -#define TR_TRIM "Trim" -#define TR_DREX "DRex" -#define TR_CURVE "Curve" -#define TR_FLMODE TR("Mode","Modes") -#define TR_MIXWARNING "Warning" -#define TR_OFF "OFF" -#define TR_MULTPX "Multpx" -#define TR_DELAYDOWN "Delay Dn" -#define TR_DELAYUP "Delay Up" -#define TR_SLOWDOWN "Slow Dn" -#define TR_SLOWUP "Slow Up" -#define TR_MIXER "MIXER" -#define TR_CV "CV" -#define TR_GV "GV" -#define TR_ACHANNEL "A\004channel" -#define TR_RANGE INDENT"Range" -#define TR_BAR "Bar" -#define TR_ALARM INDENT"Alarm" -#define TR_USRDATA "UsrData" -#define TR_BLADES INDENT"Blades" -#define TR_SCREEN "Screen " -#define TR_SOUND_LABEL "Sound" -#define TR_LENGTH INDENT"Length" -#define TR_SPKRPITCH INDENT"Pitch" -#define TR_HAPTIC_LABEL "Haptic" -#define TR_HAPTICSTRENGTH INDENT"Strength" -#define TR_CONTRAST "Contrast" -#define TR_ALARMS_LABEL "Alarms" -#define TR_BATTERY_RANGE TR("Battery range","Battery meter range") -#define TR_BATTERYWARNING INDENT"Battery Low" -#define TR_INACTIVITYALARM INDENT"Inactivity" -#define TR_MEMORYWARNING INDENT"Memory Low" -#define TR_ALARMWARNING INDENT"Sound Off" -#define TR_RENAVIG "RotEnc Navig" -#define TR_THROTTLEREVERSE TR("T-Reverse", "Throttle reverse") -#define TR_MINUTEBEEP TR(INDENT"Minute",INDENT"Minute call") -#define TR_BEEPCOUNTDOWN INDENT"Countdown" -#define TR_PERSISTENT TR(INDENT"Persist.",INDENT"Persistent") -#define TR_BACKLIGHT_LABEL "Backlight" -#define TR_BLDELAY INDENT"Duration" -#define TR_BLONBRIGHTNESS INDENT"ON Brightness" -#define TR_BLOFFBRIGHTNESS INDENT"OFF Brightness" -#define TR_SPLASHSCREEN "Splash screen" -#define TR_THROTTLEWARNING TR("T-Warning","Throttle Warning") -#define TR_SWITCHWARNING TR("S-Warning","Switch Warning") -#define TR_TIMEZONE TR("Time Zone","GPS Time zone") -#define TR_RXCHANNELORD TR("Rx Channel Ord","Default channel order") -#define TR_SLAVE "Slave" -#define TR_MODESRC "Mode\006% Source" -#define TR_MULTIPLIER "Multiplier" -#define TR_CAL "Cal" -#define TR_VTRIM "Trim- +" -#define TR_BG "BG:" -#define TR_MENUTOSTART CENTER "\006" TR_ENTER " TO START" -#define TR_SETMIDPOINT TR(CENTER "\003SET STICKS MIDPOINT",CENTER "\003CENTER STICKS/SLIDERS") -#define TR_MOVESTICKSPOTS CENTER "\006MOVE STICKS/POTS" -#define TR_RXBATT "Rx Batt:" -#define TR_TXnRX "Tx:\0Rx:" -#define OFS_RX 4 -#define TR_ACCEL "Acc:" -#define TR_NODATA CENTER "NO DATA" -#define TR_TM1TM2 "TM1\032TM2" -#define TR_THRTHP "THR\032TH%" -#define TR_TOT "TOT" -#define TR_TMR1LATMAXUS "Tmr1Lat max\006us" -#define STR_US (STR_TMR1LATMAXUS+12) -#define TR_TMR1LATMINUS "Tmr1Lat min\006us" -#define TR_TMR1JITTERUS "Tmr1 Jitter\006us" - -#if defined(CPUARM) - #define TR_TMIXMAXMS "Tmix max" - #define TR_FREESTACKMINB "Free Stack" -#else - #define TR_TMIXMAXMS "Tmix max\014ms" - #define TR_FREESTACKMINB "Free Stack\010b" -#endif - -#define TR_MENUTORESET CENTER TR_ENTER " to reset" -#define TR_PPM "PPM" -#define TR_CH "CH" -#define TR_MODEL "MODEL" -#define TR_FP "FM" -#define TR_MIX "MIX" -#define TR_EEPROMLOWMEM "EEPROM low mem" -#define TR_ALERT "\016ALERT" -#define TR_PRESSANYKEYTOSKIP "Press any key to skip" -#define TR_THROTTLENOTIDLE "Throttle not idle" -#define TR_ALARMSDISABLED "Alarms Disabled" -#define TR_PRESSANYKEY TR("\010Press any Key", "Press any Key") -#define TR_BADEEPROMDATA "Bad EEprom Data" -#define TR_EEPROMFORMATTING "Formatting EEPROM" -#define TR_EEPROMOVERFLOW "EEPROM overflow" -#define TR_MENURADIOSETUP "RADIO SETUP" -#define TR_MENUDATEANDTIME "DATE AND TIME" -#define TR_MENUTRAINER "TRAINER" -#define TR_MENUVERSION "VERSION" -#define TR_MENUDIAG TR("SWITCHES","SWITCH TEST") -#define TR_MENUANA TR("ANAS","ANALOG INPUTS") -#define TR_MENUCALIBRATION "CALIBRATION" -#define TR_TRIMS2OFFSETS "\006Trims => Offsets" -#define TR_MENUMODELSEL TR("MODELSEL","MODEL SELECTION") -#define TR_MENUSETUP TR("SETUP","MODEL SETUP") -#define TR_MENUFLIGHTPHASE "FLIGHT MODE" -#define TR_MENUFLIGHTPHASES "FLIGHT MODES" -#define TR_MENUHELISETUP "HELI SETUP" - -#if defined(PCBTARANIS) - #define TR_MENUINPUTS "INPUTS" - #define TR_MENULIMITS "SERVOS" -#elif defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_LIMITS_SYMETRICAL) // The right menu titles for the gurus ... - #define TR_MENUINPUTS "STICKS" - #define TR_MENULIMITS "SERVOS" -#else - #define TR_MENUINPUTS "DR/EXPO" - #define TR_MENULIMITS "LIMITS" -#endif - -#define TR_MENUCURVES "CURVES" -#define TR_MENUCURVE "CURVE" -#define TR_MENUCUSTOMSWITCH "CUSTOM SWITCH" -#define TR_MENUCUSTOMSWITCHES "CUSTOM SWITCHES" -#define TR_MENUCUSTOMFUNC "CUSTOM FUNCTIONS" -#define TR_MENUTELEMETRY "TELEMETRY" -#define TR_MENUTEMPLATES "TEMPLATES" -#define TR_MENUSTAT "STATS" -#define TR_MENUDEBUG "DEBUG" -#define TR_RXNUM TR("RxNum", INDENT"Receiver No.") -#define TR_SYNCMENU "[Sync]" -#define TR_LIMIT INDENT"Limit" -#define TR_MINRSSI "Min Rssi" -#define TR_LATITUDE "Latitude" -#define TR_LONGITUDE "Longitude" -#define TR_GPSCOORD TR("GPS Coords", "GPS coordinate format") -#define TR_VARIO TR("Vario", "Variometer") -#define TR_SHUTDOWN "SHUTTING DOWN" -#define TR_BATT_CALIB "Battery Calib" -#define TR_CURRENT_CALIB "Current Calib" -#define TR_VOLTAGE INDENT"Voltage" -#define TR_CURRENT INDENT"Current" -#define TR_SELECT_MODEL "Select Model" -#define TR_CREATE_MODEL "Create Model" -#define TR_COPY_MODEL "Copy Model" -#define TR_MOVE_MODEL "Move Model" -#define TR_BACKUP_MODEL "Backup Model" -#define TR_DELETE_MODEL "Delete Model" -#define TR_RESTORE_MODEL "Restore Model" -#define TR_SDCARD_ERROR "SDCARD Error" -#define TR_NO_SDCARD "No SDCARD" -#define TR_INCOMPATIBLE "Incompatible" -#define TR_WARNING "WARNING" -#define TR_EEPROMWARN "EEPROM" -#define TR_THROTTLEWARN "THROTTLE" -#define TR_ALARMSWARN "ALARMS" -#define TR_SWITCHWARN "SWITCH" -#define TR_INVERT_THR TR("Invert Thr?","Invert Throttle?") -#define TR_SPEAKER_VOLUME INDENT "Volume" -#define TR_LCD "LCD" -#define TR_BRIGHTNESS INDENT "Brightness" -#define TR_CPU_TEMP "CPU Temp.\016>" -#define TR_CPU_CURRENT "Current\022>" -#define TR_CPU_MAH "Consumpt." -#define TR_COPROC "CoProc." -#define TR_COPROC_TEMP "MB Temp. \016>" -#define TR_CAPAWARNING INDENT "Capacity Low" -#define TR_TEMPWARNING INDENT "Overheat" -#define TR_FUNC "Func" -#define TR_V1 "V1" -#define TR_V2 "V2" -#define TR_DURATION "Duration" -#define TR_DELAY "Delay" -#define TR_SD_CARD "SD CARD" -#define TR_SDHC_CARD "SD-HC CARD" -#define TR_NO_SOUNDS_ON_SD "No Sounds on SD" -#define TR_NO_MODELS_ON_SD "No Models on SD" -#define TR_NO_BITMAPS_ON_SD "No Bitmaps on SD" -#define TR_PLAY_FILE "Play" -#define TR_DELETE_FILE "Delete" -#define TR_COPY_FILE "Copy" -#define TR_RENAME_FILE "Rename" -#define TR_ASSIGN_BITMAP "Assign Bitmap" -#define TR_REMOVED " removed" -#define TR_SD_INFO "Information" -#define TR_SD_FORMAT "Format" -#define TR_NA "N/A" -#define TR_HARDWARE "HARDWARE" -#define TR_FORMATTING "Formatting..." -#define TR_TEMP_CALIB "Temp. Calib" -#define TR_TIME "Time" -#define TR_BAUDRATE "BT Baudrate" -#define TR_SD_INFO_TITLE "SD INFO" -#define TR_SD_TYPE "Type:" -#define TR_SD_SPEED "Speed:" -#define TR_SD_SECTORS "Sectors:" -#define TR_SD_SIZE "Size:" -#define TR_TYPE "Type" -#define TR_GLOBAL_VARS "Global Variables" -#define TR_GLOBAL_VAR "Global Variable" -#define TR_MENUGLOBALVARS "GLOBAL VARIABLES" -#define TR_OWN "Own" -#define TR_DATE "Date" -#define TR_ROTARY_ENCODER "R.Encs" -#define TR_CHANNELS_MONITOR "CHANNEL MONITOR" -#define TR_INTERNALRF "Internal RF" -#define TR_EXTERNALRF "External RF" -#define TR_FAILSAFE INDENT "Failsafe mode" -#define TR_FAILSAFESET "FAILSAFE SETTINGS" -#define TR_COUNTRYCODE "Country Code" -#define TR_VOICELANG "Voice Language" -#define TR_UNITSSYSTEM "Units" -#define TR_EDIT "Edit" -#define TR_INSERT_BEFORE "Insert Before" -#define TR_INSERT_AFTER "Insert After" -#define TR_COPY "Copy" -#define TR_MOVE "Move" -#define TR_PASTE "Paste" -#define TR_DELETE "Delete" -#define TR_INSERT "Insert" -#define TR_RESET_FLIGHT "Reset Flight" -#define TR_RESET_TIMER1 "Reset Timer1" -#define TR_RESET_TIMER2 "Reset Timer2" -#define TR_RESET_TELEMETRY "Reset Telemetry" -#define TR_STATISTICS "Statistics" -#define TR_ABOUT_US "About" -#define TR_AND_SWITCH "AND Switch" -#define TR_CF "CF" -#define TR_SPEAKER INDENT"Speaker" -#define TR_BUZZER INDENT"Buzzer" -#define TR_BYTES "bytes" -#define TR_MODULE_BIND "[Bind]" -#define TR_MODULE_RANGE "[Range]" -#define TR_RESET_BTN "[Reset]" -#define TR_SET "[Set]" -#define TR_TRAINER "Trainer" -#define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!" -#define TR_MODELIDUSED TR("ID already used","Model ID already used") -#define TR_MODULE INDENT "Module" -#define TR_CHANNELRANGE INDENT "Channel Range" -#define TR_LOWALARM INDENT "Low Alarm" -#define TR_CRITICALALARM INDENT "Critical Alarm" -#define TR_PERSISTENT_MAH INDENT "Store mAh" - -#if defined(MAVLINK) - #define TR_MAVLINK_RC_RSSI_SCALE_LABEL "Max RSSI" - #define TR_MAVLINK_PC_RSSI_EN_LABEL "PC RSSI EN" - #define TR_MAVMENUSETUP_TITLE "Mavlink Setup" - #define TR_MAVLINK_BAUD_LABEL "Baudrate" - #define TR_MAVLINK_INFOS "INFOS" - #define TR_MAVLINK_MODE "MODE" - #define TR_MAVLINK_CUR_MODE "Current Mode" - #define TR_MAVLINK_ARMED "Armed" - #define TR_MAVLINK_BAT_MENU_TITLE "BAT RSSI" - #define TR_MAVLINK_BATTERY_LABEL "Flight Battery status" - #define TR_MAVLINK_RC_RSSI_LABEL "RC RSSI" - #define TR_MAVLINK_PC_RSSI_LABEL "PC RSSI" - #define TR_MAVLINK_NAV_MENU_TITLE "NAV" - #define TR_MAVLINK_COURSE "Course" - #define TR_MAVLINK_HEADING "Heading" - #define TR_MAVLINK_BEARING "Bearing" - #define TR_MAVLINK_ALTITUDE "Altitude" - #define TR_MAVLINK_GPS "GPS" - #define TR_MAVLINK_NO_FIX "NO Fix" - #define TR_MAVLINK_SAT "SAT" - #define TR_MAVLINK_HDOP "HDOP" - #define TR_MAVLINK_LAT "LAT" - #define TR_MAVLINK_LON "LON" -#endif - - - -// Taranis column headers -#define TR_PHASES_HEADERS { " Name ", " Switch ", " Trims ", " Fade In ", " Fade Out " } -#define TR_LIMITS_HEADERS { " Name ", " Subtrim ", " Min ", " Max ", " Direction ", " Curve ", " PPM Center ", " Subtrim mode " } -#define TR_CSW_HEADERS { " Function ", " V1 ", " V2 ", " AND Switch ", " Duration ", " Delay " } - -// About screen -#define TR_ABOUTUS TR(" ABOUT ", "ABOUT") - -#define TR_ABOUT_OPENTX_1 TR("OpenTX\001is\001open\001source,\001non", "OpenTX is open source, non-") -#define TR_ABOUT_OPENTX_2 TR("commercial,\001wo\001warranties.", "commercial and comes with no") -#define TR_ABOUT_OPENTX_3 TR("It\001was\001developed\001for\001free.", "warranties. It was developed") -#define TR_ABOUT_OPENTX_4 TR("Support through donations", "for free. Support through") -#define TR_ABOUT_OPENTX_5 TR("is welcome!", "donations is welcome!") - -#define TR_ABOUT_BERTRAND_1 "Bertrand Songis" -#define TR_ABOUT_BERTRAND_2 "OpenTX main author" -#define TR_ABOUT_BERTRAND_3 "Companion9x co-author" - -#define TR_ABOUT_MIKE_1 "Mike Blandford" -#define TR_ABOUT_MIKE_2 "Code and drivers guru" -#define TR_ABOUT_MIKE_3 TR("Arguably,\001one\001of\001the\001best", "Arguably, one of the best") -#define TR_ABOUT_MIKE_4 "Inspirational" - -#define TR_ABOUT_ROMOLO_1 "Romolo Manfredini" -#define TR_ABOUT_ROMOLO_2 "Companion9x co-author" -#define TR_ABOUT_ROMOLO_3 "" - -#define TR_ABOUT_ANDRE_1 "Andre Bernet" -#define TR_ABOUT_ANDRE_2 "Functionality, usability," -#define TR_ABOUT_ANDRE_3 "debugging, documentation" - -#define TR_ABOUT_ROB_1 "Rob Thomson" -#define TR_ABOUT_ROB_2 "openrcforums webmaster" - -#define TR_ABOUT_MARTIN_1 "Martin Hotar" -#define TR_ABOUT_MARTIN_2 "Graphics designer" - -#if defined(PCBTARANIS) - #define TR_ABOUT_HARDWARE_1 "FrSky" - #define TR_ABOUT_HARDWARE_2 "Hardware designer/producer" - #define TR_ABOUT_HARDWARE_3 "Firmware contributor" -#else - #define TR_ABOUT_HARDWARE_1 "Brent Nelson" - #define TR_ABOUT_HARDWARE_2 "Sky9x designer/producer" - #define TR_ABOUT_HARDWARE_3 "" -#endif - -#define TR_ABOUT_PARENTS_1 "Parent projects" -#define TR_ABOUT_PARENTS_2 TR("Ersky9x (Mike Blandford)", "Ersky9x (Mike Blandford)") -#define TR_ABOUT_PARENTS_3 "ER9X (Erez Raviv)" -#define TR_ABOUT_PARENTS_4 "TH9X (Thomas Husterer)" - -#define TR_CHR_SHORT 's' -#define TR_CHR_LONG 'l' -#define TR_CHR_TOGGLE 't' -#define TR_CHR_HOUR 'h' - -#define TR_BEEP_VOLUME "Beep Volume" -#define TR_WAV_VOLUME "Wav Volume" -#define TR_VARIO_VOLUME "Vario Volume" -#define TR_BG_VOLUME "Bg Volume" - -#define TR_TOP_BAR "Top Bar" -#define TR_ALTITUDE INDENT "Altitude" -#define TR_MODS_FORBIDDEN "Modifications forbidden!" -#define TR_UNLOCKED "Unlocked" - From f49d2813306926978fab1f31512cd4aeed8f0847 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:31:02 -0500 Subject: [PATCH 16/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/es.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 11f626168..25cd5565f 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Alarma" #define TR_USRDATA "UsrData" #define TR_BLADES INDENT"Palas" +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Pantalla" #define TR_SOUND_LABEL "Sonido" #define TR_LENGTH INDENT"Longitud" From ea4abdf9bf22b54525058cdb1ecdac22b75a391b Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:44:49 -0500 Subject: [PATCH 17/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/cz.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 145783ff3..9c84a4119 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA TR("UživData", "Uživ. data") #define TR_BLADES TR(INDENT"ListyVrt", INDENT"Listy vrtule") +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Panel " #define TR_SOUND_LABEL "Zvuk" #define TR_LENGTH INDENT"Délka" From 933e2c4001122507fba22df76a6a9445da1b266c Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:45:29 -0500 Subject: [PATCH 18/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/de.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 8023eaf06..694f8ce18 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA "Daten" #define TR_BLADES INDENT"Bl\201tter" +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Bild " #define TR_SOUND_LABEL "T\203ne" #define TR_LENGTH INDENT"Dauer" From 4d3747e5b68f70be022e9fff4fd6ca096a8b4f46 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:45:59 -0500 Subject: [PATCH 19/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/fr.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 652776e6e..0e363f3f4 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Alarme" #define TR_USRDATA "Données" #define TR_BLADES INDENT"Pales" +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Ecran " #define TR_SOUND_LABEL "Son" #define TR_LENGTH INDENT"Durée" From 9f4fe675089a6cad5ef7771250d05ccce861909f Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:46:20 -0500 Subject: [PATCH 20/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/it.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 3a2c62fca..2f06e0524 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Allarme" #define TR_USRDATA "Dati" #define TR_BLADES INDENT"Pale" +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Schermo " #define TR_SOUND_LABEL "Suono" #define TR_LENGTH INDENT"Durata" From 2398f5d59c22d4117999b01f88ade72830363b5e Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:47:06 -0500 Subject: [PATCH 21/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/pl.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 5525754ed..c9b533b7b 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -444,6 +444,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA TR("Dane Użytk.", "Dane użytkownika") #define TR_BLADES TR(INDENT"Łopaty śmigla", INDENT"Łopaty śmigła") +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Ekran " #define TR_SOUND_LABEL "Dźwięk" #define TR_LENGTH INDENT"Długość" From f48ed4b0d5daa8a8bccb5d44f787f729fd69b5d6 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:47:52 -0500 Subject: [PATCH 22/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/pt.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 691c840af..fa8c8b1dd 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Alarme" #define TR_USRDATA "UsrData" #define TR_BLADES INDENT"Helice" +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Tela" #define TR_SOUND_LABEL "Som" #define TR_LENGTH INDENT"Comprimento" From 6158f80c0677897648d0f29385be9ac17c7e2ee1 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:48:12 -0500 Subject: [PATCH 23/43] Added Spur and Pinion Gear Strings (English) --- radio/src/translations/se.h.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 68de29549..796c10fa4 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -443,6 +443,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA "Användardata" #define TR_BLADES INDENT"Blad" +#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley +#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley #define TR_SCREEN "Skärm" #define TR_SOUND_LABEL "Ljud " #define TR_LENGTH INDENT"Tid" From 1589f33443ebfd28b2983fbe604f223888bc3e70 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:49:00 -0500 Subject: [PATCH 24/43] Update README.txt --- README.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/README.txt b/README.txt index 70103f756..4e524cfd6 100644 --- a/README.txt +++ b/README.txt @@ -3,6 +3,7 @@ Add Gear Ratio to RPM Telemetry Calculation and allow for Blades to equal 1 Jan 16 2014 - Switched to 'next' branch - Need to solve issue with frsky_sport.cpp and calc compile error +- Need to translate "Spur" and "Gear" to other languages, using English as placeholder for now. Jan 15 2014 From 924435073735ad2c7f79165e4e25fbe0a33d1ee3 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 20:50:57 -0500 Subject: [PATCH 25/43] Update README.txt --- README.txt | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.txt b/README.txt index 4e524cfd6..6dcc5a26f 100644 --- a/README.txt +++ b/README.txt @@ -7,24 +7,25 @@ Jan 16 2014 Jan 15 2014 -•Fully working in Simulator now, new options for Spur and Pinion are in Telemetry setup screen for the model. Pinion is forced to stay equal to or smaller than spur (to prevent divide by zero). -•Tested on Taranis Rev A (eeprom is modified so backup everything before experimenting). +- Fully working in Simulator now, new options for Spur and Pinion are in Telemetry setup screen for the model. Pinion is forced to stay equal to or smaller than spur (to prevent divide by zero). +- Tested on Taranis Rev A (eeprom is modified so backup everything before experimenting). Jan 14 2014 -•The current implementation of OpenTX has a few limitations with regards to RPM sensors on Nitro Helicopters and this patch is to resolve and improve that. +- The current implementation of OpenTX has a few limitations with regards to RPM sensors on Nitro Helicopters and this patch is to resolve and improve that. -•Initial changes to make: -◦Change Minimum Blades to 1 (currently hardcoded to 2) to allow for Fan RPM Sensors (single magnet) and crank sensors. -◦Change Maximum Blades to 255 (currently limited to 5) to allow for any number of divider for both nitro or electric. -◦Add Spur Gear USRDATA option to assist with calculating head speed -◦Add Pinion Gear USRDATA option to assist with calculating head speed -◦Change RPM telemetry calculation to take into account gear ratio based upon Spur and Pinion size +- Initial changes to make: +- Change Minimum Blades to 1 (currently hardcoded to 2) to allow for Fan RPM Sensors (single magnet) and crank sensors. +- Change Maximum Blades to 255 (currently limited to 5) to allow for any number of divider for both nitro or electric. +- Add Spur Gear USRDATA option to assist with calculating head speed +- Add Pinion Gear USRDATA option to assist with calculating head speed +- Change RPM telemetry calculation to take into account gear ratio based upon Spur and Pinion size -•Future: -◦Add new telemtry calculated value "HDSP" for Headspeed to allow user to see engine RPM and calculated headspeed -◦Add more options for electric setups +- Future: +- Add gear ratio calc displayed in userdata but not editable. +- Add new telemtry calculated value "HDSP" for Headspeed to allow user to see engine RPM and calculated headspeed +- Add more options for electric setups Author - Tim Foley From acd974403b6724c06e810b66b2eccc645dceea40 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 18:06:34 -0800 Subject: [PATCH 26/43] Fixed cross initialization error --- .gitignore | 7 + radio/src/gui/menu_model.cpp~ | 5643 --------------------------- radio/src/telemetry/frsky.cpp | 3 +- radio/src/telemetry/frsky.cpp~ | 926 ----- radio/src/telemetry/frsky_sport.cpp | 12 +- 5 files changed, 20 insertions(+), 6571 deletions(-) create mode 100644 .gitignore delete mode 100644 radio/src/gui/menu_model.cpp~ delete mode 100644 radio/src/telemetry/frsky.cpp~ diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4b4d86a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.[oa] +*~ +opentx.bin +opentx.elf +opentx.lst +opentx.map + diff --git a/radio/src/gui/menu_model.cpp~ b/radio/src/gui/menu_model.cpp~ deleted file mode 100644 index d1f9889fb..000000000 --- a/radio/src/gui/menu_model.cpp~ +++ /dev/null @@ -1,5643 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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" -#ifdef MAVLINK -#include "gui/view_mavlink.h" -#endif - -#define WCHART 32 -#define X0 (LCD_W-WCHART-2) -#define Y0 32 - -enum EnumTabModel { - e_ModelSelect, - e_ModelSetup, - IF_HELI(e_Heli) - IF_FLIGHT_MODES(e_FlightModesAll) - e_InputsAll, - e_MixAll, - e_Limits, - IF_CURVES(e_CurvesAll) -#if LCD_W >= 212 - IF_GVARS(e_GVars) -#endif - e_CustomSwitches, - e_CustomFunctions, -#if defined(LUA_MODEL_SCRIPTS) - e_CustomScripts, -#endif - IF_FRSKY(e_Telemetry) - IF_MAVLINK(e_MavSetup) - IF_TEMPLATES(e_Templates) -}; - -void menuModelSelect(uint8_t event); -void menuModelSetup(uint8_t event); -void menuModelHeli(uint8_t event); -void menuModelFlightModesAll(uint8_t event); -void menuModelExposAll(uint8_t event); -void menuModelMixAll(uint8_t event); -void menuModelLimits(uint8_t event); -void menuModelCurvesAll(uint8_t event); -void menuModelGVars(uint8_t event); -void menuModelCustomSwitches(uint8_t event); -void menuModelCustomFunctions(uint8_t event); -void menuModelCustomScripts(uint8_t event); -void menuModelTelemetry(uint8_t event); -void menuModelTemplates(uint8_t event); -void menuModelExpoOne(uint8_t event); - -const MenuFuncP_PROGMEM menuTabModel[] PROGMEM = { - menuModelSelect, - menuModelSetup, - IF_HELI(menuModelHeli) - IF_FLIGHT_MODES(menuModelFlightModesAll) - menuModelExposAll, - menuModelMixAll, - menuModelLimits, - IF_CURVES(menuModelCurvesAll) -#if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) - IF_GVARS(menuModelGVars) -#endif - menuModelCustomSwitches, - menuModelCustomFunctions, -#if defined(LUA_MODEL_SCRIPTS) - menuModelCustomScripts, -#endif - IF_FRSKY(menuModelTelemetry) - IF_MAVLINK(menuTelemetryMavlinkSetup) - IF_TEMPLATES(menuModelTemplates) -}; - -#define COPY_MODE 1 -#define MOVE_MODE 2 -static uint8_t s_copyMode = 0; -static int8_t s_copySrcRow; -static int8_t s_copyTgtOfs; - -uint8_t eeFindEmptyModel(uint8_t id, bool down) -{ - uint8_t i = id; - for (;;) { - i = (MAX_MODELS + (down ? i+1 : i-1)) % MAX_MODELS; - if (!eeModelExists(i)) break; - if (i == id) return 0xff; // no free space in directory left - } - return i; -} - -void selectModel(uint8_t sub) -{ - displayPopup(STR_LOADINGMODEL); - saveTimers(); - eeCheck(true); // force writing of current model data before this is changed - g_eeGeneral.currModel = sub; - eeDirty(EE_GENERAL); - eeLoadModel(sub); -} - -#if defined(SDCARD) -#define LIST_NONE_SD_FILE 1 -bool listSdFiles(const char *path, const char *extension, const uint8_t maxlen, const char *selection, uint8_t flags=0) -{ - FILINFO fno; - DIR dir; - char *fn; /* This function is assuming non-Unicode cfg. */ -#if _USE_LFN - TCHAR lfn[_MAX_LFN + 1]; - fno.lfname = lfn; - fno.lfsize = sizeof(lfn); -#endif - - static uint16_t s_last_menu_offset = 0; - -#if defined(CPUARM) - static uint8_t s_last_flags; - - if (selection) { - s_last_flags = flags; - memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); - strcpy(reusableBuffer.modelsel.menu_bss[0], path); - strcat(reusableBuffer.modelsel.menu_bss[0], "/"); - strncat(reusableBuffer.modelsel.menu_bss[0], selection, maxlen); - strcat(reusableBuffer.modelsel.menu_bss[0], extension); - if (f_stat(reusableBuffer.modelsel.menu_bss[0], &fno) != FR_OK) { - selection = NULL; - } - } - else { - flags = s_last_flags; - } -#endif - - if (s_menu_offset == 0) { - s_last_menu_offset = 0; - memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); - } - else if (s_menu_offset == s_menu_count - MENU_MAX_LINES) { - s_last_menu_offset = 0xffff; - memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); - } - else if (s_menu_offset == s_last_menu_offset) { - // should not happen, only there because of Murphy's law - return true; - } - else if (s_menu_offset > s_last_menu_offset) { - memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], (MENU_MAX_LINES-1)*MENU_LINE_LENGTH); - memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], 0xff, MENU_LINE_LENGTH); - } - else { - memmove(reusableBuffer.modelsel.menu_bss[1], reusableBuffer.modelsel.menu_bss[0], (MENU_MAX_LINES-1)*MENU_LINE_LENGTH); - memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH); - } - - s_menu_count = 0; - s_menu_flags = BSS; - - FRESULT res = f_opendir(&dir, path); /* Open the directory */ - if (res == FR_OK) { - - if (flags & LIST_NONE_SD_FILE) { - s_menu_count++; - if (selection) { - s_last_menu_offset++; - } - else if (s_menu_offset==0 || s_menu_offset < s_last_menu_offset) { - char *line = reusableBuffer.modelsel.menu_bss[0]; - memset(line, 0, MENU_LINE_LENGTH); - strcpy(line, "---"); - s_menu[0] = line; - } - } - - for (;;) { - res = f_readdir(&dir, &fno); /* Read a directory item */ - if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ - -#if _USE_LFN - fn = *fno.lfname ? fno.lfname : fno.fname; -#else - fn = fno.fname; -#endif - - uint8_t len = strlen(fn); - if (len < 5 || len > maxlen+4 || strcasecmp(fn+len-4, extension) || (fno.fattrib & AM_DIR)) continue; - - s_menu_count++; - fn[len-4] = '\0'; - - if (s_menu_offset == 0) { - if (selection && strncasecmp(fn, selection, maxlen) < 0) { - s_last_menu_offset++; - } - else { - for (uint8_t i=0; i=0; i--) { - char *line = reusableBuffer.modelsel.menu_bss[i]; - if (line[0] == '\0' || strcasecmp(fn, line) > 0) { - if (i > 0) memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], sizeof(reusableBuffer.modelsel.menu_bss[i]) * i); - memset(line, 0, MENU_LINE_LENGTH); - strcpy(line, fn); - break; - } - } - for (uint8_t i=0; i s_last_menu_offset) { - if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-2]) > 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1]) < 0) { - memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], 0, MENU_LINE_LENGTH); - strcpy(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], fn); - } - } - else { - if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[1]) < 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[0]) > 0) { - memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH); - strcpy(reusableBuffer.modelsel.menu_bss[0], fn); - } - } - } - } - - if (s_menu_offset > 0) - s_last_menu_offset = s_menu_offset; - else - s_menu_offset = s_last_menu_offset; - - return s_menu_count; -} -#endif - -#if defined(PCBTARANIS) - static int8_t modelselBitmapIdx; - static uint8_t modelselBitmap[MODEL_BITMAP_SIZE]; - #define MODELSEL_W 133 - #define BMP_DIRTY() modelselBitmapIdx = -1 -#else - #define MODELSEL_W LCD_W - #define BMP_DIRTY() -#endif - -#if defined(NAVIGATION_MENUS) -void onModelSelectMenu(const char *result) -{ - int8_t sub = m_posVert; - - if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) { - selectModel(sub); - } - else if (result == STR_COPY_MODEL) { - s_copyMode = COPY_MODE; - s_copyTgtOfs = 0; - s_copySrcRow = -1; - } - else if (result == STR_MOVE_MODEL) { - s_copyMode = MOVE_MODE; - s_copyTgtOfs = 0; - s_copySrcRow = -1; - } -#if defined(SDCARD) - else if (result == STR_BACKUP_MODEL) { - eeCheck(true); // force writing of current model data before this is changed - POPUP_WARNING(eeBackupModel(sub)); - } - else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) { - if (!listSdFiles(MODELS_PATH, MODELS_EXT, sizeof(g_model.header.name), NULL)) { - POPUP_WARNING(STR_NO_MODELS_ON_SD); - s_menu_flags = 0; - } - } -#endif - else if (result == STR_DELETE_MODEL) { - POPUP_CONFIRMATION(STR_DELETEMODEL); -#if defined(CPUARM) - s_warning_info = modelHeaders[sub].name; -#else - char * name = reusableBuffer.modelsel.mainname; - eeLoadModelName(sub, name); - s_warning_info = name; -#endif - s_warning_info_len = sizeof(g_model.header.name); - } -#if defined(SDCARD) - else { - // The user choosed a file on SD to restore - POPUP_WARNING(eeRestoreModel(sub, (char *)result)); - BMP_DIRTY(); - if (!s_warning && g_eeGeneral.currModel == sub) - eeLoadModel(sub); - } -#endif -} -#endif - -void menuModelSelect(uint8_t event) -{ - if (s_warning_result) { - s_warning_result = 0; - eeDeleteModel(m_posVert); // delete file - s_copyMode = 0; - event = EVT_ENTRY_UP; - BMP_DIRTY(); - } - - uint8_t _event_ = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event); - -#if defined(PCBTARANIS) - if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) - _event_ -= KEY_EXIT; -#else - if (s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) - _event_ -= KEY_EXIT; -#endif - - int8_t oldSub = m_posVert; - - if (!check_submenu_simple(_event_, MAX_MODELS-1)) return; - -#if defined(NAVIGATION_POT2) - if (event==0 && p2valdiff<0) { - event = EVT_KEY_FIRST(KEY_RIGHT); - } -#endif - - if (s_editMode > 0) s_editMode = 0; - -#if !defined(CPUARM) - if (event) { - eeFlush(); // flush eeprom write - } -#endif - - int8_t sub = m_posVert; - - switch (event) - { - case EVT_ENTRY: - m_posVert = sub = g_eeGeneral.currModel; - if (sub >= LCD_LINES-1) s_pgOfs = sub-LCD_LINES+2; - s_copyMode = 0; - s_editMode = EDIT_MODE_INIT; - BMP_DIRTY(); - eeCheck(true); - break; - case EVT_KEY_LONG(KEY_EXIT): - if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) { - POPUP_CONFIRMATION(STR_DELETEMODEL); -#if defined(CPUARM) - s_warning_info = modelHeaders[sub].name; -#else - char * name = reusableBuffer.modelsel.mainname; - eeLoadModelName(sub, name); - s_warning_info = name; -#endif - s_warning_info_len = sizeof(g_model.header.name); - killEvents(event); - break; - } - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - killEvents(event); - if (s_editMode < 0) { - popMenu(); - return; - } - else if (!s_copyMode) { - m_posVert = sub = g_eeGeneral.currModel; - s_copyMode = 0; - s_editMode = EDIT_MODE_INIT; - } - // no break -#endif - case EVT_KEY_BREAK(KEY_EXIT): - if (s_copyMode) { - sub = m_posVert = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (MAX_MODELS+sub+s_copyTgtOfs) % MAX_MODELS : s_copySrcRow; - s_copyMode = 0; - } -#if defined(PCBTARANIS) - else { - if (m_posVert != g_eeGeneral.currModel) { - m_posVert = g_eeGeneral.currModel; - s_pgOfs = 0; - } - else { - popMenu(); - return; - } - } -#endif - break; -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: - if (s_editMode == -1) { - s_editMode = 0; - break; - } - // no break; -#endif - case EVT_KEY_LONG(KEY_ENTER): - case EVT_KEY_BREAK(KEY_ENTER): - s_editMode = 0; - if (READ_ONLY()) { - if (g_eeGeneral.currModel != sub && eeModelExists(sub)) { - selectModel(sub); - } - } - else if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) { - displayPopup(s_copyMode==COPY_MODE ? STR_COPYINGMODEL : STR_MOVINGMODEL); - eeCheck(true); // force writing of current model data before this is changed - - uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS; - - if (s_copyMode == COPY_MODE) { - if (eeCopyModel(cur, s_copySrcRow)) - BMP_DIRTY(); - else - cur = sub; - } - - s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value - while (sub != cur) { - uint8_t src = cur; - cur = (s_copyTgtOfs > 0 ? cur+MAX_MODELS-1 : cur+1) % MAX_MODELS; - eeSwapModels(src, cur); - BMP_DIRTY(); - if (src == s_copySrcRow) - s_copySrcRow = cur; - else if (cur == s_copySrcRow) - s_copySrcRow = src; - } - - if (s_copySrcRow != g_eeGeneral.currModel) { - g_eeGeneral.currModel = s_copySrcRow; - eeDirty(EE_GENERAL); - } - - s_copyMode = 0; - event = EVT_ENTRY_UP; - } - else if (event == EVT_KEY_LONG(KEY_ENTER) -#if !defined(PCBTARANIS) - || IS_ROTARY_BREAK(event) -#endif - ) { - s_copyMode = 0; - killEvents(event); -#if defined(NAVIGATION_MENUS) - if (g_eeGeneral.currModel != sub) { - if (eeModelExists(sub)) { - MENU_ADD_ITEM(STR_SELECT_MODEL); - MENU_ADD_SD_ITEM(STR_BACKUP_MODEL); - MENU_ADD_ITEM(STR_COPY_MODEL); - MENU_ADD_ITEM(STR_MOVE_MODEL); - MENU_ADD_ITEM(STR_DELETE_MODEL); - } - else { -#if defined(SDCARD) - MENU_ADD_ITEM(STR_CREATE_MODEL); - MENU_ADD_ITEM(STR_RESTORE_MODEL); -#else - selectModel(sub); -#endif - } - } - else { - MENU_ADD_SD_ITEM(STR_BACKUP_MODEL); - MENU_ADD_ITEM(STR_COPY_MODEL); - MENU_ADD_ITEM(STR_MOVE_MODEL); - } - menuHandler = onModelSelectMenu; -#else - if (g_eeGeneral.currModel != sub) { - selectModel(sub); - } -#endif - } - else if (eeModelExists(sub)) { - s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); - s_copyTgtOfs = 0; - s_copySrcRow = -1; - } - break; - -#if defined(PCBTARANIS) - case EVT_KEY_BREAK(KEY_PAGE): - case EVT_KEY_LONG(KEY_PAGE): - chainMenu(event == EVT_KEY_BREAK(KEY_PAGE) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]); - killEvents(event); - return; -#else -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LEFT: - case EVT_ROTARY_RIGHT: -#endif - case EVT_KEY_FIRST(KEY_LEFT): - case EVT_KEY_FIRST(KEY_RIGHT): -#if defined(ROTARY_ENCODER_NAVIGATION) - if ((!IS_ROTARY_RIGHT(event) && !IS_ROTARY_LEFT(event)) || s_editMode < 0) { -#endif - if (sub == g_eeGeneral.currModel) { - chainMenu((IS_ROTARY_RIGHT(event) || event == EVT_KEY_FIRST(KEY_RIGHT)) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]); - return; - } - AUDIO_WARNING2(); - break; -#if defined(ROTARY_ENCODER_NAVIGATION) - } - // no break -#endif -#endif - - case EVT_KEY_FIRST(KEY_MOVE_UP): - case EVT_KEY_REPT(KEY_MOVE_UP): - case EVT_KEY_FIRST(KEY_MOVE_DOWN): - case EVT_KEY_REPT(KEY_MOVE_DOWN): - if (s_copyMode) { - int8_t next_ofs = s_copyTgtOfs + oldSub - m_posVert; - if (next_ofs == MAX_MODELS || next_ofs == -MAX_MODELS) - next_ofs = 0; - - if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) { - s_copySrcRow = oldSub; - // find a hole (in the first empty slot above / below) - sub = eeFindEmptyModel(s_copySrcRow, IS_ROTARY_DOWN(event) || event==EVT_KEY_FIRST(KEY_MOVE_DOWN)); - if (sub < 0) { - // no free room for duplicating the model - AUDIO_ERROR(); - sub = oldSub; - s_copyMode = 0; - } - next_ofs = 0; - m_posVert = sub; - } - s_copyTgtOfs = next_ofs; - } - break; - } - -#if defined(PCBTARANIS) - lcd_puts(27*FW-(LEN_FREE-4)*FW, 0, STR_FREE); - if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree(); - lcd_outdezAtt(20*FW, 0, reusableBuffer.modelsel.eepromfree, 0); - lcd_puts(21*FW, 0, STR_BYTES); -#elif !defined(PCBSKY9X) - lcd_puts(9*FW-(LEN_FREE-4)*FW, 0, STR_FREE); - if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree(); - lcd_outdezAtt(17*FW, 0, reusableBuffer.modelsel.eepromfree, 0); -#endif - -#if defined(ROTARY_ENCODER_NAVIGATION) - displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? ((IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) ? INVERS|BLINK : INVERS) : 0); -#elif defined(PCBTARANIS) - displayScreenIndex(e_ModelSelect, DIM(menuTabModel), 0); - lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); -#else - displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? INVERS : 0); -#endif - - TITLE(STR_MENUMODELSEL); - - for (uint8_t i=0; i= 0)) { - if (k == sub) { - if (s_copyMode == COPY_MODE) { - k = s_copySrcRow; - lcd_putc(MODELSEL_W-FW, y, '+'); - } - else { - k = sub + s_copyTgtOfs; - } - } - else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-MAX_MODELS < sub && k-MAX_MODELS >= sub+s_copyTgtOfs))) - k += 1; - else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+MAX_MODELS > sub && k+MAX_MODELS <= sub+s_copyTgtOfs))) - k += MAX_MODELS-1; - } - - k %= MAX_MODELS; - - if (eeModelExists(k)) { -#if defined(PCBSKY9X) - putsModelName(4*FW, y, modelHeaders[k].name, k, 0); -#elif defined(CPUARM) - putsModelName(4*FW, y, modelHeaders[k].name, k, 0); - lcd_outdezAtt(20*FW, y, eeModelSize(k), 0); -#else - char * name = reusableBuffer.modelsel.listnames[i]; - if (event) eeLoadModelName(k, name); - putsModelName(4*FW, y, name, k, 0); - lcd_outdezAtt(20*FW, y, eeModelSize(k), 0); -#endif - if (k==g_eeGeneral.currModel && (s_copyMode!=COPY_MODE || s_copySrcRow<0 || i+s_pgOfs!=(vertpos_t)sub)) lcd_putc(1, y, '*'); - } - - if (s_copyMode && (vertpos_t)sub==i+s_pgOfs) { - lcd_filled_rect(9, y, MODELSEL_W-1-9, 7); - lcd_rect(8, y-1, MODELSEL_W-1-7, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); - } - } - -#if defined(PCBTARANIS) - if (modelselBitmapIdx != m_posVert) { - modelselBitmapIdx = m_posVert; - if (modelselBitmapIdx == g_eeGeneral.currModel) - memcpy(modelselBitmap, modelBitmap, MODEL_BITMAP_SIZE); - else - loadModelBitmap(modelHeaders[sub].bitmap, modelselBitmap); - } - lcd_bmp(22*FW+2, 2*FH+FH/2, modelselBitmap); -#endif -} - -#if defined(PCBTARANIS) -uint8_t g_moduleIdx; -void menuModelFailsafe(uint8_t event) -{ - static bool longNames = false; - bool newLongNames = false; - uint8_t ch; - - if (event == EVT_KEY_BREAK(KEY_ENTER) && s_editMode) { - g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert]; - eeDirty(EE_MODEL); - AUDIO_WARNING1(); - SEND_FAILSAFE_NOW(g_moduleIdx); - } - - SIMPLE_SUBMENU_NOTITLE(32); - - SET_SCROLLBAR_X(0); - - if (m_posVert >= 16) - ch = 16; - else - ch = 0; - - lcd_putsCenter(0*FH, FAILSAFESET); - lcd_invert_line(0); - - // Column separator - lcd_vline(LCD_W/2, FH, LCD_H-FH); - - for (uint8_t col=0; col<2; col++) { - - uint8_t x = col*LCD_W/2+1; - - // Channels - for (uint8_t line=0; line<8; line++) { - uint8_t y = 9+line*7; - int32_t val; - uint8_t ofs = (col ? 0 : 1); - - if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) - val = 0; - else if (s_editMode && m_posVert == ch) - val = channelOutputs[ch]; - else - val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; - - // Channel name if present, number if not - uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); - if (lenLabel > 4) { - newLongNames = longNames = true; - } - - if (lenLabel > 0) - lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE); - else - putsChn(x+1-ofs, y, ch+1, SMLSIZE); - - // Value - LcdFlags flags = TINSIZE; - if (m_posVert == ch) { - flags |= INVERS; - if (s_editMode) - flags |= BLINK; - } -#if defined(PPM_UNIT_US) - uint8_t wbar = (longNames ? 54 : 64); - lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags); -#elif defined(PPM_UNIT_PERCENT_PREC1) - uint8_t wbar = (longNames ? 48 : 58); - lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags); -#else - uint8_t wbar = (longNames ? 54 : 64); - lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, calcRESXto1000(val)/10, flags); -#endif - - // Gauge - lcd_rect(x+LCD_W/2-3-wbar-ofs, y, wbar+1, 6); - uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2; - uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); - uint8_t x0 = (val>0) ? x+LCD_W/2-ofs-3-wbar/2 : x+LCD_W/2-ofs-2-wbar/2-len; - lcd_hline(x0, y+1, len); - lcd_hline(x0, y+2, len); - lcd_hline(x0, y+3, len); - lcd_hline(x0, y+4, len); - - ch++; - } - } - - longNames = newLongNames; -} -#endif - -#if defined(CPUM64) - #define editNameCursorPos m_posHorz -#else - static uint8_t editNameCursorPos = 0; -#endif - -void editName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, uint8_t active) -{ -#if defined(CPUM64) - // in order to save flash - lcd_putsLeft(y, STR_NAME); -#endif - - lcd_putsnAtt(x, y, name, size, ZCHAR | ((active && s_editMode <= 0) ? INVERS : 0)); - - if (active) { - uint8_t cur = editNameCursorPos; - if (s_editMode > 0) { - int8_t c = name[cur]; - int8_t v = c; - - if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) - || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { - v = checkIncDec(event, abs(v), 0, LEN_STD_CHARS, 0); - if (c <= 0) v = -v; - } - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - case EVT_ROTARY_BREAK: - if (s_editMode == EDIT_MODIFY_FIELD) { - s_editMode = EDIT_MODIFY_STRING; - cur = 0; - } - else if (cur0) cur--; - break; - case EVT_KEY_BREAK(KEY_RIGHT): - if (cur=-26 && v<=26) { - v = -v; // toggle case - if (event==EVT_KEY_LONG(KEY_LEFT)) - killEvents(KEY_LEFT); - } - break; - } - - if (c != v) { - name[cur] = v; - eeDirty(EE_MODEL); - } - lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), INVERS); - } - else { - cur = 0; - } - editNameCursorPos = cur; - } -} - -#if defined(CPUM64) -#define editSingleName(x, y, label, name, size, event, active) editName(x, y, name, size, event, active) -#else -void editSingleName(uint8_t x, uint8_t y, const pm_char *label, char *name, uint8_t size, uint8_t event, uint8_t active) -{ - lcd_putsLeft(y, label); - editName(x, y, name, size, event, active); -} -#endif - -enum menuModelSetupItems { - ITEM_MODEL_NAME, - CASE_PCBTARANIS(ITEM_MODEL_BITMAP) - ITEM_MODEL_TIMER1, - IF_PERSISTENT_TIMERS(ITEM_MODEL_TIMER1_PERSISTENT) - ITEM_MODEL_TIMER1_MINUTE_BEEP, - ITEM_MODEL_TIMER1_COUNTDOWN_BEEP, - ITEM_MODEL_TIMER2, - IF_PERSISTENT_TIMERS(ITEM_MODEL_TIMER2_PERSISTENT) - ITEM_MODEL_TIMER2_MINUTE_BEEP, - ITEM_MODEL_TIMER2_COUNTDOWN_BEEP, - ITEM_MODEL_EXTENDED_LIMITS, - ITEM_MODEL_EXTENDED_TRIMS, - ITEM_MODEL_TRIM_INC, - ITEM_MODEL_THROTTLE_REVERSED, - ITEM_MODEL_THROTTLE_TRACE, - ITEM_MODEL_THROTTLE_TRIM, - ITEM_MODEL_THROTTLE_WARNING, - ITEM_MODEL_SWITCHES_WARNING, - ITEM_MODEL_BEEP_CENTER, -#if defined(PCBTARANIS) - ITEM_MODEL_INTERNAL_MODULE_LABEL, - ITEM_MODEL_INTERNAL_MODULE_MODE, - ITEM_MODEL_INTERNAL_MODULE_CHANNELS, - ITEM_MODEL_INTERNAL_MODULE_BIND, - ITEM_MODEL_INTERNAL_MODULE_FAILSAFE, - ITEM_MODEL_EXTERNAL_MODULE_LABEL, - ITEM_MODEL_EXTERNAL_MODULE_MODE, - ITEM_MODEL_EXTERNAL_MODULE_CHANNELS, - ITEM_MODEL_EXTERNAL_MODULE_BIND, - ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE, - ITEM_MODEL_TRAINER_LABEL, - ITEM_MODEL_TRAINER_MODE, - ITEM_MODEL_TRAINER_CHANNELS, - ITEM_MODEL_TRAINER_SETTINGS, -#elif defined(PCBSKY9X) - ITEM_MODEL_PPM1_PROTOCOL, - ITEM_MODEL_PPM1_PARAMS, - ITEM_MODEL_PPM2_PROTOCOL, - ITEM_MODEL_PPM2_PARAMS, -#else - ITEM_MODEL_PPM1_PROTOCOL, - ITEM_MODEL_PPM1_PARAMS, -#endif - ITEM_MODEL_SETUP_MAX -}; - -#if defined(PCBSKY9X) - #define FIELD_PROTOCOL_MAX 2 -#else - #define FIELD_PROTOCOL_MAX 1 -#endif - -#if LCD_W >= 212 -#define MODEL_SETUP_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH) -#else -#define MODEL_SETUP_2ND_COLUMN (LCD_W-11*FW-MENUS_SCROLLBAR_WIDTH) -#endif - -#if defined(PCBTARANIS) && defined(SDCARD) -void copySelection(char *dst, const char *src, uint8_t size) -{ - if (memcmp(src, "---", 3) == 0) - memset(dst, 0, size); - else - memcpy(dst, src, size); -} - -void onModelSetupBitmapMenu(const char *result) -{ - if (result == STR_UPDATE_LIST) { - if (!listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), NULL)) { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - s_menu_flags = 0; - } - } - else { - // The user choosed a bmp file in the list - copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap)); - LOAD_MODEL_BITMAP(); - memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); - eeDirty(EE_MODEL); - } -} -#endif - -void menuModelSetup(uint8_t event) -{ -#if defined(PCBTARANIS) - #define IF_PORT1_ON(x) (g_model.moduleData[0].rfProtocol == RF_PROTO_OFF ? HIDDEN_ROW : (uint8_t)(x)) - #define IF_PORT2_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x)) - #define IF_TRAINER_ON(x) (g_model.trainerMode ? (uint8_t)(x) : HIDDEN_ROW) - #define IF_PORT_ON(idx, x) (idx==0 ? IS_PORT1_ON(x) : (idx==1 ? IS_PORT2_ON(x) : IS_TRAINER_ON())) - #define IF_PORT2_XJT(x) (IS_MODULE_XJT(1) ? (uint8_t)x : HIDDEN_ROW) - #define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) - #define PORT1_CHANNELS_ROWS() IF_PORT1_ON(1) - #define PORT2_CHANNELS_ROWS() IF_PORT2_ON(IS_MODULE_DSM2(1) ? (uint8_t)0 : (uint8_t)1) - #define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) - #define PORT_CHANNELS_ROWS(x) (x==0 ? PORT1_CHANNELS_ROWS() : (x==1 ? PORT2_CHANNELS_ROWS() : TRAINER_CHANNELS_ROWS())) - #define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) - #define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX) - - bool CURSOR_ON_CELL = (m_posHorz >= 0); - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(IS_D8_RX(0) ? (uint8_t)1 : (uint8_t)2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_XJT(1) && IS_D8_RX(1)) ? (uint8_t)1 : (IS_MODULE_PPM(1) || IS_MODULE_XJT(1) || IS_MODULE_DSM2(1)) ? (uint8_t)2 : HIDDEN_ROW, IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); -#elif defined(CPUM64) - #define CURSOR_ON_CELL (true) - #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) - - uint8_t protocol = g_model.protocol; - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2 }); -#else - #define CURSOR_ON_CELL (true) - #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) - - uint8_t protocol = g_model.protocol; - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2, IF_PCBSKY9X(1) IF_PCBSKY9X(2) }); -#endif - - if (!MENU_CHECK(menuTabModel, e_ModelSetup, MODEL_SETUP_MAX_LINES)) { -#if defined(DSM2) - dsm2Flag = 0; -#endif -#if defined(PCBTARANIS) - pxxFlag[INTERNAL_MODULE] = 0; - pxxFlag[EXTERNAL_MODULE] = 0; -#endif - return; - } - - TITLE(STR_MENUSETUP); - - uint8_t sub = m_posVert - 1; - int8_t editMode = s_editMode; - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); - uint8_t attr = (sub == k ? blink : 0); - - switch(k) { - case ITEM_MODEL_NAME: - editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_MODELNAME, g_model.header.name, sizeof(g_model.header.name), event, attr); -#if defined(CPUARM) - memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name)); -#endif - break; - -#if defined(PCBTARANIS) && defined(SDCARD) - case ITEM_MODEL_BITMAP: - lcd_putsLeft(y, STR_BITMAP); - if (ZEXIST(g_model.header.bitmap)) - lcd_putsnAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.bitmap, sizeof(g_model.header.bitmap), attr); - else - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VCSWFUNC, 0, attr); - if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) { - s_editMode = 0; - if (listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), g_model.header.bitmap, LIST_NONE_SD_FILE)) { - menuHandler = onModelSetupBitmapMenu; - } - else { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - s_menu_flags = 0; - } - } - break; -#endif - - case ITEM_MODEL_TIMER1: - case ITEM_MODEL_TIMER2: - case ITEM_MODEL_TIMER1_MINUTE_BEEP: - case ITEM_MODEL_TIMER2_MINUTE_BEEP: - case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP: - case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP: - { - TimerData *timer = &g_model.timers[k>=ITEM_MODEL_TIMER2 ? 1 : 0]; - if (k==ITEM_MODEL_TIMER1_MINUTE_BEEP || k==ITEM_MODEL_TIMER2_MINUTE_BEEP) { - timer->minuteBeep = onoffMenuItem(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); - } - else if (k==ITEM_MODEL_TIMER1_COUNTDOWN_BEEP || k==ITEM_MODEL_TIMER2_COUNTDOWN_BEEP) { -#if defined(CPUARM) - timer->countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, timer->countdownBeep, 0, 2, attr, event); -#else - timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); -#endif - } - else { - putsStrIdx(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1); - putsTmrMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, m_posHorz==0 ? attr : 0); - putsTime(MODEL_SETUP_2ND_COLUMN+5*FW-2+5*FWNUM+1, y, timer->start, m_posHorz==1 ? attr : 0, m_posHorz==2 ? attr : 0); -#if defined(PCBTARANIS) - if (attr && m_posHorz < 0) lcd_filled_rect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); -#endif - if (attr && (editMode>0 || p1valdiff)) { - div_t qr = div(timer->start, 60); - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, timer->mode, -2*(MAX_PSWITCH+NUM_CSW), TMR_VAROFS-1+2*(MAX_PSWITCH+NUM_CSW)); - break; - case 1: - CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 59); - timer->start = qr.rem + qr.quot*60; - break; - case 2: - qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2; - timer->start -= qr.rem ; - if ((int16_t)timer->start < 0) timer->start=0; - break; - } - } - } - break; - } - -#if defined(CPUARM) || defined(PCBGRUVIN9X) - case ITEM_MODEL_TIMER1_PERSISTENT: - case ITEM_MODEL_TIMER2_PERSISTENT: - { - TimerData &timer = g_model.timers[k==ITEM_MODEL_TIMER2_PERSISTENT]; - timer.persistent = onoffMenuItem(timer.persistent, MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, attr, event); - break; - } -#endif - - case ITEM_MODEL_EXTENDED_LIMITS: - g_model.extendedLimits = onoffMenuItem(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event); - break; - - case ITEM_MODEL_EXTENDED_TRIMS: -#if defined(CPUM64) - g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event); -#else - g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 ? attr : 0); - if (attr && m_posHorz>0) { - s_editMode = 0; - if (event==EVT_KEY_LONG(KEY_ENTER)) { - for (uint8_t i=0; i MIXSRC_Thr) - idx += 1; - if (idx >= MIXSRC_FIRST_POT+NUM_POTS) - idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS; - putsMixerSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr); - break; - } - - case ITEM_MODEL_THROTTLE_TRIM: - g_model.thrTrim = onoffMenuItem(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event); - break; - - case ITEM_MODEL_THROTTLE_WARNING: - g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); - break; - - case ITEM_MODEL_SWITCHES_WARNING: - { - lcd_putsLeft(y, STR_SWITCHWARNING); - swstate_t states = g_model.switchWarningStates; - char c = !(states & 1); - menu_lcd_onoff(MODEL_SETUP_2ND_COLUMN, y, c, attr); - if (attr) { - s_editMode = 0; - switch(event) { - case EVT_KEY_LONG(KEY_ENTER): - if (!READ_ONLY()) { - killEvents(event); - getMovedSwitch(); - g_model.switchWarningStates = 0x01 + (switches_states << 1); - } - // no break - CASE_EVT_ROTARY_BREAK - case EVT_KEY_BREAK(KEY_ENTER): -#if !defined(PCBTARANIS) - case EVT_KEY_BREAK(KEY_LEFT): - case EVT_KEY_BREAK(KEY_RIGHT): -#endif - if (!READ_ONLY()) { - g_model.switchWarningStates ^= 0x01; - eeDirty(EE_MODEL); - } - break; - } - } - if (c) { - states >>= 1; - for (uint8_t i=1; i>= 2; -#else - attr = 0; - if (IS_3POS(i-1)) { - c = '0'+(states & 0x03); - states >>= 2; - } - else { - if (states & 0x01) - attr = INVERS; - c = pgm_read_byte(STR_VSWITCHES - 2 + 6 + (3*i)); - states >>= 1; - } - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+2*FW+i*FW, y, c, attr); -#endif - } - } - break; - } - - case ITEM_MODEL_BEEP_CENTER: - lcd_putsLeft(y, STR_BEEPCTR); - for (uint8_t i=0; i0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.externalModule, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1); - if (checkIncDec_Ret) { - g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; - if (g_model.externalModule == MODULE_TYPE_PPM) - g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0; - else - g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_PORT2_CHANNELS(); - } - break; - case 1: - if (IS_MODULE_DSM2(EXTERNAL_MODULE)) - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX); - else - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST); - if (checkIncDec_Ret) { - g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; - g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_PORT2_CHANNELS(); - } - } - } - break; - - case ITEM_MODEL_INTERNAL_MODULE_CHANNELS: - case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS: - case ITEM_MODEL_TRAINER_CHANNELS: - { - uint8_t moduleIdx = (k>=ITEM_MODEL_TRAINER_LABEL ? 2 : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0)); - ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcd_putsLeft(y, STR_CHANNELRANGE); - if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) { - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN, y, STR_CH, m_posHorz==0 ? attr : 0); - lcd_outdezAtt(lcdLastPos, y, moduleData.channelsStart+1, LEFT | (m_posHorz==0 ? attr : 0)); - lcd_putc(lcdLastPos, y, '-'); - lcd_outdezAtt(lcdLastPos + FW+1, y, moduleData.channelsStart+NUM_CHANNELS(moduleIdx), LEFT | (m_posHorz==1 ? attr : 0)); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min(MAX_CHANNELS(moduleIdx), 32-8-moduleData.channelsStart)); - if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.externalModule == MODULE_TYPE_PPM) || (k == ITEM_MODEL_TRAINER_CHANNELS)) - SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx); - break; - } - } - } - break; - } - - case ITEM_MODEL_INTERNAL_MODULE_BIND: - case ITEM_MODEL_EXTERNAL_MODULE_BIND: - case ITEM_MODEL_TRAINER_SETTINGS: - { - uint8_t moduleIdx = (k>=ITEM_MODEL_TRAINER_LABEL ? 2 : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0)); - ModuleData & moduleData = g_model.moduleData[moduleIdx]; - if (IS_MODULE_PPM(moduleIdx)) { - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (moduleData.ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, moduleData.ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, moduleData.ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, moduleData.ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.ppmPulsePol, 1); - break; - } - } - } - else { - horzpos_t l_posHorz = m_posHorz; - uint8_t xOffsetBind = 3*FW; - if (IS_MODULE_XJT(moduleIdx) && IS_D8_RX(moduleIdx)) { - xOffsetBind = 0; - lcd_putsLeft(y, INDENT "Receiver"); - if (attr) l_posHorz += 1; - } - else { - lcd_putsLeft(y, STR_RXNUM); - } - if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) { - if (xOffsetBind) lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId, (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2); - if (attr && l_posHorz==0) { - if (editMode>0 || p1valdiff) { - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId, IS_MODULE_DSM2(moduleIdx) ? 20 : 63); - if (checkIncDec_Ret) { - modelHeaders[g_eeGeneral.currModel].modelId = g_model.header.modelId; - } - } - if (editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) { - checkModelIdUnique(g_eeGeneral.currModel); - } - } - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+7*FW+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); - if (IS_MODULE_XJT(moduleIdx)) { - uint8_t newFlag = 0; - if (attr && l_posHorz>0 && s_editMode>0) { - if (l_posHorz == 1) - newFlag = PXX_SEND_RXNUM; - else if (l_posHorz == 2) { - newFlag = PXX_SEND_RANGECHECK; - } - } - pxxFlag[moduleIdx] = newFlag; - } -#if defined(DSM2) - else { - uint8_t newFlag = 0; - if (attr && l_posHorz>0 && s_editMode>0) { - if (l_posHorz == 1) - newFlag = DSM2_BIND_FLAG; - else if (l_posHorz == 2) { - newFlag = DSM2_RANGECHECK_FLAG; - } - } - dsm2Flag = newFlag; - } -#endif - } - } - break; - } - - case ITEM_MODEL_INTERNAL_MODULE_FAILSAFE: - case ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE: - { - uint8_t moduleIdx = (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0); - ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcd_putsLeft(y, TR_FAILSAFE); - if (IS_MODULE_XJT(moduleIdx)) { - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, m_posHorz==0 ? attr : 0); - if (moduleData.failsafeMode == FAILSAFE_CUSTOM) lcd_putsAtt(MODEL_SETUP_2ND_COLUMN + 10*FW, y, STR_SET, m_posHorz==1 ? attr : 0); - if (attr) { - if (moduleData.failsafeMode != FAILSAFE_CUSTOM) - m_posHorz = 0; - if (m_posHorz==0) { - if (editMode>0 || p1valdiff) { - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.failsafeMode, FAILSAFE_LAST); - if (checkIncDec_Ret) SEND_FAILSAFE_NOW(moduleIdx); - } - } - else if (m_posHorz==1) { - s_editMode = 0; - if (moduleData.failsafeMode==FAILSAFE_CUSTOM && event==EVT_KEY_FIRST(KEY_ENTER)) { - g_moduleIdx = moduleIdx; - pushMenu(menuModelFailsafe); - } - } - else { - lcd_filled_rect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); - } - } - } - break; - } - - case ITEM_MODEL_TRAINER_LABEL: - lcd_putsLeft(y, STR_TRAINER); - break; - - case ITEM_MODEL_TRAINER_MODE: - g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, 0, 1, attr, event); - break; - -#else - - case ITEM_MODEL_PPM1_PROTOCOL: -#if defined(PCBSKY9X) - lcd_putsLeft(y, PSTR("Port1")); -#else - lcd_putsLeft(y, NO_INDENT(STR_PROTO)); -#endif - - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, protocol, m_posHorz<=0 ? attr : 0); - -#if defined(PCBSKY9X) - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, m_posHorz==1 ? attr : 0); - lcd_outdezAtt(lcdLastPos, y, g_model.moduleData[0].channelsStart+1, LEFT | (m_posHorz==1 ? attr : 0)); - lcd_putc(lcdLastPos, y, '-'); - lcd_outdezAtt(lcdLastPos + FW+1, y, g_model.moduleData[0].channelsStart+NUM_PORT1_CHANNELS(), LEFT | (m_posHorz==2 ? attr : 0)); -#else - if (IS_PPM_PROTOCOL(protocol)) { - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN+7*FW, y, STR_NCHANNELS, g_model.ppmNCH+2, m_posHorz!=0 ? attr : 0); - } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } -#endif - - if (attr && (editMode>0 || p1valdiff -#if !defined(PCBSKY9X) - || (!IS_PPM_PROTOCOL(protocol) && !IS_DSM2_PROTOCOL(protocol)) -#endif - )) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.protocol, PROTO_MAX-1); - break; - case 1: -#if defined(PCBSKY9X) - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[0].channelsStart, 32-8-g_model.moduleData[0].channelsCount); - g_model.moduleData[0].ppmFrameLength = max((int8_t)0, g_model.moduleData[0].channelsCount) * 4; - SET_DEFAULT_PPM_FRAME_LENGTH(0); -#else - CHECK_INCDEC_MODELVAR(event, g_model.ppmNCH, -2, 4); - g_model.ppmFrameLength = g_model.ppmNCH * 8; -#endif - break; -#if defined(PCBSKY9X) - case 2: - if (IS_PPM_PROTOCOL(protocol)) { - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].channelsCount, -4, min(8, 32-8-g_model.moduleData[0].channelsStart)); - SET_DEFAULT_PPM_FRAME_LENGTH(0); - } - else - REPEAT_LAST_CURSOR_MOVE(); - break; -#endif - } - } - break; - -#if defined(PCBSKY9X) - case ITEM_MODEL_PPM2_PROTOCOL: - lcd_putsLeft(y, PSTR("Port2")); - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, 0, 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, m_posHorz<=0 ? attr : 0); - lcd_outdezAtt(lcdLastPos, y, g_model.moduleData[1].channelsStart+1, LEFT | (m_posHorz<=0 ? attr : 0)); - lcd_putc(lcdLastPos, y, '-'); - lcd_outdezAtt(lcdLastPos + FW+1, y, g_model.moduleData[1].channelsStart+8+g_model.moduleData[1].channelsCount, LEFT | (m_posHorz!=0 ? attr : 0)); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].channelsStart, 32-8-g_model.moduleData[1].channelsCount); - SET_DEFAULT_PPM_FRAME_LENGTH(1); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].channelsCount, -4, min(8, 32-8-g_model.moduleData[1].channelsStart)); - SET_DEFAULT_PPM_FRAME_LENGTH(1); - break; - } - } - break; - - case ITEM_MODEL_PPM2_PARAMS: - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[1].ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[1].ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[1].ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].ppmPulsePol, 1); - break; - } - } - break; -#endif - - case ITEM_MODEL_PPM1_PARAMS: -#if defined(PCBSKY9X) - if (IS_PPM_PROTOCOL(protocol)) { - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[0].ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[0].ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[0].ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[0].ppmPulsePol, 1); - break; - } - } - } -#else - if (IS_PPM_PROTOCOL(protocol)) { - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.pulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.pulsePol, 1); - break; - } - } - } -#endif -#if defined(DSM2) || defined(PXX) - else if (IS_DSM2_PROTOCOL(protocol) || IS_PXX_PROTOCOL(protocol)) { - if (attr && m_posHorz > 1) { - REPEAT_LAST_CURSOR_MOVE(); // limit 3 column row to 2 colums (Rx_Num and RANGE fields) - } - - lcd_putsLeft(y, STR_RXNUM); - lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId, (m_posHorz<=0 ? attr : 0) | LEADING0|LEFT, 2); - if (attr && (m_posHorz==0 && (editMode>0 || p1valdiff))) { - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId, 99); -#if defined(CPUARM) - if (checkIncDec_Ret) - modelHeaders[g_eeGeneral.currModel].modelId = g_model.header.modelId; -#endif - } - -#if defined(PXX) - if (protocol == PROTO_PXX) { -#if defined(CPUARM) - if (attr && m_posHorz==0 && editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) - checkModelIdUnique(g_eeGeneral.currModel); -#endif - - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_SYNCMENU, m_posHorz!=0 ? attr : 0); - if (attr && m_posHorz>0 && editMode>0) { - // send reset code - pxxFlag[0] = PXX_SEND_RXNUM; - } - } -#endif - -#if defined(DSM2) - if (IS_DSM2_PROTOCOL(protocol)) { - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_MODULE_RANGE, m_posHorz!=0 ? attr : 0); - dsm2Flag = (attr && m_posHorz>0 && editMode>0) ? DSM2_RANGECHECK_FLAG : 0; // [MENU] key toggles range check mode - } -#endif - } -#endif - break; -#endif // defined(PCBTARANIS) - } - } - -#if defined(PCBTARANIS) - if (pxxFlag[INTERNAL_MODULE] == PXX_SEND_RANGECHECK || pxxFlag[EXTERNAL_MODULE] == PXX_SEND_RANGECHECK) { - displayPopup("RSSI: "); - lcd_outdezAtt(16+4*FW, 5*FH, frskyData.rssi[0].value, BOLD); - } -#endif -} - -static uint8_t s_currIdx; - -#if MENU_COLUMNS < 2 - #if LCD_W >= 212 - #define MIXES_2ND_COLUMN (18*FW) - #else - #define MIXES_2ND_COLUMN (12*FW) - #endif -#else - #define MIXES_2ND_COLUMN (9*FW) -#endif - -#if LCD_W >= 212 - #define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90) - #define EXPO_ONE_FP_WIDTH (9*FW) -#else - #define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) - #define EXPO_ONE_FP_WIDTH (5*FW) -#endif - -#if MENU_COLUMNS > 1 -uint8_t editDelay(const xcoord_t x, const uint8_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay) -{ - lcd_puts(x, y, str); - lcd_outdezAtt(x+MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX); - return delay; -} -#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(x, y, event, attr, str, delay) -#else -uint8_t editDelay(const uint8_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay) -{ - lcd_putsLeft(y, str); - lcd_outdezAtt(MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX); - return delay; -} -#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(y, event, attr, str, delay) -#endif - -#if defined(FLIGHT_MODES) - -#if defined(CPUARM) - #define FlightModesType uint16_t -#else - #define FlightModesType uint8_t -#endif - -void displayFlightModes(uint8_t x, uint8_t y, FlightModesType value) -{ - uint8_t p = MAX_PHASES; - do { - --p; - if (!(value & (1< EXPO_ONE_2ND_COLUMN-FW))) - continue; -#endif -#if defined(PCBTARANIS) - LcdFlags flags = 0; - if (attr) { - flags |= INVERS; - if (posHorz==p) flags |= BLINK; - } - if (value & (1<= 212 - -enum FlightModesItems { - ITEM_PHASES_NAME, - ITEM_PHASES_SWITCH, - ITEM_PHASES_TRIMS, - ITEM_PHASES_FADE_IN, - ITEM_PHASES_FADE_OUT, - ITEM_PHASES_COUNT, - ITEM_PHASES_LAST = ITEM_PHASES_COUNT-1 -}; - -void editPhaseTrims(uint8_t x, uint8_t y, uint8_t phase, uint8_t event, uint8_t active) -{ - static uint8_t cursorPos = 0; - - for (uint8_t t=0; t 0) { - if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) - || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { - int16_t v = getRawTrimValue(phase, cur); - if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX; - v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == TRIM_EXTENDED_MAX) v = 0; - setTrimValue(phase, cur, v); - } - } - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - case EVT_ROTARY_BREAK: - if (s_editMode == EDIT_MODIFY_FIELD) { - s_editMode = EDIT_MODIFY_STRING; - cur = 0; - } - else if (cur0) cur--; - break; - case EVT_KEY_BREAK(KEY_RIGHT): - if (cur 0) { posHorz += 2; } - - if (sub=0) { - displayColumnHeader(STR_PHASES_HEADERS, posHorz); - } - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); - uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; - switch(j) - { - case ITEM_PHASES_NAME: - editName(4*FW, y, p->name, sizeof(p->name), event, attr); - break; - - case ITEM_PHASES_SWITCH: - if (k == 0) { - lcd_puts((5+LEN_FP_NAME)*FW+FW/2, y, STR_DEFAULT); - } - else { - putsSwitches((5+LEN_FP_NAME)*FW+FW/2, y, p->swtch, attr); - if (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, -MAX_SWITCH, MAX_SWITCH); - } - break; - - case ITEM_PHASES_TRIMS: - if (k != 0) { - editPhaseTrims((10+LEN_FP_NAME)*FW+FW/2, y, k, event, attr); - } - break; - - case ITEM_PHASES_FADE_IN: - lcd_outdezAtt(29*FW, y, (10/DELAY_STEP)*p->fadeIn, attr|PREC1); - if (active) p->fadeIn = checkIncDec(event, p->fadeIn, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS); - break; - - case ITEM_PHASES_FADE_OUT: - lcd_outdezAtt(34*FW, y, (10/DELAY_STEP)*p->fadeOut, attr|PREC1); - if (active) p->fadeOut = checkIncDec(event, p->fadeOut, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS); - break; - - } - } - } -} - -#else // LCD_W >= 212 - -enum menuModelPhaseItems { - ITEM_MODEL_PHASE_NAME, - ITEM_MODEL_PHASE_SWITCH, - ITEM_MODEL_PHASE_TRIMS, - IF_ROTARY_ENCODERS(ITEM_MODEL_PHASE_ROTARY_ENCODERS) - ITEM_MODEL_PHASE_FADE_IN, - ITEM_MODEL_PHASE_FADE_OUT, -#if defined(GVARS) && !defined(PCBSTD) - ITEM_MODEL_PHASE_GVARS_LABEL, - ITEM_MODEL_PHASE_GV1, - ITEM_MODEL_PHASE_GV2, - ITEM_MODEL_PHASE_GV3, - ITEM_MODEL_PHASE_GV4, - ITEM_MODEL_PHASE_GV5, -#endif - ITEM_MODEL_PHASE_MAX -}; - -void menuModelPhaseOne(uint8_t event) -{ - PhaseData *phase = phaseAddress(s_currIdx); - putsFlightPhase(13*FW, 0, s_currIdx+1, (getFlightPhase()==s_currIdx ? BOLD : 0)); - -#if defined(GVARS) && !defined(PCBSTD) - static const pm_uint8_t mstate_tab_phase1[] PROGMEM = {0, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1}; - static const pm_uint8_t mstate_tab_others[] PROGMEM = {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0, 0, (uint8_t)-1, 2, 2, 2, 2, 2}; - - if (!check(event, 0, NULL, 0, (s_currIdx == 0) ? mstate_tab_phase1 : mstate_tab_others, DIM(mstate_tab_others)-1, ITEM_MODEL_PHASE_MAX - 1 - (s_currIdx==0 ? (ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH) : 0))) return; - - TITLE(STR_MENUFLIGHTPHASE); - - #define PHASE_ONE_FIRST_LINE (1+1*FH) -#else - SUBMENU(STR_MENUFLIGHTPHASE, 3 + (s_currIdx==0 ? 0 : 2 + (bool)NUM_ROTARY_ENCODERS), {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0/*, 0*/}); - #define PHASE_ONE_FIRST_LINE (1+1*FH) -#endif - - int8_t sub = m_posVert; - int8_t editMode = s_editMode; - -#if defined(GVARS) && !defined(PCBSTD) - if (s_currIdx == 0 && sub>=ITEM_MODEL_PHASE_SWITCH) sub += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH; - - for (uint8_t k=0; k=ITEM_MODEL_PHASE_SWITCH) i += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH; - uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); -#else - for (uint8_t i=0, k=0, y=PHASE_ONE_FIRST_LINE; i0 ? BLINK|INVERS : INVERS) : 0); -#endif - switch(i) { - case ITEM_MODEL_PHASE_NAME: - editSingleName(MIXES_2ND_COLUMN, y, STR_PHASENAME, phase->name, sizeof(phase->name), event, attr); - break; - case ITEM_MODEL_PHASE_SWITCH: - phase->swtch = switchMenuItem(MIXES_2ND_COLUMN, y, phase->swtch, attr, event); - break; - case ITEM_MODEL_PHASE_TRIMS: - lcd_putsLeft(y, STR_TRIMS); - for (uint8_t t=0; t0) || p1valdiff)) { - int16_t v = getRawTrimValue(s_currIdx, t); - if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX; - v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == TRIM_EXTENDED_MAX) v = 0; - setTrimValue(s_currIdx, t, v); - } - } - } - break; - -#if ROTARY_ENCODERS > 0 - case ITEM_MODEL_PHASE_ROTARY_ENCODERS: - lcd_putsLeft(y, STR_ROTARY_ENCODER); - for (uint8_t t=0; t0) || p1valdiff)) { -#if ROTARY_ENCODERS > 2 - int16_t v; - if(t < (NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)) - v = phaseAddress(s_currIdx)->rotaryEncoders[t]; - else - v = g_model.rotaryEncodersExtra[s_currIdx][t-(NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)]; -#else - int16_t v = phaseAddress(s_currIdx)->rotaryEncoders[t]; -#endif - if (v < ROTARY_ENCODER_MAX) v = ROTARY_ENCODER_MAX; - v = checkIncDec(event, v, ROTARY_ENCODER_MAX, ROTARY_ENCODER_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == ROTARY_ENCODER_MAX) v = 0; -#if ROTARY_ENCODERS > 2 - if (t < (NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)) - phaseAddress(s_currIdx)->rotaryEncoders[t] = v; - else - g_model.rotaryEncodersExtra[s_currIdx][t-(NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)] = v; -#else - phaseAddress(s_currIdx)->rotaryEncoders[t] = v; -#endif - } - } - } - break; -#endif - - case ITEM_MODEL_PHASE_FADE_IN: - phase->fadeIn = EDIT_DELAY(0, y, event, attr, STR_FADEIN, phase->fadeIn); - break; - - case ITEM_MODEL_PHASE_FADE_OUT: - phase->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, phase->fadeOut); - break; - -#if defined(GVARS) && !defined(PCBSTD) - case ITEM_MODEL_PHASE_GVARS_LABEL: - lcd_putsLeft(y, STR_GLOBAL_VARS); - break; - - default: - { - uint8_t idx = i-ITEM_MODEL_PHASE_GV1; - uint8_t posHorz = m_posHorz; - if (attr && posHorz > 0 && s_currIdx==0) posHorz++; - - putsStrIdx(INDENT_WIDTH, y, STR_GV, idx+1); - - editName(4*FW, y, g_model.gvars[idx].name, LEN_GVAR_NAME, event, posHorz==0 ? attr : 0); - - int16_t v = phase->gvars[idx]; - if (v > GVAR_MAX) { - uint8_t p = v - GVAR_MAX - 1; - if (p >= s_currIdx) p++; - putsFlightPhase(11*FW, y, p+1, posHorz==1 ? attr : 0); - } - else { - lcd_putsAtt(11*FW, y, STR_OWN, posHorz==1 ? attr : 0); - } - if (attr && s_currIdx>0 && posHorz==1 && (editMode>0 || p1valdiff)) { - if (v < GVAR_MAX) v = GVAR_MAX; - v = checkIncDec(event, v, GVAR_MAX, GVAR_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == GVAR_MAX) v = 0; - phase->gvars[idx] = v; - } - } - - uint8_t p = getGVarFlightPhase(s_currIdx, idx); - lcd_outdezAtt(21*FW, y, GVAR_VALUE(idx, p), posHorz==2 ? attr : 0); - if (attr && posHorz==2 && ((editMode>0) || p1valdiff)) { - GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -GVAR_LIMIT, GVAR_LIMIT, EE_MODEL); - } - - break; - } -#endif - } - } -} - -#if defined(ROTARY_ENCODERS) - #if ROTARY_ENCODERS > 2 - #define NAME_OFS (-4-12) - #define SWITCH_OFS (-FW/2-2-13) - #define TRIMS_OFS (-FW/2-4-15) - #define ROTARY_ENC_OFS (0) - #else - #define NAME_OFS (-4) - #define SWITCH_OFS (-FW/2-2) - #define TRIMS_OFS (-FW/2-4) - #define ROTARY_ENC_OFS (2) - #endif -#else - #define NAME_OFS 0 - #define SWITCH_OFS (FW/2) - #define TRIMS_OFS (FW/2) -#endif - -void menuModelFlightModesAll(uint8_t event) -{ - SIMPLE_MENU(STR_MENUFLIGHTPHASES, menuTabModel, e_FlightModesAll, 1+MAX_PHASES+1); - - int8_t sub = m_posVert - 1; - - switch (event) { - CASE_EVT_ROTARY_BREAK - case EVT_KEY_FIRST(KEY_ENTER): - if (sub == MAX_PHASES) { - s_editMode = 0; - trimsCheckTimer = 200; // 2 seconds - } - // no break - case EVT_KEY_FIRST(KEY_RIGHT): - if (sub >= 0 && sub < MAX_PHASES) { - s_currIdx = sub; - pushMenu(menuModelPhaseOne); - } - break; - } - - uint8_t att; - for (uint8_t i=0; i(LCD_LINES-1)*FH+1) continue; -#else - uint8_t y = 1 + (i+1)*FH; -#endif - att = (i==sub ? INVERS : 0); - PhaseData *p = phaseAddress(i); -#if ROTARY_ENCODERS > 2 - putsFlightPhase(0, y, i+1, att|CONDENSED|(getFlightPhase()==i ? BOLD : 0)); -#else - putsFlightPhase(0, y, i+1, att|(getFlightPhase()==i ? BOLD : 0)); -#endif - - lcd_putsnAtt(4*FW+NAME_OFS, y, p->name, sizeof(p->name), ZCHAR); - if (i == 0) { - lcd_puts((5+LEN_FP_NAME)*FW+SWITCH_OFS, y, STR_DEFAULT); - } - else { - putsSwitches((5+LEN_FP_NAME)*FW+SWITCH_OFS, y, p->swtch, 0); - for (uint8_t t=0; tfadeIn || p->fadeOut) - lcd_putc(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, (p->fadeIn && p->fadeOut) ? '*' : (p->fadeIn ? 'I' : 'O')); - - } - -#if defined(CPUARM) - if (s_pgOfs != MAX_PHASES-(LCD_LINES-2)) return; -#endif - - lcd_putsLeft((LCD_LINES-1)*FH+1, STR_CHECKTRIMS); - putsFlightPhase(OFS_CHECKTRIMS, (LCD_LINES-1)*FH+1, s_perout_flight_phase+1); - if (sub==MAX_PHASES && !trimsCheckTimer) { - lcd_status_line(); - } -} - -#endif // defined(PCBTARANIS) - -#else // defined(FLIGHT_MODES) - -#define displayFlightModes(...) - -#endif - -#if defined(HELI) - -enum menuModelHeliItems { - ITEM_HELI_SWASHTYPE, - ITEM_HELI_COLLECTIVE, - ITEM_HELI_SWASHRING, - ITEM_HELI_ELEDIRECTION, - ITEM_HELI_AILDIRECTION, - ITEM_HELI_COLDIRECTION -}; - -#if LCD_W >= 212 - #define HELI_PARAM_OFS (23*FW) -#else - #define HELI_PARAM_OFS (14*FW) -#endif - -void menuModelHeli(uint8_t event) -{ - SIMPLE_MENU(STR_MENUHELISETUP, menuTabModel, e_Heli, 7); - - uint8_t sub = m_posVert - 1; - - for (uint8_t i=0; i<6; i++) { - uint8_t y = 1 + 1*FH + i*FH; - uint8_t attr = (sub == i ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); - switch(i) { - case ITEM_HELI_SWASHTYPE: - g_model.swashR.type = selectMenuItem(HELI_PARAM_OFS, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_NUM, attr, event); - break; - - case ITEM_HELI_COLLECTIVE: -#if defined(PCBTARANIS) - lcd_putsLeft(y, STR_COLLECTIVE); - if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH); -#else - g_model.swashR.collectiveSource = selectMenuItem(HELI_PARAM_OFS, y, STR_COLLECTIVE, NULL, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH, attr, event); -#endif - putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.collectiveSource, attr); - break; - - case ITEM_HELI_SWASHRING: - lcd_putsLeft(y, STR_SWASHRING); - lcd_outdezAtt(HELI_PARAM_OFS, y, g_model.swashR.value, LEFT|attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.swashR.value, 100); - break; - - case ITEM_HELI_ELEDIRECTION: - g_model.swashR.invertELE = selectMenuItem(HELI_PARAM_OFS, y, STR_ELEDIRECTION, STR_MMMINV, g_model.swashR.invertELE, 0, 1, attr, event); - break; - - case ITEM_HELI_AILDIRECTION: - g_model.swashR.invertAIL = selectMenuItem(HELI_PARAM_OFS, y, STR_AILDIRECTION, STR_MMMINV, g_model.swashR.invertAIL, 0, 1, attr, event); - break; - - case ITEM_HELI_COLDIRECTION: - g_model.swashR.invertCOL = selectMenuItem(HELI_PARAM_OFS, y, STR_COLDIRECTION, STR_MMMINV, g_model.swashR.invertCOL, 0, 1, attr, event); - break; - } - } -} -#endif - -typedef int16_t (*FnFuncP) (int16_t x); - -int16_t expoFn(int16_t x) -{ - ExpoData *ed = expoAddress(s_currIdx); - int16_t anas[NUM_INPUTS] = {0}; -#if defined(PCBTARANIS) - applyExpos(anas, e_perout_mode_inactive_phase, ed->srcRaw, x); -#else - anas[ed->chn] = x; - applyExpos(anas, e_perout_mode_inactive_phase); -#endif - return anas[ed->chn]; -} - -void DrawFunction(FnFuncP fn, uint8_t offset=0) -{ - lcd_vlineStip(X0-offset, 0, LCD_H, 0xee); - lcd_hlineStip(X0-WCHART-offset, Y0, WCHART*2, 0xee); - - uint8_t prev_yv = 255; - - for (int8_t xv=-WCHART; xv<=WCHART; xv++) { - uint8_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/WCHART))) / 2 * (LCD_H-1) / RESX); - if (prev_yv != 255) { - if (abs((int8_t)yv-prev_yv) <= 1) { - lcd_plot(X0+xv-offset-1, prev_yv, FORCE); - } - else { - uint8_t tmp = (prev_yv < yv ? 0 : 1); - lcd_vline(X0+xv-offset-1, yv+tmp, prev_yv-yv); - } - } - prev_yv = yv; - } -} - -#if defined(CURVES) -static uint8_t s_curveChan; -int16_t curveFn(int16_t x) -{ - return applyCustomCurve(x, s_curveChan); -} - -struct point_t { - uint8_t x; - uint8_t y; -}; - -point_t getPoint(uint8_t i) -{ - point_t result = {0, 0}; -#if defined(PCBTARANIS) - CurveInfo &crv = g_model.curves[s_curveChan]; - int8_t *points = curveAddress(s_curveChan); - bool custom = (crv.type == CURVE_TYPE_CUSTOM); - uint8_t count = 5+crv.points; -#else - CurveInfo crv = curveInfo(s_curveChan); - int8_t *points = crv.crv; - bool custom = crv.custom; - uint8_t count = crv.points; -#endif - if (i < count) { -#if defined(PCBTARANIS) - result.x = X0-1-WCHART+i*WCHART*2/(count-1); -#else - result.x = X0-1-WCHART+i*WCHART/(count/2); -#endif - result.y = (LCD_H-1) - (100 + points[i]) * (LCD_H-1) / 200; - if (custom && i>0 && i g_model.points + sizeof(g_model.points)) { - AUDIO_WARNING2(); - return false; - } - - int8_t *nextCrv = curveAddress(index+1); - memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+curveEnd[MAX_CURVES-1]-curveEnd[index]); - if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift); - while (index NUM_POINTS-5*MAX_CURVES) { - AUDIO_WARNING2(); - return false; - } - - int8_t *crv = curveAddress(index); - if (shift < 0) { - for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(3*FH+1, STR_TYPE); - lcd_putsiAtt(INDENT_WIDTH, 4*FH+1, "\010StandardCustom\0", crv.type, attr); - if (attr) { - uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST); - if (newType != crv.type) { - for (int i=1; i<4+crv.points; i++) - points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i*200/(4+crv.points)), s_curveChan)); - moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3+crv.points : -3-crv.points); - if (newType == CURVE_TYPE_CUSTOM) { - for (int i=0; i<3+crv.points; i++) - points[5+crv.points+i] = -100 + ((i+1)*200) / (4+crv.points); - } - crv.type = newType; - } - } - - attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(5*FH+1, "Count"); - lcd_outdezAtt(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 6*FH+1, PSTR("pts"), attr); - if (attr) { - int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts - if (checkIncDec_Ret) { - int8_t newPoints[MAX_POINTS]; - newPoints[0] = points[0]; - newPoints[4+count] = points[4+crv.points]; - for (int i=1; i<4+count; i++) - newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + (i*200) / (4+count)), s_curveChan)); - moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM?2:1)); - for (int i=0; i<5+count; i++) { - points[i] = newPoints[i]; - if (crv.type == CURVE_TYPE_CUSTOM && i!=0 && i!=4+count) - points[5+count+i-1] = -100 + (i*200) / (4+count); - } - crv.points = count; - } - } - - lcd_putsLeft(7*FH+1, PSTR("Smooth")); - menu_lcd_onoff(7*FW, 7*FH+1, crv.smooth, m_posVert==3 ? INVERS : 0); - if (m_posVert==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1); - - switch(event) { - case EVT_ENTRY: - pointsOfs = 0; - SET_SCROLLBAR_X(0); - break; - case EVT_KEY_LONG(KEY_ENTER): - if (m_posVert > 1) { - killEvents(event); - MENU_ADD_ITEM(STR_CURVE_PRESET); - MENU_ADD_ITEM(STR_MIRROR); - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onCurveOneMenu; - } - break; - case EVT_KEY_LONG(KEY_MENU): - pushMenu(menuChannelsView); - killEvents(event); - return; - } - - DrawCurve(FW); - - uint8_t posY = FH+1; - attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); - for (uint8_t i=0; i<5+crv.points; i++) { - point_t point = getPoint(i); - uint8_t selectionMode = 0; - if (crv.type==CURVE_TYPE_CUSTOM) { - if (m_posVert==4+2*i || (i==5+crv.points-1 && m_posVert==4+5+crv.points+5+crv.points-2-1)) - selectionMode = 2; - else if (i>0 && m_posVert==3+2*i) - selectionMode = 1; - } - else if (m_posVert == 4+i) { - selectionMode = 2; - } - - if (i>=pointsOfs && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; - lcd_outdezAtt(6+8*FW, posY, i+1, LEFT); - lcd_outdezAtt(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); - lcd_outdezAtt(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); - posY += FH; - } - - if (selectionMode > 0) { - // do selection square - lcd_filled_rect(point.x-FW-1, point.y-2, 5, 5, SOLID, FORCE); - lcd_filled_rect(point.x-FW, point.y-1, 3, 3, SOLID); - if (s_editMode > 0) { - if (selectionMode == 1) - CHECK_INCDEC_MODELVAR(event, points[5+crv.points+i-1], i==1 ? -100 : points[5+crv.points+i-2], i==5+crv.points-2 ? 100 : points[5+crv.points+i]); // edit X - else if (selectionMode == 2) - CHECK_INCDEC_MODELVAR(event, points[i], -100, 100); - } - if (i < pointsOfs) - pointsOfs = i; - else if (i > pointsOfs+6) - pointsOfs = i-6; - } - } -} -#else -void menuModelCurveOne(uint8_t event) -{ - TITLE(STR_MENUCURVE); - lcd_outdezAtt(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT); - DISPLAY_PROGRESS_BAR(20*FW+1); - - CurveInfo crv = curveInfo(s_curveChan); - - switch(event) { - case EVT_ENTRY: - s_editMode = 1; - break; - CASE_EVT_ROTARY_BREAK - case EVT_KEY_BREAK(KEY_ENTER): - if (s_editMode <= 0) - m_posHorz = 0; - if (s_editMode == 1 && crv.custom) - s_editMode = 2; - else - s_editMode = 1; - break; - case EVT_KEY_LONG(KEY_ENTER): - if (s_editMode <= 0) { - if (int8_t(++m_posHorz) > 4) - m_posHorz = -4; - for (uint8_t i=0; i 0) { - if (--s_editMode == 0) - m_posHorz = 0; - } - else { - popMenu(); - } - break; - - /* CASE_EVT_ROTARY_LEFT */ - case EVT_KEY_REPT(KEY_LEFT): - case EVT_KEY_FIRST(KEY_LEFT): - if (s_editMode==1 && m_posHorz>0) m_posHorz--; - if (s_editMode <= 0) { - if (crv.custom) { - moveCurve(s_curveChan, -crv.points+2); - } - else if (crv.points > MIN_POINTS) { - moveCurve(s_curveChan, -1, (crv.points+1)/2); - } - else { - AUDIO_WARNING2(); - } - return; - } - break; - - /* CASE_EVT_ROTARY_RIGHT */ - case EVT_KEY_REPT(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_RIGHT): - if (s_editMode==1 && m_posHorz<(crv.points-1)) m_posHorz++; - if (s_editMode <= 0) { - if (!crv.custom) { - moveCurve(s_curveChan, crv.points-2, crv.points); - } - else if (crv.points < MAX_POINTS) { - if (moveCurve(s_curveChan, 1)) { - for (int8_t i=crv.points+crv.points-2; i>=0; i--) { - if (i%2) - crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2; - else - crv.crv[i] = crv.crv[i/2]; - } - } - } - else { - AUDIO_WARNING2(); - } - } - break; - } - - lcd_putsLeft(7*FH, STR_TYPE); - uint8_t attr = (s_editMode <= 0 ? INVERS : 0); - lcd_outdezAtt(5*FW-2, 7*FH, crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 7*FH, crv.custom ? PSTR("pt'") : PSTR("pt"), attr); - - DrawCurve(); - - if (s_editMode>0) { - uint8_t i = m_posHorz; - point_t point = getPoint(i); - - if (s_editMode==1 || !BLINK_ON_PHASE) { - // do selection square - lcd_filled_rect(point.x-1, point.y-2, 5, 5, SOLID, FORCE); - lcd_filled_rect(point.x, point.y-1, 3, 3, SOLID); - } - - int8_t x = -100 + 200*i/(crv.points-1); - if (crv.custom && i>0 && i=0; i--) { - ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw); - if (ch != 0) { - count++; - } - } - return count; -} - -bool reachExpoMixCountLimit(uint8_t expo) -{ - // check mixers count limit - if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) { - POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER); - return true; - } - return false; -} - -void deleteExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); - } - else { - MixData *mix = mixAddress(idx); - memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData)); - } - resumeMixerCalculations(); - eeDirty(EE_MODEL); -} - -// TODO avoid this global s_currCh on ARM boards ... -int8_t s_currCh; -void insertExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(expo, sizeof(ExpoData)); -#if defined(PCBTARANIS) - expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); - expo->curve.type = CURVE_REF_EXPO; -#else - expo->mode = 3; // pos&neg -#endif - expo->chn = s_currCh - 1; - expo->weight = 100; - } - else { - MixData *mix = mixAddress(idx); - memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - memclear(mix, sizeof(MixData)); - mix->destCh = s_currCh-1; -#if defined(PCBTARANIS) - mix->srcRaw = s_currCh; - if (!isSourceAvailable(mix->srcRaw)) - mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); -#else - mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); -#endif - mix->weight = 100; - } - resumeMixerCalculations(); - eeDirty(EE_MODEL); -} - -void copyExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - } - else { - MixData *mix = mixAddress(idx); - memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - } - resumeMixerCalculations(); - eeDirty(EE_MODEL); -} - -void memswap(void *a, void *b, uint8_t size) -{ - uint8_t *x = (uint8_t*)a; - uint8_t *y = (uint8_t*)b; - uint8_t temp ; - - while (size--) { - temp = *x; - *x++ = *y; - *y++ = temp; - } -} - -bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up) -{ - void *x, *y; - uint8_t size; - int8_t tgt_idx = (up ? idx-1 : idx+1); - - if (expo) { - x = (ExpoData *)expoAddress(idx); - - if (tgt_idx < 0) { - if (((ExpoData *)x)->chn == 0) - return false; - ((ExpoData *)x)->chn--; - return true; - } - - if (tgt_idx == MAX_EXPOS) { - if (((ExpoData *)x)->chn == NUM_STICKS-1) - return false; - ((ExpoData *)x)->chn++; - return true; - } - - y = (ExpoData *)expoAddress(tgt_idx); - if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) { - if (up) { - if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--; - else return false; - } - else { - if (((ExpoData *)x)->chnchn++; - else return false; - } - return true; - } - - size = sizeof(ExpoData); - } - else { - x = (MixData *)mixAddress(idx); - - if (tgt_idx < 0) { - if (((MixData *)x)->destCh == 0) - return false; - ((MixData *)x)->destCh--; - return true; - } - - if (tgt_idx == MAX_MIXERS) { - if (((MixData *)x)->destCh == NUM_CHNOUT-1) - return false; - ((MixData *)x)->destCh++; - return true; - } - - y = (MixData *)mixAddress(tgt_idx); - uint8_t destCh = ((MixData *)x)->destCh; - if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) { - if (up) { - if (destCh>0) ((MixData *)x)->destCh--; - else return false; - } - else { - if (destChdestCh++; - else return false; - } - return true; - } - - size = sizeof(MixData); - } - - pauseMixerCalculations(); - memswap(x, y, size); - resumeMixerCalculations(); - - idx = tgt_idx; - return true; -} - -enum ExposFields { - CASE_PCBTARANIS(EXPO_FIELD_INPUT_NAME) - IF_CPUARM(EXPO_FIELD_NAME) - CASE_PCBTARANIS(EXPO_FIELD_SOURCE) - CASE_PCBTARANIS(EXPO_FIELD_SCALE) - EXPO_FIELD_WEIGHT, - CASE_PCBTARANIS(EXPO_FIELD_OFFSET) - CASE_9X(EXPO_FIELD_EXPO) - IF_CURVES(EXPO_FIELD_CURVE) - IF_FLIGHT_MODES(EXPO_FIELD_FLIGHT_PHASE) - EXPO_FIELD_SWITCH, - CASE_9X(EXPO_FIELD_SIDE) - CASE_PCBTARANIS(EXPO_FIELD_TRIM) - EXPO_FIELD_MAX -}; - -#if defined(PCBTARANIS) - #define CURVE_ROWS 1 -#else - #define CURVE_ROWS 0 -#endif - -void menuModelExpoOne(uint8_t event) -{ -#if defined(PCBTARANIS) - if (event == EVT_KEY_LONG(KEY_MENU)) { - pushMenu(menuChannelsView); - killEvents(event); - return; - } -#endif - - ExpoData *ed = expoAddress(s_currIdx); -#if defined(PCBTARANIS) - putsMixerSource(7*FW+FW/2, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); -#else - putsMixerSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0); -#endif - - SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {CASE_PCBTARANIS(0) IF_CPUARM(0) CASE_PCBTARANIS(0) CASE_PCBTARANIS((ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW)) 0, CASE_PCBTARANIS(0) CASE_9X(0) IF_CURVES(CURVE_ROWS) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); - - SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); - - int8_t sub = m_posVert; - - uint8_t y = FH+1; - -#if defined(PCBTARANIS) - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - switch(i) - { -#if defined(PCBTARANIS) - case EXPO_FIELD_INPUT_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN, y, "Input Name", g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); - break; -#endif - -#if defined(CPUARM) - case EXPO_FIELD_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN-IF_9X(sizeof(ed->name)*FW), y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); - break; -#endif - -#if defined(PCBTARANIS) - case EXPO_FIELD_SOURCE: - lcd_putsLeft(y, NO_INDENT(STR_SOURCE)); - putsMixerSource(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); - break; - - case EXPO_FIELD_SCALE: - lcd_putsLeft(y, STR_SCALE); - putsTelemetryChannel(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw - MIXSRC_FIRST_TELEM, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr); - if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL, NULL); - break; -#endif - - case EXPO_FIELD_WEIGHT: - lcd_putsLeft(y, STR_WEIGHT); - ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, IF_PCBTARANIS(LEFT)|attr, 0, event); - break; - -#if defined(PCBTARANIS) - case EXPO_FIELD_OFFSET: - lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); - ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); - break; -#endif - -#if !defined(PCBTARANIS) - case EXPO_FIELD_EXPO: - lcd_putsLeft(y, STR_EXPO); - if (ed->curveMode==MODE_EXPO || ed->curveParam==0) { - ed->curveMode = MODE_EXPO; - ed->curveParam = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, 0, event); - } - else { - lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); - } - break; -#endif - -#if defined(CURVES) - case EXPO_FIELD_CURVE: - lcd_putsLeft(y, STR_CURVE); -#if defined(PCBTARANIS) - editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); -#else - if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) { - putsCurve(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr); - if (attr) { - CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1); - if (ed->curveParam) ed->curveMode = MODE_CURVE; - if (ed->curveParam>=CURVE_BASE && event==EVT_KEY_LONG(KEY_ENTER)) { - s_curveChan = ed->curveParam - CURVE_BASE; - pushMenu(menuModelCurveOne); - } - } - } - else { - lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); - } -#endif - break; -#endif - -#if defined(FLIGHT_MODES) - case EXPO_FIELD_FLIGHT_PHASE: - ed->phases = editFlightModes(EXPO_ONE_2ND_COLUMN-IF_9X(EXPO_ONE_FP_WIDTH), y, event, ed->phases, attr); - break; -#endif - - case EXPO_FIELD_SWITCH: - ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN-IF_9X(3*FW), y, ed->swtch, attr, event); - break; - -#if !defined(PCBTARANIS) - case EXPO_FIELD_SIDE: - ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); - break; -#endif - -#if defined(PCBTARANIS) - case EXPO_FIELD_TRIM: - uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); - int8_t carryTrim = -ed->carryTrim; - lcd_putsLeft(y, STR_TRIM); - lcd_putsiAtt(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); - if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - break; -#endif - } - y += FH; - } - - DrawFunction(expoFn); - -#if defined(PCBTARANIS) - int x512 = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x512, 0); - if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); - x512 = limit(-1024, x512, 1024); - } - else { - lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); - } - int y512 = expoFn(x512); - lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); -#else - int16_t x512 = calibratedStick[ed->chn]; - lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto100(x512), 0); - int16_t y512 = expoFn(x512); - lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0); -#endif - - x512 = X0+x512/(RESXu/WCHART); -#if defined(CPUARM) - y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; -#else - y512 = (LCD_H-1) - (uint16_t)((y512+RESX)/2) * (LCD_H-1) / RESX; -#endif - - lcd_vline(x512, y512-3, 3*2+1); - lcd_hline(x512-3, y512, 3*2+1); -} - -enum MixFields { - IF_CPUARM(MIX_FIELD_NAME) - MIX_FIELD_SOURCE, - MIX_FIELD_WEIGHT, - MIX_FIELD_OFFSET, - CASE_9X(MIX_FIELD_TRIM) - IF_CURVES(MIX_FIELD_CURVE) - IF_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE) - MIX_FIELD_SWITCH, - MIX_FIELD_WARNING, - MIX_FIELD_MLTPX, - MIX_FIELD_DELAY_UP, - MIX_FIELD_DELAY_DOWN, - MIX_FIELD_SLOW_UP, - MIX_FIELD_SLOW_DOWN, - MIX_FIELD_COUNT -}; - -void gvarWeightItem(xcoord_t x, uint8_t y, MixData *md, uint8_t attr, uint8_t event) -{ - u_int8int16_t weight; - MD_WEIGHT_TO_UNION(md, weight); - weight.word = GVAR_MENU_ITEM(x, y, weight.word, -500, 500, attr, 0, event); - MD_UNION_TO_WEIGHT(weight, md); -} - -void menuModelMixOne(uint8_t event) -{ -#if defined(PCBTARANIS) - if (event == EVT_KEY_LONG(KEY_MENU)) { - pushMenu(menuChannelsView); - killEvents(event); - return; - } -#endif - - TITLE(s_currCh ? STR_INSERTMIX : STR_EDITMIX); - MixData *md2 = mixAddress(s_currIdx) ; - putsChn(lcdLastPos+1*FW, 0, md2->destCh+1,0); - -#if defined(ROTARY_ENCODERS) -#if defined(CURVES) - if ((m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) || (m_posVert == MIX_FIELD_CURVE && md2->curveMode == MODE_CURVE)) -#else - if (m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) -#endif - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(0) IF_CURVES(0) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}) - else - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); -#else - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); -#endif - -#if MENU_COLUMNS > 1 - lcd_vline(MENU_COLUMN2_X-4, FH+1, LCD_H-FH-1); -#endif - - int8_t sub = m_posVert; - int8_t editMode = s_editMode; - - for (uint8_t k=0; k 1 - uint8_t y; - uint8_t COLUMN_X; - if (k >= LCD_LINES-1) { - y = 1 + (k-LCD_LINES+2)*FH; - COLUMN_X = MENU_COLUMN2_X; - } - else { - y = 1 + (k+1)*FH; - COLUMN_X = 0; - } - int8_t i = k; -#else - uint8_t y = 1 + (k+1)*FH; - int8_t i = k + s_pgOfs; -#endif - - uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); - switch(i) { -#if defined(CPUARM) - case MIX_FIELD_NAME: - editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr); - break; -#endif - case MIX_FIELD_SOURCE: - lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_SOURCE)); - putsMixerSource(COLUMN_X+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); - if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); - break; - case MIX_FIELD_WEIGHT: - lcd_putsColumnLeft(COLUMN_X, y, STR_WEIGHT); - gvarWeightItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); - break; - case MIX_FIELD_OFFSET: - { - lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_OFFSET)); - u_int8int16_t offset; - MD_OFFSET_TO_UNION(md2, offset); - offset.word = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_NEG, GV_RANGELARGE, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); - break; - } - -#if !defined(PCBTARANIS) - case MIX_FIELD_TRIM: - { - uint8_t not_stick = (md2->srcRaw > NUM_STICKS); - int8_t carryTrim = -md2->carryTrim; - lcd_putsColumnLeft(COLUMN_X, y, STR_TRIM); -#if LCD_W >= 212 && defined(TRANSLATIONS_FR) - lcd_putsiAtt((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+11*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); -#else - lcd_putsiAtt((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+6*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); -#endif - if (attr && m_posHorz==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - if (!not_stick) { - lcd_puts(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX); - menu_lcd_onoff(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, !md2->noExpo, m_posHorz==1 ? attr : 0); - if (attr && m_posHorz==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1); - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - } -#endif - -#if defined(CURVES) - case MIX_FIELD_CURVE: - { - lcd_putsColumnLeft(COLUMN_X, y, STR_CURVE); -#if defined(PCBTARANIS) - editCurveRef(COLUMN_X+MIXES_2ND_COLUMN, y, md2->curve, event, attr); -#else - int8_t curveParam = md2->curveParam; - if (md2->curveMode == MODE_CURVE) { - putsCurve(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr); - if (attr) { - if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){ - s_curveChan = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE); - pushMenu(menuModelCurveOne); - } - else { - CHECK_INCDEC_MODELVAR(event, md2->curveParam, -MAX_CURVES, CURVE_BASE+MAX_CURVES-1); - if (md2->curveParam == 0) - md2->curveMode = MODE_DIFFERENTIAL; -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - MOVE_CURSOR_FROM_HERE(); -#else - m_posHorz = 0; -#endif - } - } - } - else { - lcd_putsAtt(COLUMN_X+MIXES_2ND_COLUMN, y, PSTR("Diff"), m_posHorz==0 ? attr : 0); - md2->curveParam = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, curveParam, -100, 100, LEFT|(m_posHorz==1 ? attr : 0), 0, editMode>0 ? event : 0); - if (attr && editMode>0 && m_posHorz==0) { - int8_t tmp = 0; - CHECK_INCDEC_MODELVAR(event, tmp, -1, 1); - if (tmp != 0) { - md2->curveMode = MODE_CURVE; - md2->curveParam = tmp; - } - } - } -#endif - break; - } -#endif -#if defined(FLIGHT_MODES) - case MIX_FIELD_FLIGHT_PHASE: - md2->phases = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->phases, attr); - break; -#endif - case MIX_FIELD_SWITCH: - md2->swtch = switchMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event); - break; - case MIX_FIELD_WARNING: - lcd_putsColumnLeft(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING); - if (md2->mixWarn) - lcd_outdezAtt(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT); - else - lcd_putsAtt(COLUMN_X+MIXES_2ND_COLUMN, y, STR_OFF, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3); - break; - case MIX_FIELD_MLTPX: - md2->mltpx = selectMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event); - break; - case MIX_FIELD_DELAY_UP: - md2->delayUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYUP, md2->delayUp); - break; - case MIX_FIELD_DELAY_DOWN: - md2->delayDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYDOWN, md2->delayDown); - break; - case MIX_FIELD_SLOW_UP: - md2->speedUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWUP, md2->speedUp); - break; - case MIX_FIELD_SLOW_DOWN: - md2->speedDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWDOWN, md2->speedDown); - break; - } - } -} - -static uint8_t s_maxLines = 8; -static uint8_t s_copySrcIdx; -static uint8_t s_copySrcCh; - -#define _STR_MAX(x) PSTR("/" #x) -#define STR_MAX(x) _STR_MAX(x) - -#define MIX_LINE_SRC_POS 4*FW-1 - -#if LCD_W >= 212 - #define EXPO_LINE_WEIGHT_POS 8*FW+1 - #define EXPO_LINE_SRC_POS 9*FW-2 - #define EXPO_LINE_CURVE_POS 12*FW+4 - #define EXPO_LINE_SWITCH_POS 17*FW-1 - #define EXPO_LINE_SELECT_POS 5*FW+2 - #define EXPO_LINE_FM_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH-FW-1 - #define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH - #define MIX_LINE_WEIGHT_POS 11*FW+5 - #define MIX_LINE_CURVE_POS 12*FW+4 - #define MIX_LINE_SWITCH_POS 16*FW+1 - #define MIX_LINE_DELAY_POS 19*FW+2 -#elif defined(CPUARM) - #define EXPO_LINE_WEIGHT_POS 7*FW-1 - #define EXPO_LINE_EXPO_POS 10*FW+5 - #define EXPO_LINE_SWITCH_POS 11*FW+2 - #define EXPO_LINE_SIDE_POS 14*FW+2 - #define EXPO_LINE_SELECT_POS 24 - #define EXPO_LINE_FM_POS - #define EXPO_LINE_NAME_POS LCD_W-sizeof(ed->name)*FW-MENUS_SCROLLBAR_WIDTH - #define MIX_LINE_WEIGHT_POS 11*FW+3 - #define MIX_LINE_CURVE_POS 12*FW+2 - #define MIX_LINE_SWITCH_POS 16*FW - #define MIX_LINE_DELAY_POS 19*FW+7 -#else - #define EXPO_LINE_WEIGHT_POS 7*FW-1 - #define EXPO_LINE_EXPO_POS 11*FW - #define EXPO_LINE_SWITCH_POS 11*FW+4 - #if MAX_PHASES == 6 - #define EXPO_LINE_SIDE_POS 15*FW - #else - #define EXPO_LINE_SIDE_POS 15*FW+2 - #endif - #define EXPO_LINE_FM_POS LCD_W-FW-MENUS_SCROLLBAR_WIDTH - #define EXPO_LINE_SELECT_POS 24 - #define MIX_LINE_WEIGHT_POS 11*FW+3 - #define MIX_LINE_CURVE_POS 12*FW+2 - #define MIX_LINE_SWITCH_POS 16*FW - #define MIX_LINE_DELAY_POS 19*FW+7 -#endif - -#if defined(NAVIGATION_MENUS) -void onExpoMixMenu(const char *result) -{ - bool expo = (g_menuStack[g_menuStackPtr] == menuModelExposAll); - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - if (result == STR_EDIT) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { - if (!reachExpoMixCountLimit(expo)) { - s_currCh = chn; - if (result == STR_INSERT_AFTER) { s_currIdx++; m_posVert++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - } - else if (result == STR_COPY || result == STR_MOVE) { - s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE); - s_copySrcIdx = s_currIdx; - s_copySrcCh = chn; - s_copySrcRow = m_posVert; - } - else if (result == STR_DELETE) { - deleteExpoMix(expo, s_currIdx); - } -} -#endif - -#if LCD_W >= 212 -void displayHeaderChannelName(uint8_t ch) -{ - uint8_t len = zlen(g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name)); - if (len) { - lcd_putc(17*FW, 0, ' '); - lcd_putsnAtt(18*FW, 0, g_model.limitData[ch-1].name, len, ZCHAR); - lcd_putc(18*FW+len*FW, 0, ' '); - } -} -#endif - -void menuModelExpoMix(uint8_t expo, uint8_t event) -{ - uint8_t sub = m_posVert; - - if (s_editMode > 0) - s_editMode = 0; - - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - switch (event) - { - case EVT_ENTRY: - case EVT_ENTRY_UP: - s_copyMode = 0; - s_copyTgtOfs = 0; - break; - case EVT_KEY_LONG(KEY_EXIT): - if (s_copyMode && s_copyTgtOfs == 0) { - deleteExpoMix(expo, s_currIdx); - killEvents(event); - event = 0; - } - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - if (s_copyMode) { - killEvents(event); - } -#endif - case EVT_KEY_BREAK(KEY_EXIT): - if (s_copyMode) { - if (s_copyTgtOfs) { - // cancel the current copy / move operation - if (s_copyMode == COPY_MODE) { - deleteExpoMix(expo, s_currIdx); - } - else { - do { - swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0); - s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); - } while (s_copyTgtOfs != 0); - eeDirty(EE_MODEL); - } - m_posVert = s_copySrcRow; - s_copyTgtOfs = 0; - } - s_copyMode = 0; - event = 0; - } - break; - case EVT_KEY_BREAK(KEY_ENTER): - if (sub != 0 && (!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) { - s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); - s_copySrcIdx = s_currIdx; - s_copySrcCh = chn; - s_copySrcRow = sub; - break; - } - // no break - - CASE_EVT_ROTARY_BREAK - case EVT_KEY_LONG(KEY_ENTER): - killEvents(event); - if (s_copyTgtOfs) { - s_copyMode = 0; - s_copyTgtOfs = 0; - } - else if (sub != 0) { - if (READ_ONLY()) { - if (!s_currCh) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - return; - } - } - else { - if (s_copyMode) s_currCh = 0; -#if defined(NAVIGATION_MENUS) - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - return; - } - else { - event = 0; - s_copyMode = 0; - MENU_ADD_ITEM(STR_EDIT); - MENU_ADD_ITEM(STR_INSERT_BEFORE); - MENU_ADD_ITEM(STR_INSERT_AFTER); - MENU_ADD_ITEM(STR_COPY); - MENU_ADD_ITEM(STR_MOVE); - MENU_ADD_ITEM(STR_DELETE); - menuHandler = onExpoMixMenu; - } -#else - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - } - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - return; -#endif - } - } - break; - case EVT_KEY_LONG(KEY_LEFT): - case EVT_KEY_LONG(KEY_RIGHT): - if (s_copyMode && !s_copyTgtOfs) { - if (reachExpoMixCountLimit(expo)) break; - s_currCh = chn; - if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; m_posVert++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - killEvents(event); - return; - } - break; -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LEFT: - case EVT_ROTARY_RIGHT: -#endif - case EVT_KEY_FIRST(KEY_MOVE_UP): - case EVT_KEY_REPT(KEY_MOVE_UP): - case EVT_KEY_FIRST(KEY_MOVE_DOWN): - case EVT_KEY_REPT(KEY_MOVE_DOWN): - if (s_copyMode) { - uint8_t key = (event & 0x1f); - uint8_t next_ofs = ((IS_ROTARY_UP(event) || key==KEY_MOVE_UP) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1); - - if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) { - // insert a mix on the same channel (just above / just below) - if (reachExpoMixCountLimit(expo)) break; - copyExpoMix(expo, s_currIdx); - if (IS_ROTARY_DOWN(event) || key==KEY_MOVE_DOWN) s_currIdx++; - else if (sub-s_pgOfs >= 6) s_pgOfs++; - } - else if (next_ofs==0 && s_copyMode==COPY_MODE) { - // delete the mix - deleteExpoMix(expo, s_currIdx); - if (IS_ROTARY_UP(event) || key==KEY_MOVE_UP) s_currIdx--; - } - else { - // only swap the mix with its neighbor - if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_UP(event) || key==KEY_MOVE_UP)) break; - eeDirty(EE_MODEL); - } - - s_copyTgtOfs = next_ofs; - } - break; - } - - lcd_outdezAtt(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, getExpoMixCount(expo)); - lcd_puts(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS)); - SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, s_maxLines); - - sub = m_posVert; - s_currCh = 0; - uint8_t cur = 1; - uint8_t i = 0; - - for (uint8_t ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { - void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; - uint8_t y = 1+(cur-s_pgOfs)*FH; - if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { - if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { - if (expo) { -#if defined(PCBTARANIS) - putsMixerSource(0, y, ch, 0); -#else - putsMixerSource(0, y, MIXSRC_Rud+ch-1, 0); -#endif - } - else { - putsChn(0, y, ch, 0); // show CHx - } - } - uint8_t mixCnt = 0; - do { - if (s_copyMode) { - if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < 8 && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcd_rect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - if (s_currIdx == i) { - sub = m_posVert = cur; - s_currCh = ch; - } - } - else if (sub == cur) { - s_currIdx = i; - } - if (s_pgOfs < cur && cur-s_pgOfs < 8) { - uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - if (expo) { - ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event); - -#if defined(PCBTARANIS) - putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0); -#endif - -#if defined(PCBTARANIS) - putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0); -#else - if (ed->curveMode == MODE_CURVE) - putsCurve(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam); - else - displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100); -#endif - - putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); - -#if !defined(PCBTARANIS) - if (ed->mode!=3) lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); -#endif - -#if defined(CPUARM) && LCD_W >= 212 - displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); - if (ed->name[0]) lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); -#elif defined(CPUARM) - if (ed->name[0]) lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); -#else - displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); -#endif - } - else { -#if LCD_W >= 212 - if (attr) { - displayHeaderChannelName(ch); - } -#endif - - if (mixCnt > 0) lcd_putsiAtt(FW, y, STR_VMLTPX2, md->mltpx, 0); - - putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, isMixActive(i) ? BOLD : 0); - - gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr, event); - -#if LCD_W >= 212 - displayFlightModes(EXPO_LINE_FM_POS, y, md->phases); -#endif - -#if defined(CPUARM) - if (md->name[0]) { - lcd_putsnAtt(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR | (isMixActive(i) ? BOLD : 0)); - } -#if LCD_W < 212 - else -#endif -#endif - { -#if defined(PCBTARANIS) -#else - if (md->curveParam) { - if (md->curveMode == MODE_CURVE) - putsCurve(MIX_LINE_CURVE_POS, y, md->curveParam); - else - displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100); - } -#endif - if (md->swtch) putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); - - char cs = ' '; - if (md->speedDown || md->speedUp) - cs = 'S'; - if ((md->delayUp || md->delayDown)) - cs = (cs =='S' ? '*' : 'D'); - lcd_putc(MIX_LINE_DELAY_POS, y, cs); - } - } - if (s_copyMode) { - if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - /* draw a border around the raw on selection mode (copy/move) */ - lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); - } - if (cur == sub) { - /* invert the raw when it's the current one */ - lcd_filled_rect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7); - } - } - } - cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++; - } while (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)); - if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - } - else { - uint8_t attr = 0; - if (sub == cur) { - s_currIdx = i; - s_currCh = ch; - if (!s_copyMode) { - attr = INVERS; - } - } - if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { - if (expo) { -#if defined(PCBTARANIS) - putsMixerSource(0, y, ch, attr); -#else - putsMixerSource(0, y, MIXSRC_Rud+ch-1, attr); -#endif - } - else { - putsChn(0, y, ch, attr); // show CHx -#if LCD_W >= 212 - if (attr) { - displayHeaderChannelName(ch); - } -#endif - } - if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { - lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED); - } - } - cur++; y+=FH; - } - } - s_maxLines = cur; - if (sub >= s_maxLines-1) m_posVert = s_maxLines-1; -} - -void menuModelExposAll(uint8_t event) -{ - return menuModelExpoMix(1, event); -} - -void menuModelMixAll(uint8_t event) -{ - return menuModelExpoMix(0, event); -} - -bool thrOutput(uint8_t ch) -{ - for (uint8_t i=0; idestCh==ch && mix->srcRaw==MIXSRC_Thr) - return true; - } - return false; -} - -enum LimitsItems { -#if defined(PCBTARANIS) - ITEM_LIMITS_CH_NAME, -#endif - ITEM_LIMITS_OFFSET, - ITEM_LIMITS_MIN, - ITEM_LIMITS_MAX, - ITEM_LIMITS_DIRECTION, -#if defined(PCBTARANIS) && defined(CURVES) - ITEM_LIMITS_CURVE, -#endif -#if defined(PPM_CENTER_ADJUSTABLE) - ITEM_LIMITS_PPM_CENTER, -#endif -#if defined(PPM_LIMITS_SYMETRICAL) - ITEM_LIMITS_SYMETRICAL, -#endif - ITEM_LIMITS_COUNT, - ITEM_LIMITS_MAXROW = ITEM_LIMITS_COUNT-1 -}; - -#if defined(PCBTARANIS) - #define LIMITS_NAME_POS 4*FW - #define LIMITS_OFFSET_POS 14*FW+4 - #define LIMITS_MIN_POS 20*FW-3 - #if defined(PPM_CENTER_ADJUSTABLE) - #define LIMITS_DIRECTION_POS 20*FW-3 - #define LIMITS_MAX_POS 24*FW+2 - #define LIMITS_REVERT_POS 25*FW-1 - #define LIMITS_CURVE_POS 27*FW-1 - #define LIMITS_PPM_CENTER_POS 34*FW - #else - #define LIMITS_DIRECTION_POS 21*FW - #define LIMITS_MAX_POS 26*FW - #define LIMITS_REVERT_POS 27*FW - #define LIMITS_CURVE_POS 32*FW - #endif -#else - #if defined(PPM_UNIT_US) - #define LIMITS_MIN_POS 12*FW+1 - #else - #define LIMITS_MIN_POS 12*FW - #endif - #define LIMITS_OFFSET_POS 8*FW - #if defined(PPM_LIMITS_SYMETRICAL) - #if defined(PPM_CENTER_ADJUSTABLE) - #define LIMITS_MAX_POS 15*FW - #define LIMITS_REVERT_POS 16*FW-3 - #define LIMITS_PPM_CENTER_POS 20*FW+1 - #else - #define LIMITS_DIRECTION_POS 12*FW+4 - #define LIMITS_MAX_POS 16*FW+4 - #define LIMITS_REVERT_POS 17*FW - #endif - #else - #if defined(PPM_CENTER_ADJUSTABLE) - #define LIMITS_MAX_POS 16*FW - #define LIMITS_REVERT_POS 17*FW-2 - #define LIMITS_PPM_CENTER_POS 21*FW+2 - #else - #define LIMITS_MAX_POS 17*FW - #define LIMITS_REVERT_POS 18*FW - #define LIMITS_DIRECTION_POS 12*FW+5 - #endif - #endif -#endif - -#if defined(CPUARM) - #define LIMITS_MIN_MAX_OFFSET 1000 - #define CONVERT_US_MIN_MAX(x) (((x)*128)/250) - #define MIN_MAX_LIMIT (10*limit) - #define MIN_MAX_ATTR attr|PREC1 -#else - #define LIMITS_MIN_MAX_OFFSET 100 - #define CONVERT_US_MIN_MAX(x) ((int16_t(x)*128)/25) - #define MIN_MAX_LIMIT (limit) - #define MIN_MAX_ATTR attr -#endif - -#if defined(PPM_UNIT_US) - #define MIN_MAX_DISPLAY(x) CONVERT_US_MIN_MAX(x) - #undef MIN_MAX_ATTR - #define MIN_MAX_ATTR attr -#else - #define MIN_MAX_DISPLAY(x) (x) -#endif - -#if defined(PCBTARANIS) -void onLimitsMenu(const char *result) -{ - uint8_t ch = m_posVert - 1; - - if (result == STR_RESET) { - LimitData *ld = limitAddress(ch); - ld->min = 0; - ld->max = 0; - ld->offset = 0; - ld->ppmCenter = 0; - ld->revert = false; - ld->curve = 0; - } - else if (result == STR_COPY_TRIMS_TO_OFFSET) { - copyTrimsToOffset(ch); - } -} -#endif - -void menuModelLimits(uint8_t event) -{ - uint8_t sub = m_posVert - 1; - - if (sub < NUM_CHNOUT) { -#if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US) - lcd_outdezAtt(13*FW, 0, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, 0); - lcd_puts(13*FW, 0, STR_US); -#else - lcd_outdezAtt(13*FW, 0, calcRESXto1000(channelOutputs[sub]), PREC1); -#endif - } - -#if defined(CPUARM) - MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, 0}); -#else - MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, 0}); -#endif - -#if LCD_W >= 212 - if (sub=0) { - displayColumnHeader(STR_LIMITS_HEADERS, m_posHorz); - } -#endif - - if (s_warning_result) { - s_warning_result = 0; - LimitData *ld = limitAddress(sub); - ld->revert = !ld->revert; - eeDirty(EE_MODEL); - } - - for (uint8_t i=0; i= 212 || !defined(PPM_CENTER_ADJUSTABLE) - int16_t v = (ld->revert) ? -ld->offset : ld->offset; - char swVal = '-'; // '-', '<', '>' - if((channelOutputs[k] - v) > 50) swVal = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim! - if((channelOutputs[k] - v) < -50) swVal = (ld->revert ? 126 : 127); - putsChn(0, y, k+1, 0); - lcd_putc(LIMITS_DIRECTION_POS, y, swVal); -#endif - -#if defined(PPM_CENTER_ADJUSTABLE) - int8_t limit = ((g_model.extendedLimits && !limitAddress(k)->ppmCenter) ? 125 : 100); -#else - int8_t limit = (g_model.extendedLimits ? 125 : 100); -#endif - -#if defined(PCBTARANIS) - putsChn(0, y, k+1, (sub==k && m_posHorz < 0) ? INVERS : 0); - if (sub==k && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - MENU_ADD_ITEM(STR_RESET); - MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFFSET); - menuHandler = onLimitsMenu; - } -#else - putsChn(0, y, k+1, 0); -#endif - - for (uint8_t j=0; j0) ? BLINK|INVERS : INVERS) : 0); - uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; - if (active) STICK_SCROLL_DISABLE(); - switch(j) - { -#if defined(PCBTARANIS) - case ITEM_LIMITS_CH_NAME: - editName(LIMITS_NAME_POS, y, ld->name, sizeof(ld->name), event, attr); - break; -#endif - - case ITEM_LIMITS_OFFSET: -#if defined(PCBTARANIS) - ld->offset = GVAR_MENU_ITEM(LIMITS_OFFSET_POS, y, MIN_MAX_DISPLAY(ld->offset), -1000, 1000, attr|PREC1, 0, event); -#else - #if defined(PPM_UNIT_US) - lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1); - #else - lcd_outdezAtt(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1); - #endif - if (active) { - ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL|NO_INCDEC_MARKS); - } - else if (attr && event==EVT_KEY_LONG(KEY_MENU)) { - copyTrimsToOffset(k); - s_editMode = 0; - } -#endif - break; - - case ITEM_LIMITS_MIN: -#if defined(CPUARM) - ld->min = LIMITS_MIN_MAX_OFFSET + GVAR_MENU_ITEM(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), -MIN_MAX_LIMIT, 0, MIN_MAX_ATTR, DBLKEYS_1000, event); -#else - lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); - if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDecModel(event, ld->min-LIMITS_MIN_MAX_OFFSET, -MIN_MAX_LIMIT, 0); -#endif - break; - - case ITEM_LIMITS_MAX: -#if defined(CPUARM) - ld->max = -LIMITS_MIN_MAX_OFFSET + GVAR_MENU_ITEM(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), 0, MIN_MAX_LIMIT, MIN_MAX_ATTR, DBLKEYS_1000, event); -#else - lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); - if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDecModelZero(event, ld->max+LIMITS_MIN_MAX_OFFSET, +MIN_MAX_LIMIT); -#endif - break; - - case ITEM_LIMITS_DIRECTION: - { - uint8_t revert = ld->revert; -#if defined(PPM_CENTER_ADJUSTABLE) - lcd_putcAtt(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr); -#else - lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr); -#endif - if (active) { - uint8_t revert_new = checkIncDecModel(event, revert, 0, 1); - if (checkIncDec_Ret && thrOutput(k)) { - POPUP_CONFIRMATION(STR_INVERT_THR); - } - else { - ld->revert = revert_new; - } - } - break; - } - -#if defined(PCBTARANIS) && defined(CURVES) - case ITEM_LIMITS_CURVE: - putsCurve(LIMITS_CURVE_POS, y, ld->curve, attr); - if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) { - s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1); - pushMenu(menuModelCurveOne); - } - if (active) { - CHECK_INCDEC_MODELVAR(event, ld->curve, -MAX_CURVES, +MAX_CURVES); - } - break; -#endif - -#if defined(PPM_CENTER_ADJUSTABLE) - case ITEM_LIMITS_PPM_CENTER: - lcd_outdezAtt(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr); -#pragma message("could be less restrictive!") - if (active && ld->max <= 0 && ld->min >= 0) { - CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -125, +125); - } - break; -#endif - -#if defined(PPM_LIMITS_SYMETRICAL) - case ITEM_LIMITS_SYMETRICAL: - lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '^', attr); - if (active) { - CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1); - } - break; -#endif - } - } - } -} - -#if defined(CURVES) - -#if defined(GVARS) - #define CURVE_SELECTED() (sub >= 0 && sub < MAX_CURVES) - #define GVAR_SELECTED() (sub >= MAX_CURVES) -#else - #define CURVE_SELECTED() (sub >= 0) -#endif - -void menuModelCurvesAll(uint8_t event) -{ -#if defined(GVARS) && defined(PCBSTD) - SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES+MAX_GVARS); -#else - SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES); -#endif - - int8_t sub = m_posVert - 1; - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: -#endif -#if defined(PCBTARANIS) - case EVT_KEY_BREAK(KEY_ENTER): -#else - case EVT_KEY_FIRST(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_ENTER): -#endif - if (CURVE_SELECTED() && !READ_ONLY()) { - s_curveChan = sub; - pushMenu(menuModelCurveOne); - } - break; - } - - for (uint8_t i=0; i= MAX_CURVES) { - putsStrIdx(0, y, STR_GV, k-MAX_CURVES+1); - if (GVAR_SELECTED()) { - if (attr && s_editMode>0) attr |= BLINK; - lcd_outdezAtt(10*FW, y, GVAR_VALUE(k-MAX_CURVES, -1), attr); - if (attr) g_model.gvars[k-MAX_CURVES] = checkIncDec(event, g_model.gvars[k-MAX_CURVES], -1000, 1000, EE_MODEL); - } - } - else -#endif - { - putsStrIdx(0, y, STR_CV, k+1, attr); -#if defined(PCBTARANIS) - editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); - CurveInfo & crv = g_model.curves[k]; - lcd_outdezAtt(11*FW, y, 5+crv.points, LEFT); - lcd_putsAtt(lcdLastPos, y, PSTR("pts"), 0); -#endif - } - } - - if (CURVE_SELECTED()) { - s_curveChan = sub; - DrawCurve(23); - } -} -#endif - -#if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) - -void onGVARSMenu(const char *result) -{ - int8_t sub = m_posVert - 1; - - if (result == STR_ENABLE_POPUP) { - g_model.gvars[sub].popup = true; - eeDirty(EE_MODEL); - } - else if (result == STR_DISABLE_POPUP) { - g_model.gvars[sub].popup = false; - eeDirty(EE_MODEL); - } - else if (result == STR_CLEAR) { - for (int i=0; i 6 - for (uint8_t l=0; l0) ? BLINK|INVERS : INVERS) : 0); - xcoord_t x = 12*FW + FWNUM + (j-1)*(2+3*FWNUM) - 3; - -#if MAX_GVARS == 6 - if (i==0 && j!=9) putsStrIdx(x+2, FH+1, STR_FP, j, SMLSIZE); -#elif MAX_GVARS <= 5 - if (i==0 && j!=9) putsStrIdx(x+2, 2*FH, STR_FP, j, SMLSIZE); -#endif - - switch(j) - { - case 0: - editName(4*FW-3, y, g_model.gvars[i].name, LEN_GVAR_NAME, event, attr); - break; - - default: - { - PhaseData *phase = &g_model.phaseData[j-1]; - int16_t & v = phase->gvars[i]; - int16_t vmin, vmax; - if (v > GVAR_MAX) { - uint8_t p = v - GVAR_MAX - 1; - if (p >= j-1) p++; - putsFlightPhase(x-15, y, p+1, attr|SMLSIZE); - vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_PHASES-1; - } - else { - if (abs(v) >= 100) - lcd_outdezAtt(x, y+1, v, attr | TINSIZE); - else - lcd_outdezAtt(x, y, v, attr); - vmin = -GVAR_MAX; vmax = GVAR_MAX; - } - if (attr) { - if (event == EVT_KEY_LONG(KEY_ENTER)) { - s_editMode = 2; // TODO constant for that ... - v = (v > GVAR_MAX ? 0 : GVAR_MAX+1); - eeDirty(EE_MODEL); - } - else if (s_editMode>0 || p1valdiff) { - v = checkIncDec(event, v, vmin, vmax, EE_MODEL); - } - } - break; - } - } - } - } - -#if defined(CPUARM) - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) -#elif defined(CPUM64) - #define INCDEC_DECLARE_VARS() - #define INCDEC_SET_FLAG(f) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) -#else - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) -#endif - - if (m_posVert > 0 && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - if (g_model.gvars[sub].popup) - MENU_ADD_ITEM(STR_DISABLE_POPUP); - else - MENU_ADD_ITEM(STR_ENABLE_POPUP); - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onGVARSMenu; - } -} -#endif - -#if defined(CPUARM) - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) -#elif defined(CPUM64) - #define INCDEC_DECLARE_VARS() - #define INCDEC_SET_FLAG(f) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) -#else - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) -#endif - -enum CustomSwitchFields { - CSW_FIELD_FUNCTION, - CSW_FIELD_V1, - CSW_FIELD_V2, - CSW_FIELD_ANDSW, -#if defined(CPUARM) - CSW_FIELD_DURATION, - CSW_FIELD_DELAY, -#endif - CSW_FIELD_COUNT, - CSW_FIELD_LAST = CSW_FIELD_COUNT-1 -}; - -#if LCD_W >= 212 - #define CSW_1ST_COLUMN (4*FW-3) - #define CSW_2ND_COLUMN (8*FW+1) - #define CSW_3RD_COLUMN (14*FW) - #define CSW_4TH_COLUMN (21*FW+1) - #define CSW_5TH_COLUMN (26*FW+1) - #define CSW_6TH_COLUMN (31*FW+1) -#else - #define CSW_1ST_COLUMN (4*FW-3) - #define CSW_2ND_COLUMN (8*FW-3) - #define CSW_3RD_COLUMN (13*FW-6) - #define CSW_4TH_COLUMN (18*FW+2) -#endif - -#if defined(CPUARM) && LCD_W < 212 - -#define CSWONE_2ND_COLUMN (11*FW) - -void menuModelCustomSwitchOne(uint8_t event) -{ - TITLE(STR_MENUCUSTOMSWITCH); - - CustomSwData * cs = cswAddress(s_currIdx); - uint8_t sw = SWSRC_SW1+s_currIdx; - putsSwitches(14*FW, 0, sw, (getSwitch(sw) ? BOLD : 0)); - SIMPLE_SUBMENU_NOTITLE(CSW_FIELD_COUNT); - - int8_t sub = m_posVert; - - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - uint8_t cstate = cswFamily(cs->func); - switch(i) { - case CSW_FIELD_FUNCTION: - lcd_putsLeft(y, STR_FUNC); - lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_VCSWFUNC, cs->func, attr); - if (attr) { - CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); - if (cstate != cswFamily(cs->func)) { - cs->v1 = 0; - cs->v2 = 0; - } - } - break; - case CSW_FIELD_V1: - { - lcd_putsLeft(y, STR_V1); - int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM; - if (cstate == CS_VBOOL) { - putsSwitches(CSWONE_2ND_COLUMN, y, cs->v1, attr); - v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v1+1, LEFT|attr); - v1_max = 99; - } - else { - putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v1, attr); - } - if (attr) { - CHECK_INCDEC_MODELVAR(event, cs->v1, v1_min, v1_max); - } - break; - } - case CSW_FIELD_V2: - { - lcd_putsLeft(y, STR_V2); - int8_t v2_min=0, v2_max=MIXSRC_LAST_TELEM; - if (cstate == CS_VBOOL) { - putsSwitches(CSWONE_2ND_COLUMN, y, cs->v2, attr); - v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2+1, LEFT|attr); - v2_max = 99; - } - else if (cstate == CS_VCOMP) { - putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v2, attr); - } - else { -#if defined(FRSKY) - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSWONE_2ND_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), attr|LEFT); - v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); - if (cstate == CS_VOFS) { - v2_min = -128; - v2_max -= 128; - } - else { - v2_max = min((uint8_t)127, (uint8_t)v2_max); - v2_min = -v2_max; - } - if (cs->v2 > v2_max) { - cs->v2 = v2_max; - eeDirty(EE_MODEL); - } - } - else -#endif - { - v2_min = -125; v2_max = 125; - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2, LEFT|attr); - } - } - - if (attr) { - CHECK_INCDEC_MODELVAR(event, cs->v2, v2_min, v2_max); - } - break; - } - case CSW_FIELD_ANDSW: - lcd_putsLeft(y, STR_AND_SWITCH); - putsSwitches(CSWONE_2ND_COLUMN, y, cs->andsw, attr); - if (attr) CHECK_INCDEC_MODELVAR(event, cs->andsw, -MAX_SWITCH, MAX_SWITCH); - break; - case CSW_FIELD_DURATION: - lcd_putsLeft(y, STR_DURATION); - if (cs->duration > 0) - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 5*cs->duration, attr|PREC1|LEFT); - else - lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_CSW_DURATION); - break; - case CSW_FIELD_DELAY: - lcd_putsLeft(y, STR_DELAY); - if (cs->delay > 0) - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 5*cs->delay, attr|PREC1|LEFT); - else - lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_CSW_DELAY); - break; - } - } -} - -void menuModelCustomSwitches(uint8_t event) -{ - SIMPLE_MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1); - - uint8_t y = 0; - uint8_t k = 0; - int8_t sub = m_posVert - 1; - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: -#endif - case EVT_KEY_FIRST(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_ENTER): - if (sub >= 0) { - s_currIdx = sub; - pushMenu(menuModelCustomSwitchOne); - } - break; - } - - for (uint8_t i=0; ifunc > 0) { - // CSW func - lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, 0); - - // CSW params - uint8_t cstate = cswFamily(cs->func); - - if (cstate == CS_VBOOL) { - putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0); - putsSwitches(CSW_3RD_COLUMN, y, cs->v2, 0); - } - else if (cstate == CS_VCOMP) { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); - putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, 0); - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSW_2ND_COLUMN, y, cs->v1+1, LEFT); - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2+1, LEFT); - } - else { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT); - } - else { - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT); - } - } - - // CSW and switch - putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, 0); - } - } -} - -#else - -#if defined(PCBTARANIS) -enum ClipboardType { - CLIPBOARD_TYPE_NONE, - CLIPBOARD_TYPE_CUSTOM_SWITCH, - CLIPBOARD_TYPE_CUSTOM_FUNCTION, -}; - -struct Clipboard { - ClipboardType type; - union { - CustomSwData csw; - CustomFnData cfn; - } data; -}; - -Clipboard clipboard; - -void onCustomSwitchesMenu(const char *result) -{ - int8_t sub = m_posVert-1; - CustomSwData * cs = cswAddress(sub); - - if (result == STR_COPY) { - clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH; - clipboard.data.csw = *cs; - } - else if (result == STR_PASTE) { - *cs = clipboard.data.csw; - eeDirty(EE_MODEL); - } - else if (result == STR_DELETE) { - memset(cs, 0, sizeof(CustomSwData)); - eeDirty(EE_MODEL); - } -} -#endif - -void menuModelCustomSwitches(uint8_t event) -{ - INCDEC_DECLARE_VARS(); - - MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1, {0, NAVIGATION_LINE_BY_LINE|CSW_FIELD_LAST/*repeated...*/}); - - uint8_t y = 0; - uint8_t k = 0; - int8_t sub = m_posVert - 1; - horzpos_t horz = m_posHorz; - -#if LCD_W >= 212 - if (horz>=0) { - displayColumnHeader(STR_CSW_HEADERS, horz); - } -#endif - -#if defined(PCBTARANIS) - if (sub>=0 && horz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { - killEvents(event); - CustomSwData * cs = cswAddress(sub); - if (cs->func) MENU_ADD_ITEM(STR_COPY); - if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH) - MENU_ADD_ITEM(STR_PASTE); - if (cs->func || cs->v1 || cs->v2 || cs->delay || cs->duration || cs->andsw) MENU_ADD_ITEM(STR_DELETE); - menuHandler = onCustomSwitchesMenu; - } -#endif - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); - uint8_t attr1 = (horz==1 ? attr : 0); - uint8_t attr2 = (horz==2 ? attr : 0); - CustomSwData * cs = cswAddress(k); - - // CSW name - uint8_t sw = SWSRC_SW1+k; - putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && horz<0) ? INVERS : 0)); - - // CSW func - lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0); - - // CSW params - uint8_t cstate = cswFamily(cs->func); -#if defined(CPUARM) - int16_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; -#else - int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; -#endif - - if (cstate == CS_VBOOL) { - putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); - putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2); - v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; - v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; - INCDEC_SET_FLAG(INCDEC_SWITCH); - INCDEC_ENABLE_CHECK(NULL); - } - else if (cstate == CS_VCOMP) { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, attr1); - putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2); - INCDEC_SET_FLAG(INCDEC_SOURCE); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSW_2ND_COLUMN, y, cswTimerValue(cs->v1), LEFT|PREC1|attr1); - lcd_outdezAtt(CSW_3RD_COLUMN, y, cswTimerValue(cs->v2), LEFT|PREC1|attr2); - v1_min = v2_min = -128; - v1_max = v2_max = 122; - INCDEC_SET_FLAG(0); - INCDEC_ENABLE_CHECK(NULL); - } - else { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, attr1); - if (horz == 1) { - INCDEC_SET_FLAG(INCDEC_SOURCE); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } - else { - INCDEC_SET_FLAG(0); - INCDEC_ENABLE_CHECK(NULL); - } -#if defined(FRSKY) - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); - v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); -#if defined(CPUARM) - v2_min = minTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); - if (cs->v2 < v2_min || cs->v2 > v2_max) { - cs->v2 = 0; - eeDirty(EE_MODEL); - } -#else - if (cstate == CS_VOFS) { - v2_min = -128; - v2_max -= 128; - } - else { - v2_max = min((uint8_t)127, (uint8_t)v2_max); - v2_min = -v2_max; - } - if (cs->v2 > v2_max) { - cs->v2 = v2_max; - eeDirty(EE_MODEL); - } -#endif - } - else { - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); - v2_min = -125; v2_max = 125; - } -#else - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); - v2_min = -128; v2_max = 127; - } - else { - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); - v2_min = -125; v2_max = 125; - } -#endif - } - - // CSW and switch - putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==3 ? attr : 0); - -#if defined(CPUARM) - // CSW duration - if (cs->duration > 0) - lcd_outdezAtt(CSW_5TH_COLUMN, y, 5*cs->duration, (horz==4 ? attr : 0)|PREC1|LEFT); - else - lcd_putsiAtt(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==4 ? attr : 0); - - // CSW delay - if (cs->delay > 0) - lcd_outdezAtt(CSW_6TH_COLUMN, y, 5*cs->delay, (horz==5 ? attr : 0)|PREC1|LEFT); - else - lcd_putsiAtt(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==5 ? attr : 0); -#endif - - if ((s_editMode>0 || p1valdiff) && attr) { - switch (horz) { - case CSW_FIELD_FUNCTION: - { - CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); - uint8_t new_cstate = cswFamily(cs->func); - if (cstate != new_cstate) - cs->v1 = cs->v2 = (new_cstate==CS_VTIMER ? -119/*1.0*/ : 0); - break; - } - case CSW_FIELD_V1: - cs->v1 = CHECK_INCDEC_PARAM(event, cs->v1, v1_min, v1_max); - break; - case CSW_FIELD_V2: - cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); -#if defined(PCBTARANIS) - if (cstate==CS_VOFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - getvalue_t x = getValue(cs->v1); - TRACE("AUTO x=%d", x); - if (cs->v1 < MIXSRC_GVAR1) - cs->v2 = calcRESXto100(x); - else if (cs->v1 - MIXSRC_FIRST_TELEM + 1 == TELEM_ALT) - cs->v2 *= 100; - eeDirty(EE_MODEL); - } -#endif - break; - case CSW_FIELD_ANDSW: -#if defined(CPUARM) - CHECK_INCDEC_MODELSWITCH(event, cs->andsw, -MAX_CSW_ANDSW, MAX_CSW_ANDSW); -#else - CHECK_INCDEC_MODELVAR_ZERO(event, cs->andsw, MAX_CSW_ANDSW); -#endif - break; -#if defined(CPUARM) - case CSW_FIELD_DURATION: - CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_CSW_DURATION); - break; - case CSW_FIELD_DELAY: - CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_CSW_DELAY); - break; -#endif - } - } - } -} -#endif - -#if LCD_W >= 212 - #define MODEL_CUSTOM_FUNC_1ST_COLUMN (5+4*FW) - #define MODEL_CUSTOM_FUNC_2ND_COLUMN (9*FW) - #define MODEL_CUSTOM_FUNC_3RD_COLUMN (21*FW) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN (33*FW-3) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (34*FW-3) -#else - #define MODEL_CUSTOM_FUNC_1ST_COLUMN (3) - #define MODEL_CUSTOM_FUNC_2ND_COLUMN (5*FW-2) - #define MODEL_CUSTOM_FUNC_3RD_COLUMN (15*FW+2) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN (20*FW) - #if defined(GRAPHICS) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (20*FW) - #else - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (18*FW+2) - #endif -#endif - -#if defined(CPUARM) && defined(SDCARD) -void onCustomFunctionsFileSelectionMenu(const char *result) -{ - int8_t sub = m_posVert - 1; - - if (result == STR_UPDATE_LIST) { - char directory[] = SOUNDS_PATH; - strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - if (!listSdFiles(directory, SOUNDS_EXT, sizeof(g_model.funcSw[sub].param), NULL)) { - POPUP_WARNING(STR_NO_SOUNDS_ON_SD); - s_menu_flags = 0; - } - } - else { - // The user choosed a wav file in the list - memcpy(g_model.funcSw[sub].param.name, result, sizeof(g_model.funcSw[sub].param.name)); - eeDirty(EE_MODEL); - } -} -#endif - -#if defined(PCBTARANIS) -void onCustomFunctionsMenu(const char *result) -{ - int8_t sub = m_posVert-1; - CustomFnData * cfn = &g_model.funcSw[sub]; - - if (result == STR_COPY) { - clipboard.type = CLIPBOARD_TYPE_CUSTOM_FUNCTION; - clipboard.data.cfn = *cfn; - } - else if (result == STR_PASTE) { - *cfn = clipboard.data.cfn; - eeDirty(EE_MODEL); - } - else if (result == STR_CLEAR) { - memset(cfn, 0, sizeof(CustomFnData)); - eeDirty(EE_MODEL); - } - else if (result == STR_INSERT) { - memmove(cfn+1, cfn, (NUM_CFN-sub-1)*sizeof(CustomFnData)); - memset(cfn, 0, sizeof(CustomFnData)); - eeDirty(EE_MODEL); - } - else if (result == STR_DELETE) { - memmove(cfn, cfn+1, (NUM_CFN-sub-1)*sizeof(CustomFnData)); - memset(&g_model.funcSw[NUM_CFN-1], 0, sizeof(CustomFnData)); - eeDirty(EE_MODEL); - } -} - -#endif - -void menuModelCustomFunctions(uint8_t event) -{ - MENU(STR_MENUCUSTOMFUNC, menuTabModel, e_CustomFunctions, NUM_CFN+1, {0, NAVIGATION_LINE_BY_LINE|3/*repeated*/}); - - uint8_t y; - uint8_t k = 0; - int8_t sub = m_posVert - 1; - -#if defined(PCBTARANIS) - if (sub>=0 && m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { - killEvents(event); - CustomFnData *sd = &g_model.funcSw[sub]; - if (!CFN_EMPTY(sd)) - MENU_ADD_ITEM(STR_COPY); - if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION) - MENU_ADD_ITEM(STR_PASTE); - if (!CFN_EMPTY(sd) && CFN_EMPTY(&g_model.funcSw[NUM_CFN-1])) - MENU_ADD_ITEM(STR_INSERT); - if (CFN_EMPTY(sd)) - MENU_ADD_ITEM(STR_DELETE); - else - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onCustomFunctionsMenu; - } -#endif - - for (uint8_t i=0; i= 212 - putsStrIdx(0, y, STR_CF, k+1, (sub==k && m_posHorz<0) ? INVERS : 0); -#endif - - CustomFnData *sd = &g_model.funcSw[k]; - for (uint8_t j=0; j<4; j++) { - uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); - uint8_t active = (attr && (s_editMode>0 || p1valdiff)); - switch (j) { - case 0: - putsSwitches(MODEL_CUSTOM_FUNC_1ST_COLUMN, y, sd->swtch, attr | ((activeFnSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0)); - if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_MODELSWITCH(event, sd->swtch, SWSRC_FIRST, SWSRC_LAST); - break; - - case 1: - if (sd->swtch) { - uint8_t func_displayed; - if (CFN_FUNC(sd) < FUNC_TRAINER) { - func_displayed = 0; - putsChn(MODEL_CUSTOM_FUNC_2ND_COLUMN+6*FW, y, CFN_CH_NUMBER(sd)+1, attr); - } - else if (CFN_FUNC(sd) <= FUNC_TRAINER + NUM_STICKS) { - func_displayed = 1; - if (CFN_FUNC(sd) != FUNC_TRAINER) - putsMixerSource(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, MIXSRC_Rud+CFN_FUNC(sd)-FUNC_TRAINER-1, attr); - } -#if defined(DEBUG) - else if (CFN_FUNC(sd) == FUNC_TEST) { -#if defined(GVARS) - func_displayed = FUNC_TEST - FUNC_TRAINER - NUM_STICKS - MAX_GVARS + 2; -#else - func_displayed = FUNC_TEST - FUNC_TRAINER - NUM_STICKS + 1; -#endif - } -#endif -#if defined(GVARS) - else if (CFN_FUNC(sd) >= FUNC_ADJUST_GV1) { - func_displayed = FUNC_ADJUST_GV1 - FUNC_TRAINER - NUM_STICKS + 1; - putsStrIdx(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, STR_GV, CFN_FUNC(sd)-FUNC_ADJUST_GV1+1, attr); - } -#endif - else { - func_displayed = 2 + CFN_FUNC(sd) - FUNC_TRAINER - NUM_STICKS - 1; - } - lcd_putsiAtt(MODEL_CUSTOM_FUNC_2ND_COLUMN, y, STR_VFSWFUNC, func_displayed, attr); - if (active) { -#if defined(CPUARM) - CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(sd), FUNC_MAX-1); -#else - if (CFN_FUNC(sd) < FUNC_TRAINER) { - CHECK_INCDEC_MODELVAR_ZERO(event, sd->internal.func_safety.func, 16); - } - else { - CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(sd), FUNC_MAX-1); - if (CFN_FUNC(sd) < FUNC_TRAINER) - sd->internal.func_safety.func = 15; - } -#endif - if (checkIncDec_Ret) CFN_RESET(sd); - } - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - - case 2: - if (sd->swtch) { - INCDEC_DECLARE_VARS(); - int16_t val_displayed = CFN_PARAM(sd); - int8_t val_min = 0; - uint8_t val_max = 255; - if (CFN_FUNC(sd) == FUNC_PLAY_SOUND) { -#if defined(AUDIO) - val_max = AU_FRSKY_LAST-AU_FRSKY_FIRST-1; - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_FUNCSOUNDS, val_displayed, attr); -#else - break; -#endif - } -#if defined(HAPTIC) - else if (CFN_FUNC(sd) == FUNC_HAPTIC) { - val_max = 3; - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); - } -#endif -#if defined(CPUARM) && defined(SDCARD) - else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK || CFN_FUNC(sd) == FUNC_BACKGND_MUSIC) { -#if LCD_W >= 212 - xcoord_t x = MODEL_CUSTOM_FUNC_3RD_COLUMN; -#else - xcoord_t x = (CFN_FUNC(sd) == FUNC_PLAY_TRACK ? MODEL_CUSTOM_FUNC_2ND_COLUMN + FW + FW*strlen(TR_PLAY_TRACK) : MODEL_CUSTOM_FUNC_3RD_COLUMN); -#endif - if (ZEXIST(sd->param.name)) - lcd_putsnAtt(x, y, sd->param.name, sizeof(sd->param.name), attr); - else - lcd_putsiAtt(x, y, STR_VCSWFUNC, 0, attr); - if (active && event==EVT_KEY_BREAK(KEY_ENTER)) { - s_editMode = 0; - char directory[] = SOUNDS_PATH; - strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - if (listSdFiles(directory, SOUNDS_EXT, sizeof(sd->param.name), sd->param.name)) { - menuHandler = onCustomFunctionsFileSelectionMenu; - } - else { - POPUP_WARNING(STR_NO_SOUNDS_ON_SD); - s_menu_flags = 0; - } - } - break; - } - else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { - val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } -#endif -#if defined(CPUARM) - else if (CFN_FUNC(sd) == FUNC_VOLUME) { - val_max = MIXSRC_LAST_CH; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } -#elif defined(VOICE) - else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK) { -#if defined(GVARS) - if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - s_editMode = !s_editMode; - active = true; - val_displayed = (val_displayed > 250 ? 0 : 251); - } - if (val_displayed > 250) { - putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed-250, attr); - } - else { - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT); - } -#else - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT); -#endif - } - else if (CFN_FUNC(sd) == FUNC_PLAY_BOTH) { - lcd_putcAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+3*FWNUM, y, '|', attr); - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+3*FWNUM, y, val_displayed+PROMPT_CUSTOM_BASE, attr); - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+2+3*FWNUM, y, (val_displayed+PROMPT_CUSTOM_BASE+1)%10, attr|LEFT); - } - else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { - val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } -#endif -#if defined(SDCARD) - else if (CFN_FUNC(sd) == FUNC_LOGS) { - if (val_displayed) { - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|PREC1|LEFT); - lcd_putc(lcdLastPos, y, 's'); - } - else { - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_MMMINV, 0, attr); - } - } -#endif - else if (CFN_FUNC(sd) == FUNC_RESET) { - val_max = FUNC_RESET_PARAM_LAST; - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_VFSWRESET, CFN_PARAM(sd), attr); - } - else if (CFN_FUNC(sd) < FUNC_TRAINER) { - val_displayed = (int8_t)CFN_PARAM(sd); - val_min = -125; val_max = 125; - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); - } -#if defined(GVARS) - else if (CFN_FUNC(sd) >= FUNC_ADJUST_GV1 -#if defined(DEBUG) - && CFN_FUNC(sd) <= FUNC_ADJUST_GVLAST -#endif - ) { - switch (CFN_GVAR_MODE(sd)) { - case FUNC_ADJUST_GVAR_CONSTANT: - val_displayed = (int8_t)CFN_PARAM(sd); - val_min = -125; val_max = 125; - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); - break; - case FUNC_ADJUST_GVAR_SOURCE: - val_max = MIXSRC_LAST_CH; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - break; - case FUNC_ADJUST_GVAR_GVAR: - val_max = MAX_GVARS-1; - putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed+1, attr); - break; - default: // FUNC_ADJUST_GVAR_INC - val_max = 1; - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, PSTR("\002-1+1"), val_displayed, attr); - break; - } - - if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - s_editMode = !s_editMode; - active = true; - CFN_GVAR_MODE(sd) += 1; - val_displayed = 0; - } - } -#endif - else { - if (attr) m_posHorz = (CURSOR_MOVED_LEFT(event) ? 1 : 3); - break; - } - - if (active) { - CFN_PARAM(sd) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max); - } - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - - case 3: - if (sd->swtch && (CFN_FUNC(sd) <= FUNC_INSTANT_TRIM -#if defined(GVARS) - || CFN_FUNC(sd) >= FUNC_ADJUST_GV1 -#endif -#if defined(CPUARM) - || CFN_FUNC(sd) == FUNC_VOLUME -#endif - )) { - menu_lcd_onoff(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(sd), attr); - if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_ACTIVE(sd), 1); - } - else if (sd->swtch && HAS_REPEAT_PARAM(sd)) { - if (CFN_PLAY_REPEAT(sd) == 0) { -#if LCD_W >= 212 - lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); -#else - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '-', attr); -#endif - } -#if defined(CPUARM) - else if (CFN_PLAY_REPEAT(sd) == CFN_PLAY_REPEAT_NOSTART) { -#if LCD_W >= 212 - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN-2, y, '!', attr); - lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); -#else - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '!', attr); -#endif - } -#endif - else { - lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(sd)*CFN_PLAY_REPEAT_MUL, attr); -#if LCD_W >= 212 - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, 's', attr); -#endif - } -#if defined(CPUARM) - if (active) CFN_PLAY_REPEAT(sd) = checkIncDecModel(event, CFN_PLAY_REPEAT(sd)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(sd), -1, 60/CFN_PLAY_REPEAT_MUL); -#else - if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(sd), 60/CFN_PLAY_REPEAT_MUL); -#endif - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - } - } - } -} - -#if defined(LUA_MODEL_SCRIPTS) -void onModelCustomScriptMenu(const char *result) -{ - ScriptData &sd = g_model.scriptsData[s_currIdx]; - - if (result == STR_UPDATE_LIST) { - if (!listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), NULL)) { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - s_menu_flags = 0; - } - } - else { - // The user choosed a lua file in the list - copySelection(sd.file, result, sizeof(sd.file)); - memset(sd.inputs, 0, sizeof(sd.inputs)); - eeDirty(EE_MODEL); - LUA_LOAD_MODEL_SCRIPT(s_currIdx); - } -} - -enum menuModelCustomScriptItems { - ITEM_MODEL_CUSTOMSCRIPT_FILE, - ITEM_MODEL_CUSTOMSCRIPT_NAME, - ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL, -}; - -#define SCRIPT_ONE_2ND_COLUMN_POS (12*FW) -#define SCRIPT_ONE_3RD_COLUMN_POS (23*FW) - -void menuModelCustomScriptOne(uint8_t event) -{ - TITLE(STR_MENUCUSTOMSCRIPT); - - ScriptData &sd = g_model.scriptsData[s_currIdx]; - - putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); - - SUBMENU_NOTITLE(3+scriptInternalData[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); - - int8_t sub = m_posVert; - - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - - if (i == ITEM_MODEL_CUSTOMSCRIPT_FILE) { - lcd_putsLeft(y, "Script"); - if (ZEXIST(sd.file) > 0) - lcd_putsnAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.file, sizeof(sd.file), attr); - else - lcd_putsiAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, STR_VCSWFUNC, 0, attr); - if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && !READ_ONLY()) { - s_editMode = 0; - if (listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { - menuHandler = onModelCustomScriptMenu; - } - else { - POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); - s_menu_flags = 0; - } - } - } - else if (i == ITEM_MODEL_CUSTOMSCRIPT_NAME) { - lcd_putsLeft(y, "Name"); - editName(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.name, sizeof(sd.name), event, attr); - } - else if (i == ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL) { - lcd_putsLeft(y, "Inputs"); - } - else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInternalData[s_currIdx].inputsCount) { - int inputIdx = i-ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL-1; - lcd_putsnAtt(INDENT_WIDTH, y, scriptInternalData[s_currIdx].inputs[inputIdx].name, 10, 0); - if (scriptInternalData[s_currIdx].inputs[inputIdx].type == 0) { - lcd_outdezAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr|LEFT); - if (attr) { - CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx], scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); - } - } - else { - putsMixerSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr); - if (attr) { - uint8_t *source = (uint8_t *)&g_model.scriptsData[s_currIdx].inputs[inputIdx]; - CHECK_INCDEC_MODELSOURCE(event, *source, scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); - } - } - } - } - - if (scriptInternalData[s_currIdx].outputsCount > 0) { - lcd_vline(SCRIPT_ONE_3RD_COLUMN_POS-4, FH+1, LCD_H-FH-1); - lcd_puts(SCRIPT_ONE_3RD_COLUMN_POS, FH+1, "Outputs"); - - for (int i=0; i= 0) { - s_currIdx = sub; - pushMenu(menuModelCustomScriptOne); - } - break; - } - - for (int i=0; i= 212 - #define TELEM_COL1 (1*FW) - #define TELEM_COL2 (16*FW) - #define TELEM_COL3 (28*FW) - #define TELEM_BARS_COLMIN (3*FW+56) - #define TELEM_BARS_COLMAX (20*FW-3) - #define TELEM_SCRTYPE_COL (10*FW) -#else - #define TELEM_COL1 INDENT_WIDTH - #if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_CZ) - #define TELEM_COL2 (9*FW) - #else - #define TELEM_COL2 (8*FW) - #endif - #define TELEM_BARS_COLMIN (56-3*FW) - #define TELEM_BARS_COLMAX (14*FW-3) - #define TELEM_SCRTYPE_COL (10*FW) -#endif - -#if defined(PCBTARANIS) - #define CHANNEL_ROWS (uint8_t)-1, 1, 0, 0, 0, - #define RSSI_ROWS (uint8_t)-1, 0, 0, -#else - #define CHANNEL_ROWS (uint8_t)-1, 1, 0, 2, 2, - #define RSSI_ROWS (uint8_t)-1, 1, 1, -#endif - -#if defined(GAUGES) - #define SCREEN_TYPE_ROWS 0 -#else - #define SCREEN_TYPE_ROWS (uint8_t)-1 -#endif - -#if defined(PCBSTD) - #define VARIO_RANGE_ROWS 1 -#else - #define VARIO_RANGE_ROWS 3 -#endif - -void menuModelTelemetry(uint8_t event) -{ - MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, CHANNEL_ROWS CHANNEL_ROWS RSSI_ROWS USRDATA_LINES 0, 0, IF_CPUARM(0) IF_VARIO(LABEL(Vario)) IF_VARIO(0) IF_VARIO(VARIO_RANGE_ROWS) CASE_PCBTARANIS(LABEL(TopBar)) CASE_PCBTARANIS(0) SCREEN_TYPE_ROWS, 2, 2, 2, 2, SCREEN_TYPE_ROWS, 2, 2, 2, 2, IF_CPUARM(SCREEN_TYPE_ROWS) IF_CPUARM(2) IF_CPUARM(2) IF_CPUARM(2) IF_CPUARM(2) }); - - uint8_t sub = m_posVert - 1; - -#if !defined(PCBTARANIS) - switch (event) { - case EVT_KEY_BREAK(KEY_DOWN): - case EVT_KEY_BREAK(KEY_UP): - case EVT_KEY_BREAK(KEY_LEFT): - case EVT_KEY_BREAK(KEY_RIGHT): - if (s_editMode>0 && sub<=ITEM_TELEMETRY_RSSI_ALARM2) - frskySendAlarms(); // update FrSky module when edit mode exited - break; - } -#endif - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); - uint8_t attr = (sub == k ? blink : 0); - uint8_t ch = (k >= ITEM_TELEMETRY_A2_LABEL) ? 1 : 0; - FrSkyChannelData & channel = g_model.frsky.channels[ch]; - uint8_t dest=TELEM_A1-1+ch; - switch(k) { - case ITEM_TELEMETRY_A1_LABEL: - case ITEM_TELEMETRY_A2_LABEL: - lcd_putsLeft(y, STR_ACHANNEL); - lcd_outdezAtt(2*FW, y, ch+1, 0); - putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, frskyData.analog[ch].value, LEFT); - break; - - case ITEM_TELEMETRY_A1_RANGE: - case ITEM_TELEMETRY_A2_RANGE: - lcd_putsLeft(y, STR_RANGE); - putsTelemetryChannel(TELEM_COL2, y, dest, 255-channel.offset, (m_posHorz<=0 ? attr : 0)|NO_UNIT|LEFT); - lcd_putsiAtt(lcdLastPos, y, STR_VTELEMUNIT, channel.type, m_posHorz!=0 ? attr : 0); - if (attr && (s_editMode>0 || p1valdiff)) { - if (m_posHorz == 0) { - uint16_t ratio = checkIncDec(event, channel.ratio, 0, 256, EE_MODEL); - if (checkIncDec_Ret) { - if (ratio == 127 && channel.multiplier > 0) { - channel.multiplier--; channel.ratio = 255; - } - else if (ratio == 256) { - if (channel.multiplier < FRSKY_MULTIPLIER_MAX) { channel.multiplier++; channel.ratio = 128; } - } - else { - channel.ratio = ratio; - } - } - } - else { - CHECK_INCDEC_MODELVAR_ZERO(event, channel.type, UNIT_A1A2_MAX); - } - } - break; - - case ITEM_TELEMETRY_A1_OFFSET: - case ITEM_TELEMETRY_A2_OFFSET: - lcd_putsLeft(y, STR_OFFSET); - putsTelemetryChannel(TELEM_COL2, y, dest, 0, LEFT|attr); - if (attr) channel.offset = checkIncDec(event, channel.offset, -256, 256, EE_MODEL); - break; - - case ITEM_TELEMETRY_A1_ALARM1: - case ITEM_TELEMETRY_A1_ALARM2: - case ITEM_TELEMETRY_A2_ALARM1: - case ITEM_TELEMETRY_A2_ALARM2: - { - uint8_t j = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1) ? 0 : 1); -#if defined(PCBTARANIS) - lcd_putsLeft(y, (j==0 ? STR_LOWALARM : STR_CRITICALALARM)); - putsTelemetryChannel(TELEM_COL2, y, dest, channel.alarms_value[j], LEFT|attr); - if (attr && (s_editMode>0 || p1valdiff)) { - channel.alarms_value[j] = checkIncDec(event, channel.alarms_value[j], 0, 255, EE_MODEL); - } -#else - lcd_putsLeft(y, STR_ALARM); - lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ALARM_LEVEL(ch, j), m_posHorz<=0 ? attr : 0); - lcd_putsiAtt(TELEM_COL2+4*FW, y, STR_VALARMFN, ALARM_GREATER(ch, j), (m_posHorz<0 || m_posHorz==1) ? attr : 0); - putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, channel.alarms_value[j], ((m_posHorz<0 || m_posHorz==2) ? attr : 0) | LEFT); - - if (attr && (s_editMode>0 || p1valdiff)) { - uint8_t t; - switch (m_posHorz) { - case 0: - t = ALARM_LEVEL(ch, j); - channel.alarms_level = (channel.alarms_level & ~(3<<(2*j))) + (checkIncDecModel(event, t, 0, 3) << (2*j)); - break; - case 1: - t = ALARM_GREATER(ch, j); - if (t != checkIncDecModel(event, t, 0, 1)) { - channel.alarms_greater ^= (1 << j); - frskySendAlarms(); - } - break; - case 2: - channel.alarms_value[j] = checkIncDec(event, channel.alarms_value[j], 0, 255, EE_MODEL); - break; - } - } -#endif - break; - } - - case ITEM_TELEMETRY_RSSI_LABEL: - lcd_putsLeft(y, PSTR("RSSI")); - break; - - case ITEM_TELEMETRY_RSSI_ALARM1: - case ITEM_TELEMETRY_RSSI_ALARM2: { - uint8_t j = k-ITEM_TELEMETRY_RSSI_ALARM1; -#if defined(PCBTARANIS) - lcd_putsLeft(y, (j==0 ? STR_LOWALARM : STR_CRITICALALARM)); - lcd_outdezNAtt(TELEM_COL2, y, getRssiAlarmValue(j), LEFT|attr, 3); - if (attr && (s_editMode>0 || p1valdiff)) { - CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].value, -30, 30); - } -#else - lcd_putsLeft(y, STR_ALARM); - lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ((2+j+g_model.frsky.rssiAlarms[j].level)%4), m_posHorz<=0 ? attr : 0); - lcd_putc(TELEM_COL2+4*FW, y, '<'); - lcd_outdezNAtt(TELEM_COL2+6*FW, y, getRssiAlarmValue(j), LEFT|(m_posHorz!=0 ? attr : 0), 3); - - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].level, -3, 2); // circular (saves flash) - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].value, -30, 30); - break; - } - } -#endif - break; - } - -#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) - case ITEM_TELEMETRY_USR_LABEL: - lcd_putsLeft(y, STR_USRDATA); - break; - -#if !defined(PCBTARANIS) - case ITEM_TELEMETRY_USR_PROTO: - lcd_putsLeft(y, STR_PROTO); - lcd_putsiAtt(TELEM_COL2, y, STR_VTELPROTO, g_model.frsky.usrProto, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.usrProto, USR_PROTO_LAST); - break; -#endif - - case ITEM_TELEMETRY_USR_BLADES: - lcd_putsLeft(y, STR_BLADES); - lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 3); - break; -#endif - - case ITEM_TELEMETRY_USR_VOLTAGE_SOURCE: - lcd_putsLeft(y, STR_VOLTAGE); - lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.voltsSource+1, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.voltsSource, 3); - break; - - case ITEM_TELEMETRY_USR_CURRENT_SOURCE: - lcd_putsLeft(y, STR_CURRENT); - lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.currentSource, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.currentSource, 3); - break; - -#if defined(CPUARM) - case ITEM_TELEMTETRY_PERSISTENT_MAH: - g_model.frsky.mAhPersistent = onoffMenuItem(g_model.frsky.mAhPersistent, TELEM_COL2, y, STR_PERSISTENT_MAH, attr, event); - break; -#endif - -#if defined(VARIO) - case ITEM_TELEMETRY_VARIO_LABEL: - lcd_putsLeft(y, STR_VARIO); - break; - - case ITEM_TELEMETRY_VARIO_SOURCE: - lcd_putsLeft(y, STR_SOURCE); - lcd_putsiAtt(TELEM_COL2, y, STR_VARIOSRC, g_model.frsky.varioSource, attr); - if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioSource, 0, VARIO_SOURCE_LAST); - break; - - case ITEM_TELEMETRY_VARIO_RANGE: - lcd_putsLeft(y, STR_LIMIT); -#if defined(PCBSTD) - lcd_outdezAtt(TELEM_COL2, y, 5+g_model.frsky.varioCenterMax, (m_posHorz==0 ? attr : 0)|PREC1|LEFT); - lcd_outdezAtt(TELEM_COL2+8*FW, y, 10+g_model.frsky.varioMax, (m_posHorz==1 ? attr : 0)); - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -15, +15); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); - break; - } - } -#else - lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz<=0 ? attr : 0)|LEFT); - if (g_model.frsky.varioCenterMin == -16) - lcd_putsAtt(TELEM_COL2+4*FW-2, y, STR_OFF, m_posHorz==1 ? attr : 0); - else - lcd_outdezAtt(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((m_posHorz<0 || m_posHorz==1) ? attr : 0)|PREC1); - lcd_outdezAtt(TELEM_COL2+10*FW, y, 5+g_model.frsky.varioCenterMax, ((m_posHorz<0 || m_posHorz==2) ? attr : 0)|PREC1); - lcd_outdezAtt(TELEM_COL2+13*FW+2, y, 10+g_model.frsky.varioMax, ((m_posHorz<0 || m_posHorz==3) ? attr : 0)); - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min(10, g_model.frsky.varioCenterMax+5)); - break; - case 2: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max(-10, g_model.frsky.varioCenterMin-5), +15); - break; - case 3: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); - break; - } - } -#endif - break; -#endif - -#if defined(PCBTARANIS) - case ITEM_TELEMETRY_TOP_BAR_LABEL: - lcd_putsLeft(y, STR_TOP_BAR); - break; - - case ITEM_TELEMETRY_TOP_BAR_ALTITUDE: - g_model.frsky.altitudeDisplayed = onoffMenuItem(g_model.frsky.altitudeDisplayed, TELEM_COL2, y, STR_ALTITUDE, attr, event); - break; -#endif - - case ITEM_TELEMETRY_SCREEN_LABEL1: - case ITEM_TELEMETRY_SCREEN_LABEL2: -#if defined(CPUARM) - case ITEM_TELEMETRY_SCREEN_LABEL3: - { - uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 0 : (k < ITEM_TELEMETRY_SCREEN_LABEL3 ? 1 : 2)); - putsStrIdx(0*FW, y, STR_SCREEN, screenIndex+1); -#if defined(GAUGES) - bool screenType = IS_BARS_SCREEN(screenIndex); - if (screenType != selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VSCREEN, screenType, 0, 1, attr, event)) - g_model.frsky.screensType ^= (1 << screenIndex); -#endif - break; - } -#else - { - uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 1 : 2); - putsStrIdx(0*FW, y, STR_SCREEN, screenIndex); -#if defined(GAUGES) - bool screenType = g_model.frsky.screensType & screenIndex; - if (screenType != selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VSCREEN, screenType, 0, 1, attr, event)) - g_model.frsky.screensType ^= screenIndex; -#endif - break; - } -#endif - - case ITEM_TELEMETRY_SCREEN_LINE1: - case ITEM_TELEMETRY_SCREEN_LINE2: - case ITEM_TELEMETRY_SCREEN_LINE3: - case ITEM_TELEMETRY_SCREEN_LINE4: - case ITEM_TELEMETRY_SCREEN_LINE5: - case ITEM_TELEMETRY_SCREEN_LINE6: - case ITEM_TELEMETRY_SCREEN_LINE7: - case ITEM_TELEMETRY_SCREEN_LINE8: - -#if defined(CPUARM) - case ITEM_TELEMETRY_SCREEN_LINE9: - case ITEM_TELEMETRY_SCREEN_LINE10: - case ITEM_TELEMETRY_SCREEN_LINE11: - case ITEM_TELEMETRY_SCREEN_LINE12: -#endif - - { - uint8_t screenIndex, lineIndex; - if (k < ITEM_TELEMETRY_SCREEN_LABEL2) { - screenIndex = 0; - lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1; - } -#if defined(CPUARM) - else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) { - screenIndex = 2; - lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9; - } -#endif - else { - screenIndex = 1; - lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5; - } - -#if 0 - putsStrIdx(0, y, PSTR(INDENT"Line"), lineIndex+1, m_posHorz<0 ? attr : 0); -#endif - -#if defined(GAUGES) - if (IS_BARS_SCREEN(screenIndex)) { - FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex]; - uint8_t barSource = bar.source; - lcd_putsiAtt(TELEM_COL1, y, STR_VTELEMCHNS, barSource, m_posHorz==0 ? attr : 0); - if (barSource) { - putsTelemetryChannel(TELEM_BARS_COLMIN, y, barSource-1, convertTelemValue(barSource, bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT); - putsTelemetryChannel(TELEM_BARS_COLMAX, y, barSource-1, convertTelemValue(barSource, 255-bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT); - } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - bar.source = checkIncDecModel(event, barSource, 0, TELEM_DISPLAY_MAX); - if (checkIncDec_Ret) { - bar.barMin = 0; - bar.barMax = 255-maxTelemValue(bar.source); - } - break; - case 1: - bar.barMin = checkIncDec(event, bar.barMin, 0, 254-bar.barMax, EE_MODEL|NO_INCDEC_MARKS); - break; - case 2: - bar.barMax = 255 - checkIncDec(event, 255-bar.barMax, bar.barMin+1, maxTelemValue(barSource), EE_MODEL|NO_INCDEC_MARKS); - break; - } - } - } - else -#endif - { - for (uint8_t c=0; c0 || p1valdiff)) { - CHECK_INCDEC_MODELVAR_ZERO(event, value, (lineIndex==3 && c==0) ? TELEM_STATUS_MAX : TELEM_DISPLAY_MAX); - } - } - if (attr && m_posHorz == NUM_LINE_ITEMS) { - REPEAT_LAST_CURSOR_MOVE(); - } - } - break; - } - } - } -} -#endif - -#if defined(TEMPLATES) -void menuModelTemplates(uint8_t event) -{ - SIMPLE_MENU(STR_MENUTEMPLATES, menuTabModel, e_Templates, 1+TMPL_COUNT); - - uint8_t sub = m_posVert - 1; - - if (sub < TMPL_COUNT) { - if (s_warning_result) { - s_warning_result = 0; - applyTemplate(sub); - AUDIO_WARNING2(); - } - if (event==EVT_KEY_BREAK(KEY_ENTER)) { - POPUP_CONFIRMATION(STR_VTEMPLATES+1 + (sub * LEN2_VTEMPLATES)); - s_editMode = 0; - } - } - - uint8_t y = 1 + 1*FH; - uint8_t k = 0; - for (uint8_t i=0; i frskyData.hub.maxRpm) diff --git a/radio/src/telemetry/frsky.cpp~ b/radio/src/telemetry/frsky.cpp~ deleted file mode 100644 index 35d3bf5cc..000000000 --- a/radio/src/telemetry/frsky.cpp~ +++ /dev/null @@ -1,926 +0,0 @@ -/* - * Authors (alphabetical order) - * - Andre Bernet - * - Andreas Weitl - * - Bertrand Songis - * - Bryan J. Rentoul (Gruvin) - * - Cameron Weeks - * - Erez Raviv - * - Gabriel Birkus - * - Jean-Pierre Parisy - * - Karl Szmutny - * - Michael Blandford - * - Michal Hlavinka - * - Pat Mackenzie - * - Philip Moss - * - Rob Thomson - * - Romolo Manfredini - * - Thomas Husterer - * - * opentx is based on code named - * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, - * er9x by Erez Raviv: http://code.google.com/p/er9x/, - * and the original (and ongoing) project by - * Thomas Husterer, th9x: http://code.google.com/p/th9x/ - * - * 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" - -// Enumerate FrSky packet codes -#define LINKPKT 0xfe -#define USRPKT 0xfd -#define A11PKT 0xfc -#define A12PKT 0xfb -#define A21PKT 0xfa -#define A22PKT 0xf9 -#define ALRM_REQUEST 0xf8 -#define RSSI1PKT 0xf7 -#define RSSI2PKT 0xf6 -#define RSSI_REQUEST 0xf1 - -#define START_STOP 0x7e -#define BYTESTUFF 0x7d -#define STUFF_MASK 0x20 - -#if defined(TELEMETREZ) -#define PRIVATE 0x1B -#endif - -uint8_t frskyRxBuffer[FRSKY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) -uint8_t frskyTxBuffer[FRSKY_TX_PACKET_SIZE]; // Ditto for transmit buffer -#if !defined(CPUARM) -uint8_t frskyTxBufferCount = 0; -#endif -uint8_t frskyStreaming = 0; -#if defined(WS_HOW_HIGH) -uint8_t frskyUsrStreaming = 0; -#endif -uint8_t link_counter = 0; -FrskyData frskyData; - -#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) -void checkMinMaxAltitude() -{ - if (TELEMETRY_ALT_BP > frskyData.hub.maxAltitude) - frskyData.hub.maxAltitude = TELEMETRY_ALT_BP; - if (TELEMETRY_ALT_BP < frskyData.hub.minAltitude) - frskyData.hub.minAltitude = TELEMETRY_ALT_BP; -} -#endif - -#if defined(VARIO) && !defined(FRSKY_SPORT) && (defined(FRSKY_HUB) || defined(WS_HOW_HIGH)) -void evalVario(int16_t altitude_bp, uint16_t altitude_ap) -{ - int32_t varioAltitude_cm = (int32_t)altitude_bp * 100 + (altitude_bp > 0 ? altitude_ap : -altitude_ap); - uint8_t varioAltitudeQueuePointer = frskyData.hub.varioAltitudeQueuePointer + 1; - if (varioAltitudeQueuePointer >= VARIO_QUEUE_LENGTH) - varioAltitudeQueuePointer = 0; - frskyData.hub.varioAltitudeQueuePointer = varioAltitudeQueuePointer; - frskyData.hub.varioSpeed -= frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] ; - frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] = varioAltitude_cm - frskyData.hub.varioAltitude_cm; - frskyData.hub.varioAltitude_cm = varioAltitude_cm; - frskyData.hub.varioSpeed += frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] ; -} -#else -#define evalVario(...) -#endif - -#if defined(FRSKY_HUB) -typedef enum { - TS_IDLE = 0, // waiting for 0x5e frame marker - TS_DATA_ID, // waiting for dataID - TS_DATA_LOW, // waiting for data low byte - TS_DATA_HIGH, // waiting for data high byte - TS_XOR = 0x80 // decode stuffed byte -} TS_STATE; - -void parseTelemHubByte(uint8_t byte) -{ - static int8_t structPos; - static uint8_t lowByte; - static TS_STATE state = TS_IDLE; - - if (byte == 0x5e) { - state = TS_DATA_ID; - return; - } - if (state == TS_IDLE) { - return; - } - if (state & TS_XOR) { - byte = byte ^ 0x60; - state = (TS_STATE)(state - TS_XOR); - } - if (byte == 0x5d) { - state = (TS_STATE)(state | TS_XOR); - return; - } - if (state == TS_DATA_ID) { - if (byte > 0x3f) { - state = TS_IDLE; - } - else { - structPos = byte*2; - state = TS_DATA_LOW; - } - return; - } - if (state == TS_DATA_LOW) { - lowByte = byte; - state = TS_DATA_HIGH; - return; - } - - state = TS_IDLE; - -#if defined(GPS) - if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLatitude_bp)) { - if (lowByte || byte) - frskyData.hub.gpsFix = 1; - else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLatitude_bp > 1) - frskyData.hub.gpsFix = 0; - } - else if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLongitude_bp)) { - if (lowByte || byte) - frskyData.hub.gpsFix = 1; - else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLongitude_bp > 1) - frskyData.hub.gpsFix = 0; - } - - if ((uint8_t)structPos == offsetof(FrskySerialData, gpsAltitude_bp) || - ((uint8_t)structPos >= offsetof(FrskySerialData, gpsAltitude_ap) && (uint8_t)structPos <= offsetof(FrskySerialData, gpsLatitudeNS) && (uint8_t)structPos != offsetof(FrskySerialData, baroAltitude_bp) && (uint8_t)structPos != offsetof(FrskySerialData, baroAltitude_ap))) { - // If we don't have a fix, we may discard the value - if (frskyData.hub.gpsFix <= 0) - return; - } -#endif - -#if 0 - uint16_t previousValue = *((uint16_t *)(((uint8_t*)&frskyData.hub) + structPos)); -#endif - - ((uint8_t*)&frskyData.hub)[structPos] = lowByte; - ((uint8_t*)&frskyData.hub)[structPos+1] = byte; - - switch ((uint8_t)structPos) { - - case offsetof(FrskySerialData, rpm): - //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); - // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley - // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing - // - frskyData.hub.rpm *= (uint8_t)60; - frskyData.hub.rpm /= (g_model.frsky.blades+1); - float gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); - frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); - if (frskyData.hub.rpm > frskyData.hub.maxRpm) - frskyData.hub.maxRpm = frskyData.hub.rpm; - break; - - case offsetof(FrskySerialData, temperature1): - if (frskyData.hub.temperature1 > frskyData.hub.maxTemperature1) - frskyData.hub.maxTemperature1 = frskyData.hub.temperature1; - break; - - case offsetof(FrskySerialData, temperature2): - if (frskyData.hub.temperature2 > frskyData.hub.maxTemperature2) - frskyData.hub.maxTemperature2 = frskyData.hub.temperature2; - break; - - case offsetof(FrskySerialData, current): - if (frskyData.hub.current > frskyData.hub.maxCurrent) - frskyData.hub.maxCurrent = frskyData.hub.current; - break; - - case offsetof(FrskySerialData, currentConsumption): - // we receive data from openXsensor. stops the calculation of consumption and power - frskyData.hub.openXsensor = 1; - break; - - case offsetof(FrskySerialData, volts_ap): -#if defined(FAS_BSS) - frskyData.hub.vfas = (frskyData.hub.volts_bp * 10 + frskyData.hub.volts_ap); -#else - frskyData.hub.vfas = ((frskyData.hub.volts_bp * 100 + frskyData.hub.volts_ap * 10) * 21) / 110; -#endif - /* TODO later if (!frskyData.hub.minVfas || frskyData.hub.minVfas > frskyData.hub.vfas) - frskyData.hub.minVfas = frskyData.hub.vfas; */ - break; - - case offsetof(FrskySerialData, baroAltitude_bp): - // First received barometer altitude => Altitude offset - if (!frskyData.hub.baroAltitudeOffset) - frskyData.hub.baroAltitudeOffset = -frskyData.hub.baroAltitude_bp; - if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI) { - evalVario(frskyData.hub.baroAltitude_bp, 0); - } - frskyData.hub.baroAltitude_bp += frskyData.hub.baroAltitudeOffset; - checkMinMaxAltitude(); - break; - - case offsetof(FrskySerialData, baroAltitude_ap): - if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI_PLUS) { - evalVario(frskyData.hub.baroAltitude_bp-frskyData.hub.baroAltitudeOffset, frskyData.hub.baroAltitude_ap); - } - break; - -#if defined(GPS) - case offsetof(FrskySerialData, gpsAltitude_ap): - if (!frskyData.hub.gpsAltitudeOffset) - frskyData.hub.gpsAltitudeOffset = -frskyData.hub.gpsAltitude_bp; - frskyData.hub.gpsAltitude_bp += frskyData.hub.gpsAltitudeOffset; - if (!frskyData.hub.baroAltitudeOffset) { - if (frskyData.hub.gpsAltitude_bp > frskyData.hub.maxAltitude) - frskyData.hub.maxAltitude = frskyData.hub.gpsAltitude_bp; - if (frskyData.hub.gpsAltitude_bp < frskyData.hub.minAltitude) - frskyData.hub.minAltitude = frskyData.hub.gpsAltitude_bp; - } - if (!frskyData.hub.pilotLatitude && !frskyData.hub.pilotLongitude) { - // First received GPS position => Pilot GPS position - getGpsPilotPosition(); - } - else if (frskyData.hub.gpsDistNeeded || g_menuStack[g_menuStackPtr] == menuTelemetryFrsky) { - getGpsDistance(); - } - break; - - case offsetof(FrskySerialData, gpsSpeed_bp): - // Speed => Max speed - if (frskyData.hub.gpsSpeed_bp > frskyData.hub.maxGpsSpeed) - frskyData.hub.maxGpsSpeed = frskyData.hub.gpsSpeed_bp; - break; -#endif - - case offsetof(FrskySerialData, volts): - // Voltage => Cell number + Cell voltage - { - uint8_t battnumber = ((frskyData.hub.volts & 0x00F0) >> 4); - if (battnumber < 12) { - if (frskyData.hub.cellsCount < battnumber+1) { - frskyData.hub.cellsCount = battnumber+1; - } - uint8_t cellVolts = (uint8_t)(((((frskyData.hub.volts & 0xFF00) >> 8) + ((frskyData.hub.volts & 0x000F) << 8)))/10); - frskyData.hub.cellVolts[battnumber] = cellVolts; - if (!frskyData.hub.minCellVolts || cellVolts < frskyData.hub.minCellVolts || battnumber==frskyData.hub.minCellIdx) { - frskyData.hub.minCellIdx = battnumber; - frskyData.hub.minCellVolts = cellVolts; - } - } - break; - } - -#if defined(GPS) - case offsetof(FrskySerialData, hour): - frskyData.hub.hour = ((uint8_t)(frskyData.hub.hour + g_eeGeneral.timezone + 24)) % 24; - break; -#endif - - case offsetof(FrskySerialData, accelX): - case offsetof(FrskySerialData, accelY): - case offsetof(FrskySerialData, accelZ): - *(int16_t*)(&((uint8_t*)&frskyData.hub)[structPos]) /= 10; - break; - -#if 0 - case offsetof(FrskySerialData, gpsAltitude_bp): - case offsetof(FrskySerialData, fuelLevel): - case offsetof(FrskySerialData, gpsLongitude_bp): - case offsetof(FrskySerialData, gpsLatitude_bp): - case offsetof(FrskySerialData, gpsCourse_bp): - case offsetof(FrskySerialData, day): - case offsetof(FrskySerialData, year): - case offsetof(FrskySerialData, sec): - case offsetof(FrskySerialData, gpsSpeed_ap): - case offsetof(FrskySerialData, gpsLongitude_ap): - case offsetof(FrskySerialData, gpsLatitude_ap): - case offsetof(FrskySerialData, gpsCourse_ap): - case offsetof(FrskySerialData, gpsLongitudeEW): - case offsetof(FrskySerialData, gpsLatitudeNS): - case offsetof(FrskySerialData, varioSpeed): - case offsetof(FrskySerialData, power): /* because sent by openXsensor */ - case offsetof(FrskySerialData, vfas): - case offsetof(FrskySerialData, volts_bp): - break; - - default: - *((uint16_t *)(((uint8_t*)&frskyData.hub) + structPos)) = previousValue; - break; -#endif - } -} -#endif - -#if defined(WS_HOW_HIGH) -void parseTelemWSHowHighByte(uint8_t byte) -{ - if (frskyUsrStreaming < (FRSKY_TIMEOUT10ms*3 - 10)) { - ((uint8_t*)&frskyData.hub)[offsetof(FrskySerialData, baroAltitude_bp)] = byte; - checkMinMaxAltitude(); - if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI) { - evalVario(frskyData.hub.baroAltitude_bp, 0); - } - } - else { - // At least 100mS passed since last data received - ((uint8_t*)&frskyData.hub)[offsetof(FrskySerialData, baroAltitude_bp)+1] = byte; - } - // baroAltitude_bp unit here is feet! - frskyUsrStreaming = FRSKY_TIMEOUT10ms*3; // reset counter -} -#endif - -void processFrskyPacket(uint8_t *packet) -{ - // What type of packet? - switch (packet[0]) - { - case LINKPKT: // A1/A2/RSSI values - { - link_counter += 32; - frskyData.analog[0].set(packet[1], g_model.frsky.channels[0].type); - frskyData.analog[1].set(packet[2], g_model.frsky.channels[1].type); - frskyData.rssi[0].set(packet[3]); - frskyData.rssi[1].set(packet[4] / 2); - frskyStreaming = FRSKY_TIMEOUT10ms; // reset counter only if valid frsky packets are being detected -#if defined(VARIO) - uint8_t varioSource = g_model.frsky.varioSource - VARIO_SOURCE_A1; - if (varioSource < 2) - frskyData.hub.varioSpeed = applyChannelRatio(varioSource, frskyData.analog[varioSource].value); -#endif - break; - } -#if defined(FRSKY_HUB) || defined (WS_HOW_HIGH) - case USRPKT: // User Data packet - uint8_t numBytes = 3 + (packet[1] & 0x07); // sanitize in case of data corruption leading to buffer overflow - for (uint8_t i=3; i>1) * (voltage>>1)) / 25; -#endif - - frskyData.hub.currentPrescale += current; - if (frskyData.hub.currentPrescale >= 3600) { - frskyData.hub.currentConsumption += 1; - frskyData.hub.currentPrescale -= 3600; - } - } - - if (frskyData.hub.power > frskyData.hub.maxPower) - frskyData.hub.maxPower = frskyData.hub.power; - } -} - -void telemetryWakeup() -{ -#if defined(PCBSKY9X) - rxPdcUsart(processSerialData); // Receive serial data here -#endif - - // Attempt to transmit any waiting Fr-Sky alarm set packets every 50ms (subject to packet buffer availability) - static uint8_t frskyTxDelay = 5; - if (frskyAlarmsSendState && (--frskyTxDelay == 0)) { - frskyTxDelay = 5; // 50ms - frskySendNextAlarm(); - } - -#ifndef SIMU -#if defined(WS_HOW_HIGH) - if (frskyUsrStreaming > 0) { - frskyUsrStreaming--; - } -#endif - - if (frskyStreaming > 0) { - frskyStreaming--; - } - else { - frskyData.rssi[0].set(0); - frskyData.rssi[1].set(0); - } -#endif - -#if defined(VARIO) - if (TELEMETRY_STREAMING() && !IS_FAI_ENABLED()) - varioWakeup(); -#endif -} - -#if 0 -// not used any more -bool FRSKY_alarmRaised(uint8_t idx) -{ - for (int i=0; i<2; i++) { - if (ALARM_LEVEL(idx, i) != alarm_off) { - if (ALARM_GREATER(idx, i)) { - if (frskyData.analog[idx].value > g_model.frsky.channels[idx].alarms_value[i]) - return true; - } - else { - if (frskyData.analog[idx].value < g_model.frsky.channels[idx].alarms_value[i]) - return true; - } - } - } - return false; -} -#endif - -#if !defined(CPUARM) -inline void FRSKY_EnableTXD(void) -{ - frskyTxBufferCount = 0; - UCSR0B |= (1 << TXEN0); // enable TX -} - -inline void FRSKY_EnableRXD(void) -{ - UCSR0B |= (1 << RXEN0); // enable RX - UCSR0B |= (1 << RXCIE0); // enable Interrupt -} -#endif - -void FRSKY_Init(void) -{ - // clear frsky variables - resetTelemetry(); - -#if defined(PCBTARANIS) - // TODO -#elif defined(PCBSKY9X) - startPdcUsartReceive() ; -#elif !defined(SIMU) - - DDRE &= ~(1 << DDE0); // set RXD0 pin as input - PORTE &= ~(1 << PORTE0); // disable pullup on RXD0 pin - -#undef BAUD -#define BAUD 9600 -#include - - UBRR0H = UBRRH_VALUE; - UBRR0L = UBRRL_VALUE; - UCSR0A &= ~(1 << U2X0); // disable double speed operation. - - // set 8N1 - UCSR0B = 0 | (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (0 << RXEN0) | (0 << TXEN0) | (0 << UCSZ02); - UCSR0C = 0 | (1 << UCSZ01) | (1 << UCSZ00); - - - while (UCSR0A & (1 << RXC0)) UDR0; // flush receive buffer - - // These should be running right from power up on a FrSky enabled '9X. - FRSKY_EnableTXD(); // enable FrSky-Telemetry reception - FRSKY_EnableRXD(); // enable FrSky-Telemetry reception -#endif -} - -void FrskyValueWithMin::set(uint8_t value) -{ - if (this->value == 0) { - this->value = value; - } - else { - sum += value; - if (link_counter == 0) { - this->value = sum / 8; - sum = 0; - } - } - - if (value && (!min || value < min)) - min = value; -} - -void FrskyValueWithMinMax::set(uint8_t value, uint8_t unit) -{ - FrskyValueWithMin::set(value); - if (unit != UNIT_VOLTS) { - this->value = value; - } - if (!max || value > max) - max = value; -} - -void resetTelemetry() -{ - memclear(&frskyData, sizeof(frskyData)); - -#if defined(FRSKY_HUB) - frskyData.hub.gpsLatitude_bp = 2; - frskyData.hub.gpsLongitude_bp = 2; - frskyData.hub.gpsFix = -1; -#endif - -#ifdef SIMU - frskyData.analog[0].set(120, UNIT_VOLTS); - frskyData.analog[1].set(240, UNIT_VOLTS); - frskyData.rssi[0].value = 75; - frskyData.rssi[1].value = 75; - frskyData.hub.fuelLevel = 75; - frskyData.hub.rpm = 12000; - -#if defined(GPS) - frskyData.hub.gpsFix = 1; - frskyData.hub.gpsLatitude_bp = 4401; - frskyData.hub.gpsLatitude_ap = 7710; - frskyData.hub.gpsLongitude_bp = 1006; - frskyData.hub.gpsLongitude_ap = 8872; - frskyData.hub.gpsSpeed_bp = (100 * 250) / 463; - getGpsPilotPosition(); - - frskyData.hub.gpsLatitude_bp = 4401; - frskyData.hub.gpsLatitude_ap = 7455; - frskyData.hub.gpsLongitude_bp = 1006; - frskyData.hub.gpsLongitude_ap = 9533; - getGpsDistance(); -#endif - - frskyData.hub.cellsCount = 6; - - frskyData.hub.gpsAltitude_bp = 50; - frskyData.hub.baroAltitude_bp = 50; - frskyData.hub.minAltitude = 10; - frskyData.hub.maxAltitude = 500; - - frskyData.hub.accelY = 100; - frskyData.hub.temperature1 = -30; - frskyData.hub.maxTemperature1 = 100; - - frskyData.hub.current = 5; - frskyData.hub.maxCurrent = 56; -#endif -} diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index 8499cb5f8..cf34b6198 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -179,11 +179,21 @@ void processHubPacket(uint8_t id, uint16_t value) } ((uint16_t*)&frskyData.hub)[id] = value; + float gear_ratio = 1; switch (id) { case RPM_ID: - frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + + // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley + // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing + // + frskyData.hub.rpm *= (uint8_t)60; + frskyData.hub.rpm /= (g_model.frsky.blades+1); + gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); + frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); + if (frskyData.hub.rpm > frskyData.hub.maxRpm) frskyData.hub.maxRpm = frskyData.hub.rpm; break; From 8b739815e3ac45175a4b5eab2728583b9c6c05da Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 21:08:27 -0500 Subject: [PATCH 27/43] Update README.txt --- README.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/README.txt b/README.txt index 6dcc5a26f..e6280ca4d 100644 --- a/README.txt +++ b/README.txt @@ -2,7 +2,6 @@ Add Gear Ratio to RPM Telemetry Calculation and allow for Blades to equal 1 Jan 16 2014 - Switched to 'next' branch -- Need to solve issue with frsky_sport.cpp and calc compile error - Need to translate "Spur" and "Gear" to other languages, using English as placeholder for now. From 753c5e3119959e5d5db2ba7ffd81bc481e2b483d Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 21:54:21 -0500 Subject: [PATCH 28/43] Remove accidental file --- .gitignore | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 4b4d86a64..000000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.[oa] -*~ -opentx.bin -opentx.elf -opentx.lst -opentx.map - From 28fad3a306a93353c7874b902e2a3a56b6be1c88 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 19:58:18 -0500 Subject: [PATCH 29/43] Cleaned up comments --- radio/src/gui/menu_model.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index 681aaa22f..4dad2c5c8 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -5164,8 +5164,8 @@ enum menuModelTelemetryItems { ITEM_TELEMETRY_USR_PROTO, #endif ITEM_TELEMETRY_USR_BLADES, - ITEM_TELEMETRY_USR_SPUR_GEAR, // T.Foley - ITEM_TELEMETRY_USR_PINION_GEAR, // T.Foley + ITEM_TELEMETRY_USR_SPUR_GEAR, + ITEM_TELEMETRY_USR_PINION_GEAR, #endif ITEM_TELEMETRY_USR_VOLTAGE_SOURCE, ITEM_TELEMETRY_USR_CURRENT_SOURCE, @@ -5202,8 +5202,7 @@ enum menuModelTelemetryItems { }; #if defined(PCBTARANIS) - //#define USRDATA_LINES (uint8_t)-1, 0, - #define USRDATA_LINES (uint8_t)-1, 0, 0, 0, // T.Foley - Add room for two new gearing options + #define USRDATA_LINES (uint8_t)-1, 0, 0, 0, #elif defined(FRSKY_HUB) || defined(WS_HOW_HIGH) #define USRDATA_LINES (uint8_t)-1, 0, 0, #else @@ -5406,20 +5405,18 @@ void menuModelTelemetry(uint8_t event) case ITEM_TELEMETRY_USR_BLADES: lcd_putsLeft(y, STR_BLADES); - //lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); - lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.blades, LEFT|attr); // T.Foley - //if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 3); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 254); // T.Foley + lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.blades, LEFT|attr); + if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 254); break; - case ITEM_TELEMETRY_USR_SPUR_GEAR: // T.Foley + case ITEM_TELEMETRY_USR_SPUR_GEAR: lcd_putsLeft(y, STR_SPURGEAR); lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.spur_gear, LEFT|attr); // Spur gear must be greater than or equal to pinion to prevent floating point error if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.spur_gear, g_model.frsky.pinion_gear, 254); break; - case ITEM_TELEMETRY_USR_PINION_GEAR: // T.Foley + case ITEM_TELEMETRY_USR_PINION_GEAR: lcd_putsLeft(y, STR_PINIONGEAR); lcd_outdezAtt(TELEM_COL2, y, 1+g_model.frsky.pinion_gear, LEFT|attr); // Pinion gear ,ust be less than or equal to spur gear to prevent floating point error From 4dc9194a36a3359ca0633d27dbdafc80a71be224 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 19:58:59 -0500 Subject: [PATCH 30/43] Cleaned up comments --- radio/src/myeeprom.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 04ad423fb..6f8671e71 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -976,7 +976,7 @@ PACK(typedef struct t_FrSkyData { uint8_t usrProto; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon uint8_t voltsSource:7; uint8_t altitudeDisplayed:1; - uint8_t blades; // How many blades for RPMs, 0=1 blades, 1=2 blades // T.Foley + uint8_t blades; // How many blades for RPMs, 0=1 blades, 1=2 blades uint8_t currentSource; uint8_t screensType; FrSkyScreenData screens[MAX_FRSKY_SCREENS]; @@ -989,15 +989,15 @@ PACK(typedef struct t_FrSkyData { uint16_t mAhPersistent:1; uint16_t storedMah:15; int8_t fasOffset; - uint8_t spur_gear; // How many teeth on Spur Gear for Headspeed Calc. T.Foley - uint8_t pinion_gear; // How many teeth on Pinion Gear for Headspeed Calc. T.Foley + uint8_t spur_gear; + uint8_t pinion_gear; }) FrSkyData; #else #define MAX_FRSKY_SCREENS 2 PACK(typedef struct t_FrSkyData { FrSkyChannelData channels[2]; uint8_t usrProto:2; // Protocol in FrSky user data, 0=None, 1=FrSky hub, 2=WS HowHigh, 3=Halcyon - uint8_t blades:2; // How many blades for RPMs, 0=1 blades, 1=2 blades // T.Foley + uint8_t blades:2; // How many blades for RPMs, 0=1 blades, 1=2 blades uint8_t screensType:2; uint8_t voltsSource:2; int8_t varioMin:4; @@ -1009,8 +1009,8 @@ PACK(typedef struct t_FrSkyData { uint8_t currentSource:3; int8_t varioCenterMax:5; int8_t fasOffset; - uint8_t spur_gear; // How many teeth on Spur Gear for Headspeed Calc. T.Foley - uint8_t pinion_gear; // How many teeth on Pinion Gear for Headspeed Calc. T.Foley + uint8_t spur_gear; + uint8_t pinion_gear; }) FrSkyData; #endif From 1b46c806131f155dc8a37d79f2c07c9e2ffaa7c5 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 19:59:30 -0500 Subject: [PATCH 31/43] Cleaned up comments --- radio/src/simu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 8fabf48f8..51ef32b73 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -338,7 +338,7 @@ void Open9xSim::refreshDiplay() bmp->render(); bmf->setImage(bmp); - // Recalc RPM based on Blades setting during simulator - T.Foley + // Recalc RPM based on Blades setting during simulator // Final value will change as user adjusts blades, spur or gear live in simulator frskyData.hub.rpm = 303; frskyData.hub.rpm *= (uint8_t)60; From ff876880d5150be5fb039c6114929cbe572c1c3d Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:00:11 -0500 Subject: [PATCH 32/43] Cleaned up comments --- radio/src/telemetry/frsky.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp index 4147d1693..54768146f 100644 --- a/radio/src/telemetry/frsky.cpp +++ b/radio/src/telemetry/frsky.cpp @@ -176,10 +176,6 @@ void parseTelemHubByte(uint8_t byte) switch ((uint8_t)structPos) { case offsetof(FrskySerialData, rpm): - //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); - // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley - // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing - // frskyData.hub.rpm *= (uint8_t)60; frskyData.hub.rpm /= (g_model.frsky.blades+1); gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); From 30dd3cd41dea4279609aeea73a49f4af55d49f6b Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:00:39 -0500 Subject: [PATCH 33/43] Cleaned up comments --- radio/src/telemetry/frsky_sport.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index cf34b6198..eed3c3951 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -184,16 +184,10 @@ void processHubPacket(uint8_t id, uint16_t value) switch (id) { case RPM_ID: - //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); - - // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley - // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing - // frskyData.hub.rpm *= (uint8_t)60; frskyData.hub.rpm /= (g_model.frsky.blades+1); gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); - if (frskyData.hub.rpm > frskyData.hub.maxRpm) frskyData.hub.maxRpm = frskyData.hub.rpm; break; From 392169591c61c3d98d7a578fbd20fa2aa1d5ede1 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:00:55 -0500 Subject: [PATCH 34/43] Cleaned up comments --- radio/src/translations.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 3e1ef09c7..cd553c1a7 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -185,8 +185,8 @@ const pm_char STR_BAR[] PROGMEM = TR_BAR; const pm_char STR_ALARM[] PROGMEM = TR_ALARM; const pm_char STR_USRDATA[] PROGMEM = TR_USRDATA; const pm_char STR_BLADES[] PROGMEM = TR_BLADES; -const pm_char STR_SPURGEAR[] PROGMEM = TR_SPURGEAR; // T.Foley -const pm_char STR_PINIONGEAR[] PROGMEM = TR_PINIONGEAR; // T.Foley +const pm_char STR_SPURGEAR[] PROGMEM = TR_SPURGEAR; +const pm_char STR_PINIONGEAR[] PROGMEM = TR_PINIONGEAR; const pm_char STR_SCREEN[] PROGMEM = TR_SCREEN; const pm_char STR_SOUND_LABEL[] PROGMEM = TR_SOUND_LABEL; const pm_char STR_LENGTH[] PROGMEM = TR_LENGTH; From 2107f25765a1e91645efbd639d78332b86bb4591 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:01:04 -0500 Subject: [PATCH 35/43] Cleaned up comments --- radio/src/translations.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations.h b/radio/src/translations.h index b49bb005d..d5abf15f7 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -343,8 +343,8 @@ extern const pm_char STR_BAR[]; extern const pm_char STR_ALARM[]; extern const pm_char STR_USRDATA[]; extern const pm_char STR_BLADES[]; -extern const pm_char STR_SPURGEAR[]; // T.Foley -extern const pm_char STR_PINIONGEAR[]; // T.Foley +extern const pm_char STR_SPURGEAR[]; +extern const pm_char STR_PINIONGEAR[]; extern const pm_char STR_SCREEN[]; extern const pm_char STR_SOUND_LABEL[]; extern const pm_char STR_LENGTH[]; From 770b95507e5749d2eb519b7bf0388b76e2002cde Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:01:23 -0500 Subject: [PATCH 36/43] Cleaned up comments --- radio/src/translations/cz.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 9c84a4119..529895d7a 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -443,8 +443,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA TR("UživData", "Uživ. data") #define TR_BLADES TR(INDENT"ListyVrt", INDENT"Listy vrtule") -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Panel " #define TR_SOUND_LABEL "Zvuk" #define TR_LENGTH INDENT"Délka" From bbb9a4ceda0fae2da00f8832cd14feac5da8aa1e Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:01:34 -0500 Subject: [PATCH 37/43] Cleaned up comments --- 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 694f8ce18..9df6b6953 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -443,8 +443,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA "Daten" #define TR_BLADES INDENT"Bl\201tter" -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Bild " #define TR_SOUND_LABEL "T\203ne" #define TR_LENGTH INDENT"Dauer" From 7e164f4b8d1c8604c82ecbe88ff06acca1a08705 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:01:46 -0500 Subject: [PATCH 38/43] Cleaned up comments --- radio/src/translations/en.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 86c4f48cf..bcc9c50d0 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -447,8 +447,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA "UsrData" #define TR_BLADES INDENT"Blades" -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Screen " #define TR_SOUND_LABEL "Sound" #define TR_LENGTH INDENT"Length" From d790fa3d4b97cc4b9e4f01aef06b9a71858d5ad0 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:01:59 -0500 Subject: [PATCH 39/43] Cleaned up comments --- radio/src/translations/fr.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index 0e363f3f4..b0c3cc463 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -443,8 +443,8 @@ #define TR_ALARM INDENT"Alarme" #define TR_USRDATA "Données" #define TR_BLADES INDENT"Pales" -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Ecran " #define TR_SOUND_LABEL "Son" #define TR_LENGTH INDENT"Durée" From c7d84f741dbd6e9c3c96627460df0e806b9495b0 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:02:13 -0500 Subject: [PATCH 40/43] Cleaned up comments --- radio/src/translations/it.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 2f06e0524..7c607a1f7 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -443,8 +443,8 @@ #define TR_ALARM INDENT"Allarme" #define TR_USRDATA "Dati" #define TR_BLADES INDENT"Pale" -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Schermo " #define TR_SOUND_LABEL "Suono" #define TR_LENGTH INDENT"Durata" From b44879a7e17c0b77864c855a1eee3c075b38767c Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:02:22 -0500 Subject: [PATCH 41/43] Cleaned up comments --- radio/src/translations/pl.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index c9b533b7b..a91cc44a3 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -444,8 +444,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA TR("Dane Użytk.", "Dane użytkownika") #define TR_BLADES TR(INDENT"Łopaty śmigla", INDENT"Łopaty śmigła") -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Ekran " #define TR_SOUND_LABEL "Dźwięk" #define TR_LENGTH INDENT"Długość" From 522e0cd1f6cd8833220efb34bf16ef7a499bfe2e Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:02:32 -0500 Subject: [PATCH 42/43] Cleaned up comments --- radio/src/translations/pt.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index fa8c8b1dd..1a39216b0 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -443,8 +443,8 @@ #define TR_ALARM INDENT"Alarme" #define TR_USRDATA "UsrData" #define TR_BLADES INDENT"Helice" -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Tela" #define TR_SOUND_LABEL "Som" #define TR_LENGTH INDENT"Comprimento" From dfad662f18f1deabcd96cd8d8bf89ce3e880714d Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Mon, 20 Jan 2014 20:02:44 -0500 Subject: [PATCH 43/43] Cleaned up comments --- radio/src/translations/se.h.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 796c10fa4..d034d8b94 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -443,8 +443,8 @@ #define TR_ALARM INDENT"Alarm" #define TR_USRDATA "Användardata" #define TR_BLADES INDENT"Blad" -#define TR_SPURGEAR INDENT"Spur Gear" // T.Foley -#define TR_PINIONGEAR INDENT"Pinion Gear" // T.Foley +#define TR_SPURGEAR INDENT"Spur Gear" +#define TR_PINIONGEAR INDENT"Pinion Gear" #define TR_SCREEN "Skärm" #define TR_SOUND_LABEL "Ljud " #define TR_LENGTH INDENT"Tid"