diff --git a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp index 992ece1c4..35be1eae4 100644 --- a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp @@ -100,6 +100,7 @@ inline int geteepromsize() { #include "radio/src/gui/menu_model_logical_switches.cpp" #include "radio/src/gui/menu_model_custom_functions.cpp" #include "radio/src/gui/menu_model_custom_scripts.cpp" +#include "radio/src/gui/menu_model_gvars.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" diff --git a/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp index 90f958357..4fb00cf08 100755 --- a/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp @@ -102,6 +102,7 @@ inline int geteepromsize() { #include "radio/src/gui/menu_model_logical_switches.cpp" #include "radio/src/gui/menu_model_custom_functions.cpp" #include "radio/src/gui/menu_model_custom_scripts.cpp" +#include "radio/src/gui/menu_model_gvars.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" diff --git a/radio/src/Makefile b/radio/src/Makefile index 1e0fc28f3..88f0df201 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -1021,6 +1021,7 @@ endif ifeq ($(GVARS), YES) CPPDEFS += -DGVARS + GUIMODELSRC += gui/menu_model_gvars.cpp EEPROM_VARIANT += ${GVARS_VARIANT} endif diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index 8d6914df4..46f7ace1f 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -3588,126 +3588,6 @@ void menuModelMixAll(uint8_t event) return menuModelExpoMix(0, event); } -#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 200); /*2 seconds*/ - - if (first2seconds) { - menuTitle = STR_GLOBAL_V; - for (int i=0; i 6 - for (uint8_t l=0; l0) ? BLINK|INVERS : INVERS) : 0); - coord_t x = GVARS_FM_COLUMN(j-1); - -#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: - { - FlightModeData *fm = &g_model.flightModeData[j-1]; - int16_t & v = fm->gvars[i]; - int16_t vmin, vmax; - if (v > GVAR_MAX) { - uint8_t p = v - GVAR_MAX - 1; - if (p >= j-1) p++; - putsFlightMode(x-15, y, p+1, attr|SMLSIZE); - vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_FLIGHT_MODES-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)) { - 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 (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(TEMPLATES) void menuModelTemplates(uint8_t event) { diff --git a/radio/src/gui/menu_model_gvars.cpp b/radio/src/gui/menu_model_gvars.cpp new file mode 100755 index 000000000..aef7ea8e8 --- /dev/null +++ b/radio/src/gui/menu_model_gvars.cpp @@ -0,0 +1,156 @@ +/* + * 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 + * - 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" + +#if LCD_W >= 212 && 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 200); /*2 seconds*/ + + if (first2seconds) { + menuTitle = STR_GLOBAL_V; + for (int i=0; i 6 + for (uint8_t l=0; l0) ? BLINK|INVERS : INVERS) : 0); + coord_t x = GVARS_FM_COLUMN(j-1); + +#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: + { + FlightModeData *fm = &g_model.flightModeData[j-1]; + int16_t & v = fm->gvars[i]; + int16_t vmin, vmax; + if (v > GVAR_MAX) { + uint8_t p = v - GVAR_MAX - 1; + if (p >= j-1) p++; + putsFlightMode(x-15, y, p+1, attr|SMLSIZE); + vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_FLIGHT_MODES-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)) { + 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 (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 diff --git a/radio/src/gui/menu_model_logical_switches.cpp b/radio/src/gui/menu_model_logical_switches.cpp new file mode 100755 index 000000000..2e76fe030 --- /dev/null +++ b/radio/src/gui/menu_model_logical_switches.cpp @@ -0,0 +1,636 @@ +/* + * 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 + * - 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" + +enum LogicalSwitchFields { + LS_FIELD_FUNCTION, + LS_FIELD_V1, + LS_FIELD_V2, +#if defined(PCBTARANIS) + LS_FIELD_V3, +#endif + LS_FIELD_ANDSW, +#if defined(CPUARM) + LS_FIELD_DURATION, + LS_FIELD_DELAY, +#endif + LS_FIELD_COUNT, + LS_FIELD_LAST = LS_FIELD_COUNT-1 +}; + +#if LCD_W >= 212 + #define CSW_1ST_COLUMN (4*FW-3) + #define CSW_2ND_COLUMN (8*FW+2+FW/2) + #define CSW_3RD_COLUMN (14*FW+1+FW/2) + #define CSW_4TH_COLUMN (22*FW) + #define CSW_5TH_COLUMN (26*FW+3) + #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) + #define INCDEC_DECLARE_VARS(f) uint8_t incdecFlag = (f); IsValueAvailable isValueAvailable = NULL + #define INCDEC_SET_FLAG(f) incdecFlag = (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(f) + #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(f) uint8_t incdecFlag = (f) + #define INCDEC_SET_FLAG(f) incdecFlag = (f) + #define INCDEC_ENABLE_CHECK(fn) + #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) +#endif + +#if defined(CPUARM) +void putsEdgeDelayParam(coord_t x, coord_t y, LogicalSwitchData *cs, uint8_t lattr, uint8_t rattr) +{ + lcd_putc(x-4, y, '['); + lcd_outdezAtt(x, y, lswTimerValue(cs->v2), LEFT|PREC1|lattr); + lcd_putc(lcdLastPos, y, ':'); + if (cs->v3 < 0) + lcd_putsAtt(lcdLastPos+3, y, "<<", rattr); + else if (cs->v3 == 0) + lcd_putsAtt(lcdLastPos+3, y, "--", rattr); + else + lcd_outdezAtt(lcdLastPos+3, y, lswTimerValue(cs->v2+cs->v3), LEFT|PREC1|rattr); + lcd_putc(lcdLastPos, y, ']'); +} +#endif + +#if defined(CPUARM) && LCD_W < 212 + +#define CSWONE_2ND_COLUMN (11*FW) + +void menuModelLogicalSwitchOne(uint8_t event) +{ + TITLE(STR_MENULOGICALSWITCH); + + LogicalSwitchData * cs = lswAddress(s_currIdx); + uint8_t sw = SWSRC_SW1+s_currIdx; + putsSwitches(14*FW, 0, sw, (getSwitch(sw) ? BOLD : 0)); + + SUBMENU_NOTITLE(LS_FIELD_COUNT, {0, 0, 1, 0 /*, 0...*/}); + + int8_t sub = m_posVert; + + INCDEC_DECLARE_VARS(EE_MODEL); + + int v1_val = cs->v1; + + for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); + uint8_t cstate = lswFamily(cs->func); + switch(i) { + case LS_FIELD_FUNCTION: + lcd_putsLeft(y, STR_FUNC); + lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_VCSWFUNC, cs->func, attr); + if (attr) { + cs->func = checkIncDec(event, cs->func, 0, LS_FUNC_MAX, EE_MODEL, isLogicalSwitchFunctionAvailable); + uint8_t new_cstate = lswFamily(cs->func); + if (cstate != new_cstate) { + if (new_cstate == LS_FAMILY_TIMER) { + cs->v1 = cs->v2 = 0; + } + else if (new_cstate == LS_FAMILY_EDGE) { + cs->v1 = 0; cs->v2 = -129; cs->v3 = 0; + } + else { + cs->v1 = cs->v2 = 0; + } + } + } + break; + case LS_FIELD_V1: + { + lcd_putsLeft(y, STR_V1); + int v1_min=0, v1_max=MIXSRC_LAST_TELEM; + if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY || cstate == LS_FAMILY_EDGE) { + putsSwitches(CSWONE_2ND_COLUMN, y, v1_val, attr); + v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; + } + else if (cstate == LS_FAMILY_TIMER) { + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, v1_val+1, LEFT|attr); + v1_max = 99; + } + else { + v1_val = (uint8_t)cs->v1; + putsMixerSource(CSWONE_2ND_COLUMN, y, v1_val, attr); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } + if (attr) { + cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max); + } + break; + } + case LS_FIELD_V2: + { + lcd_putsLeft(y, STR_V2); + int v2_min=0, v2_max=MIXSRC_LAST_TELEM; + if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) { + putsSwitches(CSWONE_2ND_COLUMN, y, cs->v2, attr); + v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; + } + else if (cstate == LS_FAMILY_TIMER) { + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2+1, LEFT|attr); + v2_max = 99; + } + else if (cstate == LS_FAMILY_EDGE) { + putsEdgeDelayParam(CSWONE_2ND_COLUMN, y, cs, m_posHorz==0 ? attr : 0, m_posHorz==1 ? attr : 0); + if (s_editMode <= 0) continue; + if (attr && m_posHorz==1) { + CHECK_INCDEC_MODELVAR(event, cs->v3, -1, 222 - cs->v2); + break; + } + v2_min = -129; v2_max = 122; + } + else if (cstate == LS_FAMILY_COMP) { + putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v2, attr); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } + else { +#if defined(FRSKY) + if (v1_val >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannelValue(CSWONE_2ND_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), attr|LEFT); + v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1); + if (cs->func == LS_FUNC_DIFFEGREATER) + v2_min = -v2_max; + else if (cs->func == LS_FUNC_ADIFFEGREATER) + v2_min = 0; + else + v2_min = minTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_REP10 | NO_INCDEC_MARKS); + if (cs->v2 < v2_min || cs->v2 > v2_max) { + cs->v2 = 0; + eeDirty(EE_MODEL); + } + } + else +#endif + { + v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT; + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2, LEFT|attr); + } + } + + if (attr) { + CHECK_INCDEC_MODELVAR(event, cs->v2, v2_min, v2_max); + } + break; + } + case LS_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_LS_ANDSW, MAX_LS_ANDSW); + break; + case LS_FIELD_DURATION: + lcd_putsLeft(y, STR_DURATION); + if (cs->duration > 0) + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 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_LS_DURATION); + break; + case LS_FIELD_DELAY: + lcd_putsLeft(y, STR_DELAY); + if (cs->delay > 0) + lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 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_LS_DELAY); + break; + } + } +} + +void menuModelLogicalSwitches(uint8_t event) +{ + SIMPLE_MENU(STR_MENULOGICALSWITCHES, menuTabModel, e_LogicalSwitches, NUM_LOGICAL_SWITCH+1); + + coord_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(menuModelLogicalSwitchOne); + } + 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 = lswFamily(cs->func); + + if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) { + putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0); + putsSwitches(CSW_3RD_COLUMN, y, cs->v2, 0); + } + else if (cstate == LS_FAMILY_COMP) { + putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); + putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, 0); + } + else if (cstate == LS_FAMILY_EDGE) { + putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0); + putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, 0, 0); + } + else if (cstate == LS_FAMILY_TIMER) { + lcd_outdezAtt(CSW_2ND_COLUMN, y, cs->v1+1, LEFT); + lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2+1, LEFT); + } + else { + uint8_t v1 = cs->v1; + putsMixerSource(CSW_2ND_COLUMN, y, v1, 0); + if (v1 >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1 - MIXSRC_FIRST_TELEM, convertLswTelemValue(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 { + LogicalSwitchData csw; + CustomFunctionData cfn; + } data; +}; + +Clipboard clipboard; + +void onLogicalSwitchesMenu(const char *result) +{ + int8_t sub = m_posVert-1; + LogicalSwitchData * cs = lswAddress(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_CLEAR) { + memset(cs, 0, sizeof(LogicalSwitchData)); + eeDirty(EE_MODEL); + } +} +#endif + +void menuModelLogicalSwitches(uint8_t event) +{ + INCDEC_DECLARE_VARS(EE_MODEL); + + MENU(STR_MENULOGICALSWITCHES, menuTabModel, e_LogicalSwitches, NUM_LOGICAL_SWITCH+1, {0, NAVIGATION_LINE_BY_LINE|LS_FIELD_LAST/*repeated...*/}); + + 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); + LogicalSwitchData * cs = lswAddress(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_CLEAR); + menuHandler = onLogicalSwitchesMenu; + } +#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); + LogicalSwitchData * cs = lswAddress(k); + + // CSW name + uint8_t sw = SWSRC_SW1+k; + putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && CURSOR_ON_LINE()) ? INVERS : 0)); + + // CSW func + lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0); + + // CSW params + uint8_t cstate = lswFamily(cs->func); +#if defined(CPUARM) + int16_t v1_val=cs->v1, v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; + int16_t v3_min=-1, v3_max=100; +#else + int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; + #define v1_val cs->v1 +#endif + + if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) { + putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); + putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2); + v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES; + v2_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v2_max = SWSRC_LAST_IN_LOGICAL_SWITCHES; + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH); + INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches); + } +#if defined(CPUARM) + else if (cstate == LS_FAMILY_EDGE) { + putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); + putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, attr2, horz==LS_FIELD_V3 ? attr : 0); + v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES; + v2_min=-129; v2_max = 122; + v3_max = 222 - cs->v2; + if (horz == 1) { + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH); + INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches); + } + else { + INCDEC_SET_FLAG(EE_MODEL); + INCDEC_ENABLE_CHECK(NULL); + } + } +#endif + else if (cstate == LS_FAMILY_COMP) { +#if defined(CPUARM) + v1_val = (uint8_t)cs->v1; +#endif + putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1); + putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2); + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailable); + } + else if (cstate == LS_FAMILY_TIMER) { + lcd_outdezAtt(CSW_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT|PREC1|attr1); + lcd_outdezAtt(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1|attr2); + v1_min = v2_min = -128; + v1_max = v2_max = 122; + INCDEC_SET_FLAG(EE_MODEL); + INCDEC_ENABLE_CHECK(NULL); + } + else { +#if defined(CPUARM) + v1_val = (uint8_t)cs->v1; +#endif + putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1); + if (horz == 1) { + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE); + INCDEC_ENABLE_CHECK(isSourceAvailableInCustomSwitches); + } + else { + INCDEC_SET_FLAG(EE_MODEL); + INCDEC_ENABLE_CHECK(NULL); + } +#if defined(CPUARM) + putsChannelValue(CSW_3RD_COLUMN, y, v1_val, calc100toRESX(cs->v2), LEFT|attr2); + v2_min = -30000; + v2_max = 30000; +#elif defined(FRSKY) + if (v1_val >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2); + v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1); +#if defined(CPUARM) + if (cs->func == LS_FUNC_DIFFEGREATER) + v2_min = -v2_max; + else if (cs->func == LS_FUNC_ADIFFEGREATER) + v2_min = 0; + else + v2_min = minTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1); + if (horz == 2 && v2_max-v2_min > 1000) + INCDEC_SET_FLAG(EE_MODEL | INCDEC_REP10 | NO_INCDEC_MARKS); + if (cs->v2 < v2_min || cs->v2 > v2_max) { + cs->v2 = 0; + eeDirty(EE_MODEL); + } +#else + if (cstate == LS_FAMILY_OFS) { + 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); +#if defined(CPUARM) && defined(GVARS) + if (v1_val >= MIXSRC_GVAR1) { + v2_min = -1024; v2_max = +1024; + } + else +#endif + { + v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT; + } + } +#else + if (v1_val >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2); + v2_min = -128; v2_max = 127; + } + else { + lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); + v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT; + } +#endif + } + + // CSW AND switch +#if defined(CPUARM) + putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==LS_FIELD_ANDSW ? attr : 0); +#else + uint8_t andsw = cs->andsw; + if (andsw > SWSRC_LAST_SWITCH) { + andsw += SWSRC_SW1-SWSRC_LAST_SWITCH-1; + } + putsSwitches(CSW_4TH_COLUMN, y, andsw, horz==LS_FIELD_ANDSW ? attr : 0); +#endif + +#if defined(CPUARM) + // CSW duration + if (cs->duration > 0) + lcd_outdezAtt(CSW_5TH_COLUMN, y, cs->duration, (horz==LS_FIELD_DURATION ? attr : 0)|PREC1|LEFT); + else + lcd_putsiAtt(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DURATION ? attr : 0); + + // CSW delay + if (cstate == LS_FAMILY_EDGE) { + lcd_puts(CSW_6TH_COLUMN, y, STR_NA); + if (attr && horz == LS_FIELD_DELAY) { + REPEAT_LAST_CURSOR_MOVE(); + } + } + else if (cs->delay > 0) { + lcd_outdezAtt(CSW_6TH_COLUMN, y, cs->delay, (horz==LS_FIELD_DELAY ? attr : 0)|PREC1|LEFT); + } + else { + lcd_putsiAtt(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DELAY ? attr : 0); + } + + if (attr && horz == LS_FIELD_V3 && cstate != LS_FAMILY_EDGE) { + REPEAT_LAST_CURSOR_MOVE(); + } +#endif + + if ((s_editMode>0 || p1valdiff) && attr) { + switch (horz) { + case LS_FIELD_FUNCTION: + { +#if defined(CPUARM) + cs->func = checkIncDec(event, cs->func, 0, LS_FUNC_MAX, EE_MODEL, isLogicalSwitchFunctionAvailable); +#else + CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, LS_FUNC_MAX); +#endif + uint8_t new_cstate = lswFamily(cs->func); + if (cstate != new_cstate) { +#if defined(CPUARM) + if (new_cstate == LS_FAMILY_TIMER) { + cs->v1 = cs->v2 = -119; + } + else if (new_cstate == LS_FAMILY_EDGE) { + cs->v1 = 0; cs->v2 = -129; cs->v3 = 0; + } + else { + cs->v1 = cs->v2 = 0; + } +#else + cs->v1 = cs->v2 = (new_cstate==LS_FAMILY_TIMER ? -119/*1.0*/ : 0); +#endif + } + break; + } + case LS_FIELD_V1: + cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max); + break; + case LS_FIELD_V2: + cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); + if (checkIncDec_Ret) TRACE("v2=%d", cs->v2); +#if defined(PCBTARANIS) + if (cstate==LS_FAMILY_OFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + getvalue_t x = getValue(v1_val); + if (v1_val < MIXSRC_GVAR1) + cs->v2 = calcRESXto100(x); + eeDirty(EE_MODEL); + } +#endif + break; +#if defined(CPUARM) + case LS_FIELD_V3: + cs->v3 = CHECK_INCDEC_PARAM(event, cs->v3, v3_min, v3_max); + break; +#endif + case LS_FIELD_ANDSW: +#if defined(CPUARM) + INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH); + INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches); + cs->andsw = CHECK_INCDEC_PARAM(event, cs->andsw, -MAX_LS_ANDSW, MAX_LS_ANDSW); +#else + CHECK_INCDEC_MODELVAR_ZERO(event, cs->andsw, MAX_LS_ANDSW); +#endif + break; +#if defined(CPUARM) + case LS_FIELD_DURATION: + CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_LS_DURATION); + break; + case LS_FIELD_DELAY: + CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_LS_DELAY); + break; +#endif + } + } + } +} +#endif