diff --git a/companion/src/eeprominterface.cpp b/companion/src/eeprominterface.cpp index a4a483d16d..3f95054d99 100644 --- a/companion/src/eeprominterface.cpp +++ b/companion/src/eeprominterface.cpp @@ -1524,7 +1524,7 @@ bool ModelData::isGVarLinked(int phaseIdx, int gvarIdx) return flightModeData[phaseIdx].gvars[gvarIdx] > 1024; } -int ModelData::getGVarValue(int phaseIdx, int gvarIdx) +int ModelData::getGVarFieldValue(int phaseIdx, int gvarIdx) { int idx = flightModeData[phaseIdx].gvars[gvarIdx]; for (int i=0; idx>1024 && i= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast)) _active = (version >= 216 ? fn.repeatParam : (fn.repeatParam/5)); else _active = (fn.enabled ? 1 : 0); @@ -2209,7 +2209,7 @@ class ArmCustomFunctionField: public TransformedField { { fn.func = (AssignFunc)_func; - if (fn.func == FuncPlaySound || fn.func == FuncPlayPrompt || fn.func == FuncPlayValue || fn.func == FuncPlayHaptic) + if (fn.func == FuncPlaySound || fn.func == FuncPlayPrompt || fn.func == FuncPlayValue || fn.func == FuncPlayHaptic || (fn.func >= FuncAdjustGV1 && fn.func <= FuncAdjustGVLast)) fn.repeatParam = (version >= 216 ? _active : (_active*5)); else fn.enabled = (_active & 0x01); diff --git a/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp b/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp index 3b72be5c14..282fc05eda 100644 --- a/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp +++ b/companion/src/firmwares/opentx/simulator/opentxsimulator.cpp @@ -148,7 +148,8 @@ namespace NAMESPACE { #include "radio/src/gui/horus/menu_model_setup.cpp" #include "radio/src/gui/horus/menu_model_heli.cpp" #include "radio/src/gui/horus/menu_model_flightmodes.cpp" -#include "radio/src/gui/horus/menu_model_inputs_mixes.cpp" +#include "radio/src/gui/horus/menu_model_inputs.cpp" +#include "radio/src/gui/horus/menu_model_mixes.cpp" #include "radio/src/gui/horus/menu_model_curves.cpp" #include "radio/src/gui/horus/menu_model_logical_switches.cpp" #include "radio/src/gui/horus/menu_model_custom_functions.cpp" @@ -220,7 +221,8 @@ namespace NAMESPACE { #include "radio/src/gui/taranis/menu_model_setup.cpp" #include "radio/src/gui/taranis/menu_model_heli.cpp" #include "radio/src/gui/taranis/menu_model_flightmodes.cpp" -#include "radio/src/gui/taranis/menu_model_inputs_mixes.cpp" +#include "radio/src/gui/taranis/menu_model_inputs.cpp" +#include "radio/src/gui/taranis/menu_model_mixes.cpp" #include "radio/src/gui/taranis/menu_model_curves.cpp" #include "radio/src/gui/taranis/menu_model_logical_switches.cpp" #include "radio/src/gui/taranis/menu_model_custom_functions.cpp" diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index 66827ce4d7..7438c6b2ea 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -373,8 +373,8 @@ void CustomFunctionsPanel::refreshCustomFunction(int i, bool modified) } else if (func>=FuncAdjustGV1 && func<=FuncAdjustGVLast) { if (modified) cfn.adjustMode = fswtchGVmode[i]->currentIndex(); - widgetsMask |= CUSTOM_FUNCTION_GV_MODE + CUSTOM_FUNCTION_ENABLE; - if (cfn.adjustMode==0) { + widgetsMask |= CUSTOM_FUNCTION_GV_MODE | (IS_ARM(firmware->getBoard()) ? CUSTOM_FUNCTION_REPEAT : CUSTOM_FUNCTION_ENABLE); + if (cfn.adjustMode==0 || cfn.adjustMode==3) { if (modified) cfn.param = fswtchParam[i]->value(); fswtchParam[i]->setDecimals(0); fswtchParam[i]->setSingleStep(1); @@ -677,12 +677,6 @@ void CustomFunctionsPanel::populateFuncParamCB(QComboBox *b, uint function, unsi case 2: populateSourceCB(b, RawSource(value), generalSettings, model, POPULATE_GVARS); break; - case 3: - b->clear(); - b->addItem("-1", 0); - b->addItem("+1", 1); - b->setCurrentIndex(value); - break; } } else { diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index 532792bfb5..21782ae9b7 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -220,7 +220,7 @@ void FlightModePanel::update() gvNames[i]->setText(model->gvars_names[i]); } gvValues[i]->setDisabled(model->isGVarLinked(phaseIdx, i)); - gvValues[i]->setValue(model->getGVarValue(phaseIdx, i)); + gvValues[i]->setValue(model->getGVarFieldValue(phaseIdx, i)); if (IS_TARANIS(GetEepromInterface()->getBoard()) && phaseIdx == 0) { gvPopups[i]->setChecked(model->gvars_popups[i]); } diff --git a/companion/src/simulation/simulatorimport.h b/companion/src/simulation/simulatorimport.h index fc5298cbe1..0a8d7b08fa 100644 --- a/companion/src/simulation/simulatorimport.h +++ b/companion/src/simulation/simulatorimport.h @@ -71,7 +71,7 @@ for (int i=0; i @@ -156,18 +156,6 @@ int cliStackInfo(const char ** argv) return 0; } -int cliVolume(const char ** argv) -{ - int level = 0; - if (toInt(argv, 1, &level) > 0) { - setVolume(level); - } - else { - serialPrint("%s: Invalid argument \"%s\"", argv[0], argv[1]); - } - return 0; -} - #if defined(PCBFLAMENCO) int cliReadBQ24195(const char ** argv) { @@ -229,6 +217,16 @@ int cliSet(const char ** argv) serialPrint("%s: Invalid arguments \"%s\" \"%s\"", argv[0], argv[1], argv[2]); } } + else if (!strcmp(argv[1], "volume")) { + int level = 0; + if (toInt(argv, 2, &level) > 0) { + setVolume(level); + } + else { + serialPrint("%s: Invalid argument \"%s\" \"%s\"", argv[0], argv[1], argv[2]); + } + return 0; + } return 0; } @@ -279,6 +277,9 @@ int cliDisplay(const char ** argv) gettime(&utm); serialPrint("rtc = %4d-%02d-%02d %02d:%02d:%02d.%02d0", utm.tm_year+1900, utm.tm_mon+1, utm.tm_mday, utm.tm_hour, utm.tm_min, utm.tm_sec, g_ms100); } + else if (!strcmp(argv[1], "volume")) { + serialPrint("volume = %d", getVolume()); + } #if defined(PCBFLAMENCO) else if (!strcmp(argv[1], "bq24195")) { { @@ -326,7 +327,7 @@ int cliDisplay(const char ** argv) int cliDebugVars(const char ** argv) { -#if defined(PCBHORUS) +#if defined(PCBHORUS) && !defined(SIMU) extern unsigned int ioMutexReq, ioMutexRel; extern unsigned int sdReadRetries; @@ -367,7 +368,6 @@ const CliCommand cliCommands[] = { { "set", cliSet, " " }, { "stackinfo", cliStackInfo, "" }, { "trace", cliTrace, "on | off" }, - { "volume", cliVolume, "" }, #if defined(PCBFLAMENCO) { "read_bq24195", cliReadBQ24195, "" }, { "write_bq24195", cliWriteBQ24195, " " }, diff --git a/radio/src/curves.cpp b/radio/src/curves.cpp index 456af0d0cd..6aaa6e5b42 100644 --- a/radio/src/curves.cpp +++ b/radio/src/curves.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "opentx.h" #if defined(XCURVES) @@ -72,7 +72,7 @@ CurveInfo curveInfo(uint8_t idx) #if defined(XCURVES) #define CUSTOM_POINT_X(points, count, idx) ((idx)==0 ? -100 : (((idx)==(count)-1) ? 100 : points[(count)+(idx)-1])) -s32 compute_tangent(CurveInfo *crv, int8_t *points, int i) +s32 compute_tangent(CurveInfo * crv, int8_t * points, int i) { s32 m=0; uint8_t num_points = crv->points + 5; @@ -238,16 +238,32 @@ int applyCurve(int x, CurveRef & curve) switch (curve.type) { case CURVE_REF_DIFF: { +#if defined(CPUARM) + int curveParam = GET_GVAR_PREC1(curve.value, -100, 100, mixerCurrentFlightMode); + if (curveParam > 0 && x < 0) + x = (x * (1000 - curveParam)) / 1000; + else if (curveParam < 0 && x > 0) + x = (x * (1000 + curveParam)) / 1000; + return x; +#else int curveParam = calc100to256(GET_GVAR(curve.value, -100, 100, mixerCurrentFlightMode)); if (curveParam > 0 && x < 0) x = (x * (256 - curveParam)) >> 8; else if (curveParam < 0 && x > 0) x = (x * (256 + curveParam)) >> 8; return x; +#endif } case CURVE_REF_EXPO: - return expo(x, GET_GVAR(curve.value, -100, 100, mixerCurrentFlightMode)); + { +#if defined(CPUARM) + int curveParam = GET_GVAR_PREC1(curve.value, -100, 100, mixerCurrentFlightMode) / 10; +#else + int curveParam = GET_GVAR(curve.value, -100, 100, mixerCurrentFlightMode); +#endif + return expo(x, curveParam); + } case CURVE_REF_FUNC: switch (curve.value) { diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp index bf895ec786..ada577f793 100644 --- a/radio/src/functions.cpp +++ b/radio/src/functions.cpp @@ -27,7 +27,6 @@ CustomFunctionsContext modelFunctionsContext = { 0 }; CustomFunctionsContext globalFunctionsContext = { 0 }; #endif - #if defined(DEBUG) /* * This is a test function for debugging purpose, you may insert there your code and compile with the option DEBUG=YES @@ -204,10 +203,8 @@ PLAY_FUNCTION(playValue, source_t idx) } #else default: - { PLAY_NUMBER(val, 0, 0); break; - } #endif } #endif @@ -228,6 +225,27 @@ void playCustomFunctionFile(const CustomFunctionData *sd, uint8_t id) } #endif +#if defined(CPUARM) +bool isRepeatDelayElapsed(const CustomFunctionData * functions, CustomFunctionsContext & functionsContext, uint8_t index) +{ + const CustomFunctionData * cfn = &functions[index]; + tmr10ms_t tmr10ms = get_tmr10ms(); + uint8_t repeatParam = CFN_PLAY_REPEAT(cfn); + if (!IS_SILENCE_PERIOD_ELAPSED() && repeatParam == CFN_PLAY_REPEAT_NOSTART) { + functionsContext.lastFunctionTime[index] = tmr10ms; + } + if (!functionsContext.lastFunctionTime[index] || (repeatParam && repeatParam!=CFN_PLAY_REPEAT_NOSTART && (signed)(tmr10ms-functionsContext.lastFunctionTime[index])>=100*repeatParam)) { + functionsContext.lastFunctionTime[index] = tmr10ms; + return true; + } + else { + return false; + } +} +#else +#define isRepeatDelayElapsed(...) true +#endif + #if defined(CPUARM) #define VOLUME_HYSTERESIS 10 // how much must a input value change to actually be considered for new volume setting getvalue_t requiredSpeakerVolumeRawLast = 1024 + 1; //initial value must be outside normal range @@ -361,10 +379,8 @@ void evalFunctions() #if defined(CPUARM) case FUNC_SET_TIMER: - { timerSet(CFN_TIMER_INDEX(cfn), CFN_PARAM(cfn)); break; - } #endif #if defined(CPUARM) @@ -398,30 +414,36 @@ void evalFunctions() #if defined(GVARS) case FUNC_ADJUST_GVAR: - if (CFN_GVAR_MODE(cfn) == 0) { - SET_GVAR(CFN_GVAR_INDEX(cfn), CFN_PARAM(cfn), mixerCurrentFlightMode); - } - else if (CFN_GVAR_MODE(cfn) == 2) { - SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_PARAM(cfn), mixerCurrentFlightMode), mixerCurrentFlightMode); - } - else if (CFN_GVAR_MODE(cfn) == 3) { - if (!(functionsContext.activeSwitches & switch_mask)) { - SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightPhase(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + (CFN_PARAM(cfn) ? +1 : -1), mixerCurrentFlightMode); + if (isRepeatDelayElapsed(functions, functionsContext, i)) { + if (CFN_GVAR_MODE(cfn) == FUNC_ADJUST_GVAR_CONSTANT) { + SET_GVAR(CFN_GVAR_INDEX(cfn), CFN_PARAM(cfn), mixerCurrentFlightMode); } - } - else if (CFN_PARAM(cfn) >= MIXSRC_TrimRud && CFN_PARAM(cfn) <= MIXSRC_TrimAil) { - trimGvar[CFN_PARAM(cfn)-MIXSRC_TrimRud] = CFN_GVAR_INDEX(cfn); - } -#if defined(ROTARY_ENCODERS) - else if (CFN_PARAM(cfn) >= MIXSRC_REa && CFN_PARAM(cfn) < MIXSRC_TrimRud) { - int8_t scroll = rePreviousValues[CFN_PARAM(cfn)-MIXSRC_REa] - (g_rotenc[CFN_PARAM(cfn)-MIXSRC_REa] / ROTARY_ENCODER_GRANULARITY); - if (scroll) { - SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightPhase(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + scroll, mixerCurrentFlightMode); + else if (CFN_GVAR_MODE(cfn) == FUNC_ADJUST_GVAR_GVAR) { + SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_PARAM(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_PARAM(cfn))), mixerCurrentFlightMode); } - } + else if (CFN_GVAR_MODE(cfn) == FUNC_ADJUST_GVAR_INCDEC) { +#if defined(CPUARM) + SET_GVAR(CFN_GVAR_INDEX(cfn), limit(CFN_GVAR_CST_MIN+g_model.gvars[CFN_GVAR_INDEX(cfn)].min, GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + CFN_PARAM(cfn), CFN_GVAR_CST_MAX-g_model.gvars[CFN_GVAR_INDEX(cfn)].max), mixerCurrentFlightMode); +#else + if (!(functionsContext.activeSwitches & switch_mask)) { + SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + (CFN_PARAM(cfn) ? +1 : -1), mixerCurrentFlightMode); + } #endif - else { - SET_GVAR(CFN_GVAR_INDEX(cfn), calcRESXto100(getValue(CFN_PARAM(cfn))), mixerCurrentFlightMode); + } + else if (CFN_PARAM(cfn) >= MIXSRC_TrimRud && CFN_PARAM(cfn) <= MIXSRC_TrimAil) { + trimGvar[CFN_PARAM(cfn)-MIXSRC_TrimRud] = CFN_GVAR_INDEX(cfn); + } +#if defined(ROTARY_ENCODERS) + else if (CFN_PARAM(cfn) >= MIXSRC_REa && CFN_PARAM(cfn) < MIXSRC_TrimRud) { + int8_t scroll = rePreviousValues[CFN_PARAM(cfn)-MIXSRC_REa] - (g_rotenc[CFN_PARAM(cfn)-MIXSRC_REa] / ROTARY_ENCODER_GRANULARITY); + if (scroll) { + SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + scroll, mixerCurrentFlightMode); + } + } +#endif + else { + SET_GVAR(CFN_GVAR_INDEX(cfn), calcRESXto100(getValue(CFN_PARAM(cfn))), mixerCurrentFlightMode); + } } break; #endif @@ -447,14 +469,8 @@ void evalFunctions() case FUNC_HAPTIC: #endif { - tmr10ms_t tmr10ms = get_tmr10ms(); - uint8_t repeatParam = CFN_PLAY_REPEAT(cfn); - if (!IS_SILENCE_PERIOD_ELAPSED() && repeatParam == CFN_PLAY_REPEAT_NOSTART) { - functionsContext.lastFunctionTime[i] = tmr10ms; - } - if (!functionsContext.lastFunctionTime[i] || (repeatParam && repeatParam!=CFN_PLAY_REPEAT_NOSTART && (signed)(tmr10ms-functionsContext.lastFunctionTime[i])>=100*repeatParam)) { + if (isRepeatDelayElapsed(functions, functionsContext, i)) { if (!IS_PLAYING(PLAY_INDEX)) { - functionsContext.lastFunctionTime[i] = tmr10ms; if (CFN_FUNC(cfn) == FUNC_PLAY_SOUND) { AUDIO_PLAY(AU_FRSKY_FIRST+CFN_PARAM(cfn)); } @@ -507,7 +523,7 @@ void evalFunctions() else { #if defined(GVARS) if (CFN_FUNC(cfn) == FUNC_PLAY_TRACK && param > 250) - param = GVAR_VALUE(param-251, getGVarFlightPhase(mixerCurrentFlightMode, param-251)); + param = GVAR_VALUE(param-251, getGVarFlightMode(mixerCurrentFlightMode, param-251)); #endif PUSH_CUSTOM_PROMPT(active ? param : param+1, PLAY_INDEX); } diff --git a/radio/src/gui/9x/menu_general_setup.cpp b/radio/src/gui/9x/menu_general_setup.cpp index 8c5debe211..24d14de204 100644 --- a/radio/src/gui/9x/menu_general_setup.cpp +++ b/radio/src/gui/9x/menu_general_setup.cpp @@ -260,7 +260,7 @@ void menuGeneralSetup(uint8_t event) if (checkIncDec_Ret) { g_eeGeneral.speakerVolume = (int8_t)b-VOLUME_LEVEL_DEF; #if !defined(CPUARM) - setVolume(b); + setScaledVolume(b); #endif } } @@ -367,14 +367,14 @@ void menuGeneralSetup(uint8_t event) case ITEM_SETUP_MEMORY_WARNING: { uint8_t b = 1-g_eeGeneral.disableMemoryWarning; - g_eeGeneral.disableMemoryWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event); + g_eeGeneral.disableMemoryWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event); break; } case ITEM_SETUP_ALARM_WARNING: { uint8_t b = 1-g_eeGeneral.disableAlarmWarning; - g_eeGeneral.disableAlarmWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event); + g_eeGeneral.disableAlarmWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event); break; } @@ -395,7 +395,7 @@ void menuGeneralSetup(uint8_t event) #endif case ITEM_SETUP_INACTIVITY_ALARM: - lcd_putsLeft( y,STR_INACTIVITYALARM); + lcd_putsLeft(y, STR_INACTIVITYALARM); lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.inactivityTimer, attr|LEFT); lcdDrawChar(lcdLastPos, y, 'm'); if(attr) g_eeGeneral.inactivityTimer = checkIncDec(event, g_eeGeneral.inactivityTimer, 0, 250, EE_GENERAL); //0..250minutes @@ -419,7 +419,7 @@ void menuGeneralSetup(uint8_t event) break; case ITEM_SETUP_FLASH_BEEP: - g_eeGeneral.alarmsFlash = onoffMenuItem(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ; + g_eeGeneral.alarmsFlash = editCheckBox(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ; break; case ITEM_SETUP_BACKLIGHT_DELAY: @@ -459,7 +459,7 @@ void menuGeneralSetup(uint8_t event) case ITEM_SETUP_DISABLE_SPLASH: { uint8_t b = 1-g_eeGeneral.splashMode; - g_eeGeneral.splashMode = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_SPLASHSCREEN, attr, event); + g_eeGeneral.splashMode = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_SPLASHSCREEN, attr, event); break; } #endif @@ -502,7 +502,7 @@ void menuGeneralSetup(uint8_t event) #if defined(FAI_CHOICE) case ITEM_SETUP_FAI: - onoffMenuItem(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event); + editCheckBox(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event); if (attr && checkIncDec_Ret) { if (g_eeGeneral.fai) POPUP_WARNING(PSTR("FAI\001mode blocked!")); diff --git a/radio/src/gui/9x/menu_model_custom_functions.cpp b/radio/src/gui/9x/menu_model_custom_functions.cpp index 314520e8d5..32bd6e9d4c 100644 --- a/radio/src/gui/9x/menu_model_custom_functions.cpp +++ b/radio/src/gui/9x/menu_model_custom_functions.cpp @@ -341,7 +341,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu case 4: if (HAS_ENABLE_PARAM(func)) { - menu_lcd_onoff(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); + drawCheckBox(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); #if defined(CPUARM) if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); #else diff --git a/radio/src/gui/9x/menu_model_flightmodes.cpp b/radio/src/gui/9x/menu_model_flightmodes.cpp index 5ade6fd7a1..ee677a0a46 100644 --- a/radio/src/gui/9x/menu_model_flightmodes.cpp +++ b/radio/src/gui/9x/menu_model_flightmodes.cpp @@ -172,10 +172,10 @@ void menuModelPhaseOne(uint8_t event) } } - uint8_t p = getGVarFlightPhase(s_currIdx, idx); + uint8_t p = getGVarFlightMode(s_currIdx, idx); lcdDrawNumber(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); + GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -500, 500, EE_MODEL); } break; diff --git a/radio/src/gui/9x/menu_model_inputs_mixes.cpp b/radio/src/gui/9x/menu_model_inputs_mixes.cpp index 99356f8055..31ea219039 100644 --- a/radio/src/gui/9x/menu_model_inputs_mixes.cpp +++ b/radio/src/gui/9x/menu_model_inputs_mixes.cpp @@ -171,19 +171,6 @@ void copyExpoMix(uint8_t expo, uint8_t idx) storageDirty(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; @@ -449,8 +436,8 @@ void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) void menuModelMixOne(uint8_t event) { - TITLE(s_currCh ? STR_INSERTMIX : STR_EDITMIX); - MixData *md2 = mixAddress(s_currIdx) ; + TITLE(STR_MIXER); + MixData * md2 = mixAddress(s_currIdx) ; putsChn(lcdLastPos+1*FW, 0, md2->destCh+1,0); #if defined(ROTARY_ENCODERS) @@ -530,7 +517,7 @@ void menuModelMixOne(uint8_t event) if (attr && menuHorizontalPosition==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); if (!not_stick) { lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX); - menu_lcd_onoff(COLUMN_X+MIXES_2ND_COLUMN+DREX_CHBOX_OFFSET, y, !md2->noExpo, menuHorizontalPosition==1 ? attr : 0); + drawCheckBox(COLUMN_X+MIXES_2ND_COLUMN+DREX_CHBOX_OFFSET, y, !md2->noExpo, menuHorizontalPosition==1 ? attr : 0); if (attr && menuHorizontalPosition==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1); } else if (attr) { diff --git a/radio/src/gui/9x/menu_model_setup.cpp b/radio/src/gui/9x/menu_model_setup.cpp index 3e241f5307..e4c5b8271c 100644 --- a/radio/src/gui/9x/menu_model_setup.cpp +++ b/radio/src/gui/9x/menu_model_setup.cpp @@ -232,7 +232,7 @@ void menuModelSetup(uint8_t event) case ITEM_MODEL_TIMER3_MINUTE_BEEP: { TimerData * timer = &g_model.timers[k>=ITEM_MODEL_TIMER3 ? 2 : (k>=ITEM_MODEL_TIMER2 ? 1 : 0)]; - timer->minuteBeep = onoffMenuItem(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); + timer->minuteBeep = editCheckBox(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); break; } @@ -263,10 +263,10 @@ void menuModelSetup(uint8_t event) { 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); + timer->minuteBeep = editCheckBox(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) { - timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); + timer->countdownBeep = editCheckBox(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); } else { putsStrIdx(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1); @@ -369,7 +369,7 @@ void menuModelSetup(uint8_t event) #endif case ITEM_MODEL_THROTTLE_WARNING: - g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); + g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); break; case ITEM_MODEL_SWITCHES_WARNING: @@ -465,7 +465,7 @@ void menuModelSetup(uint8_t event) #if defined(CPUARM) case ITEM_MODEL_USE_GLOBAL_FUNCTIONS: lcd_putsLeft(y, STR_USE_GLOBAL_FUNCS); - menu_lcd_onoff(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr); + drawCheckBox(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr); if (attr) g_model.noGlobalFunctions = !checkIncDecModel(event, !g_model.noGlobalFunctions, 0, 1); break; #endif diff --git a/radio/src/gui/9x/menus.h b/radio/src/gui/9x/menus.h index 281092e1e9..172a665528 100644 --- a/radio/src/gui/9x/menus.h +++ b/radio/src/gui/9x/menus.h @@ -50,7 +50,7 @@ extern uint8_t noHighlightCounter; #define NO_HIGHLIGHT() (noHighlightCounter > 0) #define START_NO_HIGHLIGHT() do { noHighlightCounter = 25; } while(0) -void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr); +void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr); typedef void (* MenuHandlerFunc)(uint8_t event); @@ -385,26 +385,26 @@ void title(const pm_char * s); #endif select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event); -uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event); +uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event); int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event); -#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = onoffMenuItem(value, x, y, label, attr, event) +#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = editCheckBox(value, x, y, label, attr, event) #if defined(CPUARM) && defined(GVARS) - #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, editflags, event) + #define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, editflags, event) #else - #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, event) + #define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, event) #endif #if defined(GVARS) #if defined(CPUARM) - int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event); + int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event); #else - int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); // @@@ open.20.fsguruh + int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); // @@@ open.20.fsguruh #endif #define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0) #else - int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); + int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); #define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v) #endif diff --git a/radio/src/gui/9x/view_main.cpp b/radio/src/gui/9x/view_main.cpp index cd65335a3b..a4ea13f794 100644 --- a/radio/src/gui/9x/view_main.cpp +++ b/radio/src/gui/9x/view_main.cpp @@ -397,8 +397,8 @@ void menuMainView(uint8_t event) case EVT_KEY_FIRST(KEY_EXIT): #if defined(GVARS) && !defined(PCBSTD) - if (s_gvar_timer > 0) { - s_gvar_timer = 0; + if (gvarDisplayTimer > 0) { + gvarDisplayTimer = 0; } #endif if (view == VIEW_TIMER2) { @@ -555,13 +555,14 @@ void menuMainView(uint8_t event) } #if defined(GVARS) && !defined(PCBSTD) - if (s_gvar_timer > 0) { - s_gvar_timer--; + if (gvarDisplayTimer > 0) { + gvarDisplayTimer--; warningText = STR_GLOBAL_VAR; displayBox(); - lcdDrawSizedText(16, 5*FH, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, ZCHAR); + lcdDrawSizedText(16, 5*FH, g_model.gvars[gvarLastChanged].name, LEN_GVAR_NAME, ZCHAR); lcdDrawText(16+7*FW, 5*FH, PSTR("[\010]"), BOLD); - lcdDrawNumber(16+7*FW+4*FW+FW/2, 5*FH, GVAR_VALUE(s_gvar_last, getGVarFlightPhase(mixerCurrentFlightMode, s_gvar_last)), BOLD); + + lcdDrawNumber(16+7*FW+4*FW+FW/2, 5*FH, GVAR_VALUE(gvarLastChanged, getGVarFlightMode(mixerCurrentFlightMode, gvarLastChanged)), BOLD); warningText = NULL; } #endif diff --git a/radio/src/gui/9x/view_mavlink.cpp b/radio/src/gui/9x/view_mavlink.cpp index a7fd6e46a9..69b7ce9b93 100644 --- a/radio/src/gui/9x/view_mavlink.cpp +++ b/radio/src/gui/9x/view_mavlink.cpp @@ -499,7 +499,7 @@ void menuTelemetryMavlinkSetup(uint8_t event) { if (attr) CHECK_INCDEC_MODELVAR(event, g_model.mavlink.rc_rssi_scale, 0, 15); break; case ITEM_MAVLINK_PC_RSSI_EN: - g_model.mavlink.pc_rssi_en = onoffMenuItem(g_model.mavlink.pc_rssi_en, + g_model.mavlink.pc_rssi_en = editCheckBox(g_model.mavlink.pc_rssi_en, RADIO_SETUP_2ND_COLUMN, y, STR_MAVLINK_PC_RSSI_EN_LABEL, diff --git a/radio/src/gui/9x/widgets.cpp b/radio/src/gui/9x/widgets.cpp index 6f1d245170..d0f00a5947 100644 --- a/radio/src/gui/9x/widgets.cpp +++ b/radio/src/gui/9x/widgets.cpp @@ -32,7 +32,7 @@ void drawStick(coord_t centrex, int16_t xval, int16_t yval) #undef MARKER_WIDTH } -void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr) +void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr) { #if defined(GRAPHICS) if (value) @@ -80,10 +80,10 @@ select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, c return value; } -uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) +uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) { #if defined(GRAPHICS) - menu_lcd_onoff(x, y, value, attr); + drawCheckBox(x, y, value, attr); return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event); #else return selectMenuItem(x, y, label, STR_OFFON, value, 0, 1, attr, event); @@ -120,12 +120,12 @@ bool noZero(int val) return val != 0; } -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) { uint16_t delta = GV_GET_GV1_VALUE(max); bool invers = (attr & INVERS); - // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + // TRACE("editGVarFieldValue(val=%d min=%d max=%d)", value, min, max); if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { s_editMode = !s_editMode; @@ -167,12 +167,12 @@ int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t m return value; } #elif defined(GVARS) -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) { uint16_t delta = GV_GET_GV1_VALUE(max); bool invers = (attr & INVERS); - // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + // TRACE("editGVarFieldValue(val=%d min=%d max=%d)", value, min, max); if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { s_editMode = !s_editMode; @@ -207,7 +207,7 @@ int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t m return value; } #else -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) { lcdDrawNumber(x, y, value, attr); if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL); diff --git a/radio/src/gui/horus/bitmaps.cpp b/radio/src/gui/horus/bitmaps.cpp index fdc01f4ae9..6fe5975302 100644 --- a/radio/src/gui/horus/bitmaps.cpp +++ b/radio/src/gui/horus/bitmaps.cpp @@ -259,3 +259,7 @@ const uint8_t LBM_SHUTDOWN[] __DMA = { const uint8_t LBM_SLEEP[] __DMA = { #include "sleep.lbm" }; + +const uint8_t LBM_BIGRSCALE[] __DMA = { +#include "mask_bigrscale.lbm" +}; diff --git a/radio/src/gui/horus/gui.h b/radio/src/gui/horus/gui.h index 45dbbbbdbc..0d0e756fad 100644 --- a/radio/src/gui/horus/gui.h +++ b/radio/src/gui/horus/gui.h @@ -78,6 +78,13 @@ void drawSubmenuTemplate(const char * name, uint16_t scrollbar_X); void drawStick(coord_t centrex, int16_t xval, int16_t yval); void drawSticks(); +#if defined(FLIGHT_MODES) +void displayFlightModes(coord_t x, coord_t y, FlightModesType value, uint8_t attr); +FlightModesType editFlightModes(coord_t x, coord_t y, evt_t event, FlightModesType value, uint8_t attr); +#else + #define displayFlightModes(...) +#endif + // Curve functions coord_t getCurveYCoord(FnFuncP fn, int x, int width); void drawFunction(FnFuncP fn, int offset); @@ -127,3 +134,4 @@ extern const uint8_t LBM_CURVE_POINT_CENTER[]; extern const uint8_t LBM_CURVE_COORD_SHADOW[]; extern const uint8_t LBM_SHUTDOWN[]; extern const uint8_t LBM_SLEEP[]; +extern const uint8_t LBM_BIGRSCALE[]; diff --git a/radio/src/gui/horus/lcd.cpp b/radio/src/gui/horus/lcd.cpp index 5533d4b7a2..deb7d88c05 100644 --- a/radio/src/gui/horus/lcd.cpp +++ b/radio/src/gui/horus/lcd.cpp @@ -547,57 +547,80 @@ void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att) } } -void putsSwitches(coord_t x, coord_t y, int8_t idx, LcdFlags att) +char * getStringAtIndex(char * dest, const char * s, int idx) +{ + uint8_t len = s[0]; + strncpy(dest, s+1+len*idx, len); + dest[len] = '\0'; + return dest; +} + +char * getStringWithIndex(char * dest, const char * s, int idx) +{ + // TODO reimplement without the sprintf + sprintf(dest, "%s%d", s, abs(idx)); + return dest; +} + +char * getSwitchString(char * dest, swsrc_t idx) { if (idx == SWSRC_NONE) { - return lcdDrawTextAtIndex(x, y, STR_VSWITCHES, 0, att); + return getStringAtIndex(dest, STR_VSWITCHES, 0); } else if (idx == SWSRC_OFF) { - return lcdDrawTextAtIndex(x, y, STR_OFFON, 0, att); + return getStringAtIndex(dest, STR_OFFON, 0); } - char s[8]; - int pos = 0; + char * s = dest; if (idx < 0) { - s[pos++] = '!'; + *s++ = '!'; idx = -idx; } if (idx <= SWSRC_LAST_SWITCH) { div_t swinfo = switchInfo(idx); if (ZEXIST(g_eeGeneral.switchNames[swinfo.quot])) { - pos = zchar2str(&s[pos], g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME); + zchar2str(s, g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME); + // TODO tous zchar2str } else { - s[pos++] = 'S'; - s[pos++] = 'A'+swinfo.quot; + *s++ = 'S'; + *s++ = 'A'+swinfo.quot; } - s[pos++] = "\300-\301"[swinfo.rem]; - s[pos] = '\0'; - lcdDrawText(x, y, s, att); + *s++ = "\300-\301"[swinfo.rem]; + *s = '\0'; } - /*else if (idx <= SWSRC_LAST_MULTIPOS_SWITCH) { + else if (idx <= SWSRC_LAST_MULTIPOS_SWITCH) { div_t swinfo = div(idx - SWSRC_FIRST_MULTIPOS_SWITCH, XPOTS_MULTIPOS_COUNT); - putsStrIdx(x, y, "S", swinfo.quot*10+swinfo.rem+11, att); - }*/ + getStringWithIndex(s, "S", swinfo.quot*10+swinfo.rem+11); + } else if (idx <= SWSRC_LAST_TRIM) { - lcdDrawTextAtIndex(x, y, STR_VSWITCHES, idx-SWSRC_FIRST_TRIM+1, att); + getStringAtIndex(s, STR_VSWITCHES, idx-SWSRC_FIRST_TRIM+1); } else if (idx <= SWSRC_LAST_LOGICAL_SWITCH) { - putsStrIdx(x, y, "L", idx-SWSRC_FIRST_LOGICAL_SWITCH+1, att); + getStringWithIndex(s, "L", idx-SWSRC_FIRST_LOGICAL_SWITCH+1); } else if (idx <= SWSRC_ONE) { - lcdDrawTextAtIndex(x, y, STR_VSWITCHES, idx-SWSRC_ON+1+(2*NUM_STICKS), att); + getStringAtIndex(s, STR_VSWITCHES, idx-SWSRC_ON+1+(2*NUM_STICKS)); } else if (idx <= SWSRC_LAST_FLIGHT_MODE) { - putsStrIdx(x, y, STR_FP, idx-SWSRC_FIRST_FLIGHT_MODE, att); + getStringWithIndex(s, STR_FP, idx-SWSRC_FIRST_FLIGHT_MODE); } else if (idx == SWSRC_TELEMETRY_STREAMING) { - lcdDrawText(x, y, "Tele", att); + strcpy(s, "Tele"); } else { - lcdDrawSizedText(x, y, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN, ZCHAR|att); + zchar2str(s, g_model.telemetrySensors[idx-SWSRC_FIRST_SENSOR].label, TELEM_LABEL_LEN); } + + return dest; +} + +void putsSwitches(coord_t x, coord_t y, swsrc_t idx, LcdFlags flags) +{ + char s[8]; + getSwitchString(s, idx); + lcdDrawText(x, y, s, flags); } void putsFlightMode(coord_t x, coord_t y, int8_t idx, LcdFlags att) diff --git a/radio/src/gui/horus/lcd.h b/radio/src/gui/horus/lcd.h index 1c833b2b11..93cddcfce3 100644 --- a/radio/src/gui/horus/lcd.h +++ b/radio/src/gui/horus/lcd.h @@ -182,7 +182,7 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags=0, uint8_t void putsStrIdx(coord_t x, coord_t y, const pm_char *str, int idx, LcdFlags att=0, const char *prefix=""); void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att); void putsStickName(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0); -void putsSwitches(coord_t x, coord_t y, int8_t swtch, LcdFlags att=0); +void putsSwitches(coord_t x, coord_t y, swsrc_t swtch, LcdFlags flags=0); void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0); void putsFlightMode(coord_t x, coord_t y, int8_t idx, LcdFlags att=0); void putsCurveRef(coord_t x, coord_t y, CurveRef &curve, LcdFlags att=0); diff --git a/radio/src/gui/horus/menu_general_calib.cpp b/radio/src/gui/horus/menu_general_calib.cpp index dd2c2c6b66..786d0ad490 100644 --- a/radio/src/gui/horus/menu_general_calib.cpp +++ b/radio/src/gui/horus/menu_general_calib.cpp @@ -195,8 +195,8 @@ bool menuCommonCalib(evt_t event) StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[i]; steps = calib->count + 1; } - if (steps > 0 && steps <= XPOTS_MULTIPOS_COUNT) { - lcdDrawNumber(LCD_W/2-(POT_BAR_INTERVAL*NUM_POTS/2)+(POT_BAR_INTERVAL*(i-POT1)), POT_BAR_BOTTOM+15, steps, TEXT_COLOR|TINSIZE, 0, "[", "]"); + if (calibrationState != 0 && steps > 0 && steps <= XPOTS_MULTIPOS_COUNT) { + lcdDrawNumber(LCD_W/2+3-(POT_BAR_INTERVAL*NUM_POTS/2)+(POT_BAR_INTERVAL*(i-POT1)), POT_BAR_BOTTOM+15, steps, TEXT_COLOR|TINSIZE, 0, "[", "]"); } } diff --git a/radio/src/gui/horus/menu_general_setup.cpp b/radio/src/gui/horus/menu_general_setup.cpp index 77a7e4356e..8921a99447 100644 --- a/radio/src/gui/horus/menu_general_setup.cpp +++ b/radio/src/gui/horus/menu_general_setup.cpp @@ -338,7 +338,7 @@ bool menuGeneralSetup(evt_t event) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MEMORYWARNING); uint8_t b = 1-g_eeGeneral.disableMemoryWarning; - g_eeGeneral.disableMemoryWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, attr, event); + g_eeGeneral.disableMemoryWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, attr, event); break; } #endif @@ -347,7 +347,7 @@ bool menuGeneralSetup(evt_t event) { lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ALARMWARNING); uint8_t b = 1-g_eeGeneral.disableAlarmWarning; - g_eeGeneral.disableAlarmWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, attr, event); + g_eeGeneral.disableAlarmWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, attr, event); break; } @@ -385,7 +385,7 @@ bool menuGeneralSetup(evt_t event) case ITEM_SETUP_FLASH_BEEP: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ALARM); - g_eeGeneral.alarmsFlash = onoffMenuItem(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, attr, event ) ; + g_eeGeneral.alarmsFlash = editCheckBox(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, attr, event ) ; break; case ITEM_SETUP_BACKLIGHT_DELAY: @@ -462,7 +462,7 @@ bool menuGeneralSetup(evt_t event) #if 0 case ITEM_SETUP_FAI: lcdDrawText(MENUS_MARGIN_LEFT, y, PSTR("FAI Mode")); - g_eeGeneral.fai = onoffMenuItem(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, attr, event); + g_eeGeneral.fai = editCheckBox(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, attr, event); if (attr && checkIncDec_Ret) { if (g_eeGeneral.fai) POPUP_WARNING(PSTR("FAI\001mode blocked!")); diff --git a/radio/src/gui/horus/menu_model.cpp b/radio/src/gui/horus/menu_model.cpp index 3b09d3542b..f7f1224879 100644 --- a/radio/src/gui/horus/menu_model.cpp +++ b/radio/src/gui/horus/menu_model.cpp @@ -34,6 +34,8 @@ uint8_t editDelay(const coord_t x, const coord_t y, const evt_t event, const uin uint8_t s_copyMode = 0; int8_t s_copySrcRow; int8_t s_copyTgtOfs; +uint8_t s_copySrcIdx; +uint8_t s_copySrcCh; uint8_t editNameCursorPos = 0; diff --git a/radio/src/gui/horus/menu_model_curves.cpp b/radio/src/gui/horus/menu_model_curves.cpp index 5d390c2a31..133bfc61c4 100644 --- a/radio/src/gui/horus/menu_model_curves.cpp +++ b/radio/src/gui/horus/menu_model_curves.cpp @@ -135,7 +135,7 @@ enum MenuModelCurveOneItems { bool menuModelCurveOne(evt_t event) { static uint8_t pointsOfs = 0; - CurveInfo & crv = g_model.curves[s_curveChan]; + CurveData & crv = g_model.curves[s_curveChan]; int8_t * points = curveAddress(s_curveChan); SUBMENU(STR_MENUCURVE, crv.type==CURVE_TYPE_CUSTOM ? 6 : 5, 0, { 0, 0, 0, 0, uint8_t(5+crv.points-1), uint8_t(5+crv.points-1) }); @@ -144,7 +144,7 @@ bool menuModelCurveOne(evt_t event) // Curve name lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, STR_NAME); - editName(MODEL_CURVE_ONE_2ND_COLUMN, MENU_CONTENT_TOP, g_model.curveNames[s_curveChan], sizeof(g_model.curveNames[s_curveChan]), event, menuVerticalPosition==ITEM_CURVE_NAME); + editName(MODEL_CURVE_ONE_2ND_COLUMN, MENU_CONTENT_TOP, crv.name, sizeof(crv.name), event, menuVerticalPosition==ITEM_CURVE_NAME); // Curve type LcdFlags attr = (menuVerticalPosition==ITEM_CURVE_TYPE ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); @@ -328,6 +328,9 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, evt_t event, uint8_t a } } +#define CURVES_NAME_POS 60 +#define CURVES_POINTS_POS 120 + bool menuModelCurvesAll(evt_t event) { SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, MAX_CURVES, DEFAULT_SCROLLBAR_X); @@ -349,9 +352,9 @@ bool menuModelCurvesAll(evt_t event) LcdFlags attr = (sub == k ? INVERS : 0); { putsStrIdx(MENUS_MARGIN_LEFT, y, STR_CV, k+1, attr); - editName(50, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); - CurveInfo & crv = g_model.curves[k]; - lcdDrawNumber(120, y, 5+crv.points, LEFT, 0, NULL, STR_PTS); + CurveData & crv = g_model.curves[k]; + editName(CURVES_NAME_POS, y, crv.name, sizeof(crv.name), 0, 0); + lcdDrawNumber(CURVES_POINTS_POS, y, 5+crv.points, LEFT, 0, NULL, STR_PTS); } } diff --git a/radio/src/gui/horus/menu_model_custom_scripts.cpp b/radio/src/gui/horus/menu_model_custom_scripts.cpp index db6845d3c4..e608a283a8 100644 --- a/radio/src/gui/horus/menu_model_custom_scripts.cpp +++ b/radio/src/gui/horus/menu_model_custom_scripts.cpp @@ -53,7 +53,7 @@ bool menuModelCustomScriptOne(evt_t event) // putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); - SUBMENU(STR_MENUCUSTOMSCRIPT, 3+scriptInputsOutputs[s_currIdx].inputsCount, 0, { 0, 0, LABEL(inputs), 0/*repeated*/ }); + SUBMENU(STR_MENUCUSTOMSCRIPTS, 3+scriptInputsOutputs[s_currIdx].inputsCount, 0, { 0, 0, LABEL(inputs), 0/*repeated*/ }); int8_t sub = menuVerticalPosition; diff --git a/radio/src/gui/horus/menu_model_flightmodes.cpp b/radio/src/gui/horus/menu_model_flightmodes.cpp index 4554a09365..c70c86d368 100644 --- a/radio/src/gui/horus/menu_model_flightmodes.cpp +++ b/radio/src/gui/horus/menu_model_flightmodes.cpp @@ -21,6 +21,36 @@ #include #include "../../opentx.h" +void displayFlightModes(coord_t x, coord_t y, FlightModesType value, uint8_t attr) +{ + for (int i=0; i +#include "../../opentx.h" + +#define EXPO_ONE_2ND_COLUMN 110 + +int expoFn(int x) +{ + ExpoData * ed = expoAddress(s_currIdx); + int16_t anas[NUM_INPUTS] = {0}; + applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x); + return anas[ed->chn]; +} + +int getExposLinesCount() +{ + int lastch = -1; + uint8_t count = MAX_INPUTS; + for (int i=0; ichn; + if (ch == lastch) { + count++; + } + else { + lastch = ch; + } + } + return count; +} + +uint8_t getExposCount() +{ + uint8_t count = 0; + uint8_t ch ; + + for (int i=MAX_EXPOS-1 ; i>=0; i--) { + ch = EXPO_VALID(expoAddress(i)); + if (ch != 0) { + count++; + } + } + return count; +} + +bool reachExposLimit() +{ + if (getExposCount() >= MAX_EXPOS) { + POPUP_WARNING(STR_NOFREEEXPO); + return true; + } + return false; +} + +void deleteExpo(uint8_t idx) +{ + pauseMixerCalculations(); + ExpoData * expo = expoAddress(idx); + int input = expo->chn; + memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); + if (!isInputAvailable(input)) { + memclear(&g_model.inputNames[input], LEN_INPUT_NAME); + } + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +// TODO avoid this global s_currCh on ARM boards ... +int8_t s_currCh; +void insertExpo(uint8_t idx) +{ + pauseMixerCalculations(); + ExpoData * expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(expo, sizeof(ExpoData)); + expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); + expo->curve.type = CURVE_REF_EXPO; + expo->mode = 3; // pos+neg + expo->chn = s_currCh - 1; + expo->weight = 100; + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +void copyExpo(uint8_t idx) +{ + pauseMixerCalculations(); + ExpoData * expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +bool swapExpos(uint8_t & idx, uint8_t up) +{ + ExpoData * x, * y; + int8_t tgt_idx = (up ? idx-1 : idx+1); + + x = expoAddress(idx); + + if (tgt_idx < 0) { + if (x->chn == 0) + return false; + x->chn--; + return true; + } + + if (tgt_idx == MAX_EXPOS) { + if (x->chn == NUM_INPUTS-1) + return false; + x->chn++; + return true; + } + + y = expoAddress(tgt_idx); + if (x->chn != y->chn || !EXPO_VALID(y)) { + if (up) { + if (x->chn>0) x->chn--; + else return false; + } + else { + if (x->chnchn++; + else return false; + } + return true; + } + + pauseMixerCalculations(); + memswap(x, y, sizeof(ExpoData)); + resumeMixerCalculations(); + + idx = tgt_idx; + return true; +} + +enum ExposFields { + EXPO_FIELD_INPUT_NAME, + EXPO_FIELD_NAME, + EXPO_FIELD_SOURCE, + EXPO_FIELD_WEIGHT, + EXPO_FIELD_OFFSET, + CASE_CURVES(EXPO_FIELD_CURVE) + CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES) + EXPO_FIELD_SWITCH, + EXPO_FIELD_SIDE, + EXPO_FIELD_TRIM, + EXPO_FIELD_MAX +}; + +#define CURVE_ROWS 1 + +bool menuModelExpoOne(evt_t event) +{ + ExpoData * ed = expoAddress(s_currIdx); + + SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, 0, { 0, 0, (ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)1 : (uint8_t)0), 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); + + int sub = menuVerticalPosition; + + coord_t y = MENU_CONTENT_TOP; + + drawFunction(expoFn, CURVE_CENTER_X, CURVE_CENTER_Y, CURVE_SIDE_WIDTH); + drawCurveHorizontalScale(); + drawCurveVerticalScale(CURVE_CENTER_X-CURVE_SIDE_WIDTH-15); + + { + char textx[5]; + char texty[5]; + int x = getValue(ed->srcRaw); + if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { + sprintf(textx, "%d", calcRESXto100(x)); + // TODO putsTelemetryChannelValue(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x); + if (ed->scale > 0) x = (x * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); + } + else { + sprintf(textx, "%d", calcRESXto100(x)); + } + + x = limit(-1024, x, 1024); + int y = limit(-1024, expoFn(x), 1024); + sprintf(texty, "%d", calcRESXto100(y)); + + x = divRoundClosest(x*CURVE_SIDE_WIDTH, RESX); + y = CURVE_CENTER_Y + getCurveYCoord(expoFn, x, CURVE_SIDE_WIDTH); + + lcdDrawSolidFilledRect(CURVE_CENTER_X+x, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, 2, 2*CURVE_SIDE_WIDTH+2, CURVE_CURSOR_COLOR); + lcdDrawSolidFilledRect(CURVE_CENTER_X-CURVE_SIDE_WIDTH-2, y-1, 2*CURVE_SIDE_WIDTH+2, 2, CURVE_CURSOR_COLOR); + lcdDrawBitmapPattern(CURVE_CENTER_X+x-4, y-4, LBM_CURVE_POINT, CURVE_CURSOR_COLOR); + lcdDrawBitmapPattern(CURVE_CENTER_X+x-4, y-4, LBM_CURVE_POINT_CENTER, TEXT_BGCOLOR); + + int left = limit(CURVE_CENTER_X-CURVE_SIDE_WIDTH, CURVE_CENTER_X-CURVE_COORD_WIDTH/2+x, CURVE_CENTER_X+CURVE_SIDE_WIDTH-CURVE_COORD_WIDTH+2); + drawCurveCoord(left, CURVE_CENTER_Y+CURVE_SIDE_WIDTH+2, textx); + int top = limit(CURVE_CENTER_Y-CURVE_SIDE_WIDTH-1, -CURVE_COORD_HEIGHT/2+y, CURVE_CENTER_Y+CURVE_SIDE_WIDTH-CURVE_COORD_HEIGHT+1); + drawCurveCoord(CURVE_CENTER_X-CURVE_SIDE_WIDTH-37, top, texty); + } + + for (int i=0; i0 ? BLINK|INVERS : INVERS) : 0); + switch (i) { + case EXPO_FIELD_INPUT_NAME: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_INPUTNAME); + editName(EXPO_ONE_2ND_COLUMN, y, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); + break; + + case EXPO_FIELD_NAME: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_EXPONAME); + editName(EXPO_ONE_2ND_COLUMN, y, ed->name, sizeof(ed->name), event, attr); + break; + + case EXPO_FIELD_SOURCE: + lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_SOURCE)); + putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|(menuHorizontalPosition==0?attr:0)); + if (attr && menuHorizontalPosition==0) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); + if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN+60, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|(menuHorizontalPosition==1?attr:0)); + if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); + } + else if (attr) { + menuHorizontalPosition = 0; + } + break; + + case EXPO_FIELD_WEIGHT: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_WEIGHT); + ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, LEFT|attr, 0, event); + break; + + case EXPO_FIELD_OFFSET: + lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_OFFSET)); + ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); + break; + +#if defined(CURVES) + case EXPO_FIELD_CURVE: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CURVE); + editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); + break; +#endif + +#if defined(FLIGHT_MODES) + case EXPO_FIELD_FLIGHT_MODES: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FLMODE); + ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr); + break; +#endif + + case EXPO_FIELD_SWITCH: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SWITCH); + ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); + break; + + case EXPO_FIELD_SIDE: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SIDE); + ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); + break; + + case EXPO_FIELD_TRIM: + uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); + int8_t carryTrim = -ed->carryTrim; + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRIM); + lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0); + if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); + break; + } + y += FH; + } + + return true; +} + +#define _STR_MAX(x) PSTR("/" #x) +#define STR_MAX(x) _STR_MAX(x) + +#define EXPO_LINE_WEIGHT_POS 92 +#define EXPO_LINE_SRC_POS 115 +#define EXPO_LINE_CURVE_POS 162 +#define EXPO_LINE_SWITCH_POS 210 +#define EXPO_LINE_SIDE_POS 250 +#define EXPO_LINE_FM_POS 270 +#define EXPO_LINE_NAME_POS 384 +#define EXPO_LINE_SELECT_POS 50 +#define EXPO_LINE_SELECT_WIDTH (LCD_W-EXPO_LINE_SELECT_POS-15) + +void lineExpoSurround(coord_t y, LcdFlags flags=CURVE_AXIS_COLOR) +{ + lcdDrawRect(EXPO_LINE_SELECT_POS, y-INVERT_VERT_MARGIN+1, EXPO_LINE_SELECT_WIDTH, INVERT_LINE_HEIGHT, s_copyMode == COPY_MODE ? SOLID : DOTTED, flags); +} + +void onExposMenu(const char * result) +{ + uint8_t chn = expoAddress(s_currIdx)->chn + 1; + + if (result == STR_EDIT) { + pushMenu(menuModelExpoOne); + } + else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { + if (!reachExposLimit()) { + s_currCh = chn; + if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; } + insertExpo(s_currIdx); + pushMenu(menuModelExpoOne); + } + } + 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 = menuVerticalPosition; + } + else if (result == STR_DELETE) { + deleteExpo(s_currIdx); + } +} + +void displayExpoInfos(coord_t y, ExpoData *ed) +{ + putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve); + if (ed->swtch) { + putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch); + } + if (ed->mode != 3) { + lcdDrawText(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? "\176" : "\177"); + } +} + +void displayExpoLine(coord_t y, ExpoData *ed) +{ + putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw); + + displayExpoInfos(y, ed); + displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes, 0); + + if (ed->name[0]) { + lcdDrawSizedText(EXPO_LINE_NAME_POS, y+2, ed->name, sizeof(ed->name), ZCHAR|SMLSIZE); + } +} + +bool menuModelExposAll(evt_t event) +{ + int sub = menuVerticalPosition; + + if (s_editMode > 0) { + s_editMode = 0; + } + + uint8_t chn = expoAddress(s_currIdx)->chn + 1; + + int linesCount = getExposLinesCount(); + SIMPLE_MENU(STR_MENUINPUTS, menuTabModel, e_InputsAll, linesCount, DEFAULT_SCROLLBAR_X); + + 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) { + deleteExpo(s_currIdx); + killEvents(event); + event = 0; + } + // no break + case EVT_KEY_BREAK(KEY_EXIT): + if (s_copyMode) { + if (s_copyTgtOfs) { + // cancel the current copy / move operation + if (s_copyMode == COPY_MODE) { + deleteExpo(s_currIdx); + } + else { + do { + swapExpos(s_currIdx, s_copyTgtOfs > 0); + s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); + } while (s_copyTgtOfs != 0); + storageDirty(EE_MODEL); + } + menuVerticalPosition = s_copySrcRow; + s_copyTgtOfs = 0; + } + s_copyMode = 0; + event = 0; + } + break; + case EVT_KEY_BREAK(KEY_ENTER): + if ((!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_KEY_LONG(KEY_ENTER): + killEvents(event); + if (s_copyTgtOfs) { + s_copyMode = 0; + s_copyTgtOfs = 0; + } + else { + if (READ_ONLY()) { + if (!s_currCh) { + pushMenu(menuModelExpoOne); + } + } + else { + if (s_copyMode) s_currCh = 0; + if (s_currCh) { + if (reachExposLimit()) break; + insertExpo(s_currIdx); + pushMenu(menuModelExpoOne); + s_copyMode = 0; + } + else { + event = 0; + s_copyMode = 0; + POPUP_MENU_ADD_ITEM(STR_EDIT); + POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); + POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); + POPUP_MENU_ADD_ITEM(STR_COPY); + POPUP_MENU_ADD_ITEM(STR_MOVE); + POPUP_MENU_ADD_ITEM(STR_DELETE); + popupMenuHandler = onExposMenu; + } + } + } + break; + case EVT_KEY_LONG(KEY_LEFT): + case EVT_KEY_LONG(KEY_RIGHT): + if (s_copyMode && !s_copyTgtOfs) { + if (reachExposLimit()) break; + s_currCh = chn; + if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; } + insertExpo(s_currIdx); + pushMenu(menuModelExpoOne); + s_copyMode = 0; + killEvents(event); + } + break; + case EVT_KEY_FIRST(KEY_UP): + case EVT_KEY_REPT(KEY_UP): + case EVT_KEY_FIRST(KEY_DOWN): + case EVT_KEY_REPT(KEY_DOWN): + if (s_copyMode) { + uint8_t key = (event & 0x1f); + uint8_t next_ofs = ((event==EVT_ROTARY_LEFT || key==KEY_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 (reachExposLimit()) break; + copyExpo(s_currIdx); + if (event==EVT_ROTARY_RIGHT || key==KEY_DOWN) s_currIdx++; + else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; + } + else if (next_ofs==0 && s_copyMode==COPY_MODE) { + // delete the mix + deleteExpo(s_currIdx); + if (event==EVT_ROTARY_LEFT || key==KEY_UP) s_currIdx--; + } + else { + // only swap the mix with its neighbor + if (!swapExpos(s_currIdx, event==EVT_ROTARY_LEFT || key==KEY_UP)) break; + storageDirty(EE_MODEL); + } + + s_copyTgtOfs = next_ofs; + } + break; + } + + char str[6]; + sprintf(str, "%d/%d", getExposCount(), MAX_EXPOS); + lcdDrawText(MENU_TITLE_NEXT_POS, MENU_TITLE_TOP+2, str, HEADER_COLOR); + + sub = menuVerticalPosition; + s_currCh = 0; + int cur = 0; + int i = 0; + + for (int ch=1; ch<=NUM_INPUTS; ch++) { + ExpoData * ed; + coord_t y = MENU_CONTENT_TOP + (cur-menuVerticalOffset)*FH; + if ((ichn+1 == ch && EXPO_VALID(ed))) { + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsMixerSource(MENUS_MARGIN_LEFT, y, ch); + } + uint8_t mixCnt = 0; + do { + if (s_copyMode) { + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lineExpoSurround(y); + cur++; y+=FH; + } + if (s_currIdx == i) { + sub = menuVerticalPosition = cur; + s_currCh = ch; + } + } + else if (sub == cur) { + s_currIdx = i; + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS); + + GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0); + displayExpoLine(y, ed); + + 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) */ + lineExpoSurround(y); + } + if (cur == sub) { + /* invert the raw when it's the current one */ + lineExpoSurround(y, ALARM_COLOR); + } + } + } + cur++; y+=FH; mixCnt++; i++; ed++; + } while (ichn+1 == ch && EXPO_VALID(ed)); + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lineExpoSurround(y); + cur++; y+=FH; + } + } + else { + uint8_t attr = 0; + if (sub == cur) { + s_currIdx = i; + s_currCh = ch; + if (!s_copyMode) { + attr = INVERS; + } + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsMixerSource(MENUS_MARGIN_LEFT, y, ch, attr); + if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { + lineExpoSurround(y); + } + } + cur++; y+=FH; + } + } + + if (sub >= linesCount-1) menuVerticalPosition = linesCount-1; + + return true; +} + diff --git a/radio/src/gui/horus/menu_model_inputs_mixes.cpp b/radio/src/gui/horus/menu_model_inputs_mixes.cpp deleted file mode 100644 index 9645c6a164..0000000000 --- a/radio/src/gui/horus/menu_model_inputs_mixes.cpp +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include "../../opentx.h" - -#define EXPO_ONE_2ND_COLUMN 110 - -#if defined(FLIGHT_MODES) -void displayFlightModes(coord_t x, coord_t y, FlightModesType value, uint8_t attr) -{ - for (int i=0; isrcRaw, x); - return anas[ed->chn]; -} - -int getLinesCount(uint8_t expo) -{ - int lastch = -1; - uint8_t count = (expo ? MAX_INPUTS : NUM_CHNOUT); - for (int i=0; i<(expo ? MAX_EXPOS : MAX_MIXERS); i++) { - bool valid = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw); - if (!valid) - break; - int ch = (expo ? expoAddress(i)->chn : mixAddress(i)->destCh); - if (ch == lastch) { - count++; - } - else { - lastch = ch; - } - } - return count; -} - -uint8_t getExpoMixCount(uint8_t expo) -{ - uint8_t count = 0; - uint8_t ch ; - - for(int8_t i=(expo ? MAX_EXPOS-1 : MAX_MIXERS-1); 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); - int input = expo->chn; - memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); - if (!isInputAvailable(input)) { - memclear(&g_model.inputNames[input], LEN_INPUT_NAME); - } - } - 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(); - storageDirty(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)); - expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); - expo->curve.type = CURVE_REF_EXPO; - expo->mode = 3; // pos&neg - 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; - 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)); - while (!isSourceAvailable(mix->srcRaw)) { - mix->srcRaw += 1; - } - } - mix->weight = 100; - } - resumeMixerCalculations(); - storageDirty(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(); - storageDirty(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_INPUTS-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 { - EXPO_FIELD_INPUT_NAME, - EXPO_FIELD_NAME, - EXPO_FIELD_SOURCE, - EXPO_FIELD_WEIGHT, - EXPO_FIELD_OFFSET, - CASE_CURVES(EXPO_FIELD_CURVE) - CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES) - EXPO_FIELD_SWITCH, - EXPO_FIELD_SIDE, - EXPO_FIELD_TRIM, - EXPO_FIELD_MAX -}; - -#define CURVE_ROWS 1 - -bool menuModelExpoOne(evt_t event) -{ - ExpoData *ed = expoAddress(s_currIdx); - - SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, 0, { 0, 0, (ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)1 : (uint8_t)0), 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); - - int sub = menuVerticalPosition; - - coord_t y = MENU_CONTENT_TOP; - - drawFunction(expoFn, CURVE_CENTER_X, CURVE_CENTER_Y, CURVE_SIDE_WIDTH); - drawCurveHorizontalScale(); - drawCurveVerticalScale(CURVE_CENTER_X-CURVE_SIDE_WIDTH-15); - - { - char textx[5]; - char texty[5]; - int x = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - sprintf(textx, "%d", calcRESXto100(x)); - // TODO putsTelemetryChannelValue(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x); - if (ed->scale > 0) x = (x * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); - } - else { - sprintf(textx, "%d", calcRESXto100(x)); - } - - x = limit(-1024, x, 1024); - int y = limit(-1024, expoFn(x), 1024); - sprintf(texty, "%d", calcRESXto100(y)); - - x = divRoundClosest(x*CURVE_SIDE_WIDTH, RESX); - y = CURVE_CENTER_Y + getCurveYCoord(expoFn, x, CURVE_SIDE_WIDTH); - - lcdDrawSolidFilledRect(CURVE_CENTER_X+x, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, 2, 2*CURVE_SIDE_WIDTH+2, CURVE_CURSOR_COLOR); - lcdDrawSolidFilledRect(CURVE_CENTER_X-CURVE_SIDE_WIDTH-2, y-1, 2*CURVE_SIDE_WIDTH+2, 2, CURVE_CURSOR_COLOR); - lcdDrawBitmapPattern(CURVE_CENTER_X+x-4, y-4, LBM_CURVE_POINT, CURVE_CURSOR_COLOR); - lcdDrawBitmapPattern(CURVE_CENTER_X+x-4, y-4, LBM_CURVE_POINT_CENTER, TEXT_BGCOLOR); - - int left = limit(CURVE_CENTER_X-CURVE_SIDE_WIDTH, CURVE_CENTER_X-CURVE_COORD_WIDTH/2+x, CURVE_CENTER_X+CURVE_SIDE_WIDTH-CURVE_COORD_WIDTH+2); - drawCurveCoord(left, CURVE_CENTER_Y+CURVE_SIDE_WIDTH+2, textx); - int top = limit(CURVE_CENTER_Y-CURVE_SIDE_WIDTH-1, -CURVE_COORD_HEIGHT/2+y, CURVE_CENTER_Y+CURVE_SIDE_WIDTH-CURVE_COORD_HEIGHT+1); - drawCurveCoord(CURVE_CENTER_X-CURVE_SIDE_WIDTH-37, top, texty); - } - - for (int i=0; i0 ? BLINK|INVERS : INVERS) : 0); - switch (i) { - case EXPO_FIELD_INPUT_NAME: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_INPUTNAME); - editName(EXPO_ONE_2ND_COLUMN, y, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); - break; - - case EXPO_FIELD_NAME: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_EXPONAME); - editName(EXPO_ONE_2ND_COLUMN, y, ed->name, sizeof(ed->name), event, attr); - break; - - case EXPO_FIELD_SOURCE: - lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_SOURCE)); - putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|(menuHorizontalPosition==0?attr:0)); - if (attr && menuHorizontalPosition==0) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN+60, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|(menuHorizontalPosition==1?attr:0)); - if (attr && menuHorizontalPosition == 1) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); - } - else if (attr) { - menuHorizontalPosition = 0; - } - break; - - case EXPO_FIELD_WEIGHT: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_WEIGHT); - ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, LEFT|attr, 0, event); - break; - - case EXPO_FIELD_OFFSET: - lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_OFFSET)); - ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); - break; - -#if defined(CURVES) - case EXPO_FIELD_CURVE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CURVE); - editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); - break; -#endif - -#if defined(FLIGHT_MODES) - case EXPO_FIELD_FLIGHT_MODES: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FLMODE); - ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr); - break; -#endif - - case EXPO_FIELD_SWITCH: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SWITCH); - ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); - break; - - case EXPO_FIELD_SIDE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SIDE); - ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); - break; - - case EXPO_FIELD_TRIM: - uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); - int8_t carryTrim = -ed->carryTrim; - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRIM); - lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0); - if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - break; - } - y += FH; - } - - return true; -} - -enum MixFields { - MIX_FIELD_NAME, - MIX_FIELD_SOURCE, - MIX_FIELD_WEIGHT, - MIX_FIELD_OFFSET, - MIX_FIELD_TRIM, - CASE_CURVES(MIX_FIELD_CURVE) - CASE_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(coord_t x, coord_t y, MixData *md, uint8_t attr, evt_t event) -{ - u_int8int16_t weight; - MD_WEIGHT_TO_UNION(md, weight); - weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event); - MD_UNION_TO_WEIGHT(weight, md); -} - -#if 0 -#define GAUGE_WIDTH 33 -#define GAUGE_HEIGHT 6 -void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) -{ - int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); - int weight = abs(GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode)); - int barMin = offset - weight; - int barMax = offset + weight; - if (y > 15) { - lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT); - lcdDrawNumber(x+GAUGE_WIDTH+1, y-6, barMax, TINSIZE); - } - if (barMin < -101) - barMin = -101; - if (barMax > 101) - barMax = 101; - lcdDrawHorizontalLine(x-2, y, GAUGE_WIDTH+2, DOTTED); - lcdDrawHorizontalLine(x-2, y+GAUGE_HEIGHT, GAUGE_WIDTH+2, DOTTED); - lcdDrawSolidVerticalLine(x-2, y+1, GAUGE_HEIGHT-1); - lcdDrawSolidVerticalLine(x+GAUGE_WIDTH-1, y+1, GAUGE_HEIGHT-1); - if (barMin <= barMax) { - int8_t right = (barMax * GAUGE_WIDTH) / 200; - int8_t left = ((barMin * GAUGE_WIDTH) / 200)-1; - lcdDrawSolidFilledRect(x+GAUGE_WIDTH/2+left, y+2, right-left, GAUGE_HEIGHT-3); - } - lcdDrawSolidVerticalLine(x+GAUGE_WIDTH/2-1, y, GAUGE_HEIGHT+1); - if (barMin == -101) { - for (uint8_t i=0; i<3; ++i) { - lcdDrawPoint(x+i, y+4-i); - lcdDrawPoint(x+3+i, y+4-i); - } - } - if (barMax == 101) { - for (uint8_t i=0; i<3; ++i) { - lcdDrawPoint(x+GAUGE_WIDTH-8+i, y+4-i); - lcdDrawPoint(x+GAUGE_WIDTH-5+i, y+4-i); - } - } -} -#undef GAUGE_WIDTH -#undef GAUGE_HEIGHT -#endif - -bool menuModelMixOne(evt_t event) -{ - MixData *md2 = mixAddress(s_currIdx) ; - - SUBMENU(s_currCh ? STR_INSERTMIX : STR_EDITMIX, MIX_FIELD_COUNT, 0, { 0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/ }); - - putsChn(MENU_TITLE_NEXT_POS, MENU_TITLE_TOP+1, md2->destCh+1, TEXT_COLOR); - - // The separation line between 2 columns - lcdDrawSolidVerticalLine(MENU_COLUMN2_X-20, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H+5, TEXT_COLOR); - - int8_t sub = menuVerticalPosition; - int8_t editMode = s_editMode; - - for (int k=0; k<2*NUM_BODY_LINES; k++) { - coord_t y; - if (k >= NUM_BODY_LINES) { - y = MENU_CONTENT_TOP + (k-NUM_BODY_LINES)*FH + 2; - } - else { - y = MENU_CONTENT_TOP + k*FH + 2; - } - int8_t i = k; - - LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); - switch(i) { - case MIX_FIELD_NAME: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MIXNAME); - editName(MIXES_2ND_COLUMN, y, md2->name, sizeof(md2->name), event, attr); - break; - case MIX_FIELD_SOURCE: - lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_SOURCE)); - putsMixerSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); - if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); - break; - case MIX_FIELD_WEIGHT: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_WEIGHT); - gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); - break; - case MIX_FIELD_OFFSET: - { - lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_OFFSET)); - u_int8int16_t offset; - MD_OFFSET_TO_UNION(md2, offset); - offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); -#if 0 - drawOffsetBar(x+MIXES_2ND_COLUMN+22, y, md2); -#endif - break; - } - case MIX_FIELD_TRIM: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRIM); - drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr); - if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1); - break; -#if defined(CURVES) - case MIX_FIELD_CURVE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CURVE); - editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr); - break; -#endif -#if defined(FLIGHT_MODES) - case MIX_FIELD_FLIGHT_PHASE: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FLMODE); - md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr); - break; -#endif - case MIX_FIELD_SWITCH: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SWITCH); - md2->swtch = switchMenuItem(MIXES_2ND_COLUMN, y, md2->swtch, attr, event); - break; - case MIX_FIELD_MLTPX: - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTPX); - md2->mltpx = selectMenuItem(MIXES_2ND_COLUMN, y, STR_VMLTPX, md2->mltpx, 0, 2, attr, event); - break; - case MIX_FIELD_DELAY_UP: - lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_DELAYUP); - md2->delayUp = editDelay(MENU_COLUMN2_X, y, event, attr, md2->delayUp); - break; - case MIX_FIELD_DELAY_DOWN: - lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_DELAYDOWN); - md2->delayDown = editDelay(MENU_COLUMN2_X, y, event, attr, md2->delayDown); - break; - case MIX_FIELD_SLOW_UP: - lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_SLOWUP); - md2->speedUp = editDelay(MENU_COLUMN2_X, y, event, attr, md2->speedUp); - break; - case MIX_FIELD_SLOW_DOWN: - lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_SLOWDOWN); - md2->speedDown = editDelay(MENU_COLUMN2_X, y, event, attr, md2->speedDown); - break; - } - } - - return true; -} - -static uint8_t s_copySrcIdx; -static uint8_t s_copySrcCh; - -#define _STR_MAX(x) PSTR("/" #x) -#define STR_MAX(x) _STR_MAX(x) - -#define EXPO_LINE_WEIGHT_POS 92 -#define EXPO_LINE_SRC_POS 115 -#define EXPO_LINE_CURVE_POS 162 -#define EXPO_LINE_SWITCH_POS 210 -#define EXPO_LINE_SIDE_POS 250 -#define EXPO_LINE_FM_POS 270 -#define EXPO_LINE_NAME_POS 380 -#define EXPO_LINE_SELECT_POS 50 -#define EXPO_LINE_SELECT_WIDTH (LCD_W-EXPO_LINE_SELECT_POS-5) - -#define MIX_LINE_WEIGHT_POS 92 -#define MIX_LINE_SRC_POS 115 -#define MIX_LINE_CURVE_POS 162 -#define MIX_LINE_SWITCH_POS 210 -#define MIX_LINE_DELAY_POS 255 -#define MIX_LINE_FM_POS 270 -#define MIX_LINE_NAME_POS 380 -#define MIX_LINE_SELECT_POS 50 -#define MIX_LINE_SELECT_WIDTH (LCD_W-EXPO_LINE_SELECT_POS-5) - -void lineSurround(bool expo, coord_t y, LcdFlags flags=CURVE_AXIS_COLOR) -{ - lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : MIX_LINE_SELECT_POS, y-INVERT_VERT_MARGIN, expo ? EXPO_LINE_SELECT_WIDTH : MIX_LINE_SELECT_WIDTH, INVERT_LINE_HEIGHT, (s_copyMode == COPY_MODE ? SOLID : DOTTED), flags); -} - -void onExpoMixMenu(const char *result) -{ - bool expo = (menuHandlers[menuLevel] == 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++; menuVerticalPosition++; } - 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 = menuVerticalPosition; - } - else if (result == STR_DELETE) { - deleteExpoMix(expo, s_currIdx); - } -} - -void displayHeaderChannelName(uint8_t ch) -{ - uint8_t len = zlen(g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name)); - if (len) { - lcdDrawSizedText(COLUMN_HEADER_X, MENU_FOOTER_TOP, g_model.limitData[ch-1].name, len, HEADER_COLOR|ZCHAR); - } -} - -void displayMixInfos(coord_t y, MixData *md) -{ - putsCurveRef(MIX_LINE_CURVE_POS, y, md->curve); - - if (md->swtch) { - putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); - } -} - -void displayMixLine(coord_t y, MixData *md) -{ - if (md->name[0]) - lcdDrawSizedText(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR); - displayMixInfos(y, md); - displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes, 0); -} - -void displayExpoInfos(coord_t y, ExpoData *ed) -{ - putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve); - if (ed->swtch) { - putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch); - } - if (ed->mode != 3) { - lcdDrawText(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? "\176" : "\177"); - } -} - -void displayExpoLine(coord_t y, ExpoData *ed) -{ - putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw); - - displayExpoInfos(y, ed); - displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes, 0); - - if (ed->name[0]) { - lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR); - } -} - -bool menuModelExpoMix(uint8_t expo, evt_t event) -{ - int sub = menuVerticalPosition; - - if (s_editMode > 0) - s_editMode = 0; - - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - int linesCount = getLinesCount(expo); - SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, linesCount, DEFAULT_SCROLLBAR_X); - - 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 - 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); - storageDirty(EE_MODEL); - } - menuVerticalPosition = s_copySrcRow; - s_copyTgtOfs = 0; - } - s_copyMode = 0; - event = 0; - } - break; - case EVT_KEY_BREAK(KEY_ENTER): - if ((!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_KEY_LONG(KEY_ENTER): - killEvents(event); - if (s_copyTgtOfs) { - s_copyMode = 0; - s_copyTgtOfs = 0; - } - else { - if (READ_ONLY()) { - if (!s_currCh) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - } - else { - if (s_copyMode) s_currCh = 0; - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - } - else { - event = 0; - s_copyMode = 0; - POPUP_MENU_ADD_ITEM(STR_EDIT); - POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); - POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); - POPUP_MENU_ADD_ITEM(STR_COPY); - POPUP_MENU_ADD_ITEM(STR_MOVE); - POPUP_MENU_ADD_ITEM(STR_DELETE); - popupMenuHandler = onExpoMixMenu; - } - } - } - 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++; menuVerticalPosition++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - killEvents(event); - } - break; - case EVT_KEY_FIRST(KEY_UP): - case EVT_KEY_REPT(KEY_UP): - case EVT_KEY_FIRST(KEY_DOWN): - case EVT_KEY_REPT(KEY_DOWN): - if (s_copyMode) { - uint8_t key = (event & 0x1f); - uint8_t next_ofs = ((event==EVT_ROTARY_LEFT || key==KEY_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 (event==EVT_ROTARY_RIGHT || key==KEY_DOWN) s_currIdx++; - else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; - } - else if (next_ofs==0 && s_copyMode==COPY_MODE) { - // delete the mix - deleteExpoMix(expo, s_currIdx); - if (event==EVT_ROTARY_LEFT || key==KEY_UP) s_currIdx--; - } - else { - // only swap the mix with its neighbor - if (!swapExpoMix(expo, s_currIdx, event==EVT_ROTARY_LEFT || key==KEY_UP)) break; - storageDirty(EE_MODEL); - } - - s_copyTgtOfs = next_ofs; - } - break; - } - - char str[6]; - sprintf(str, "%d/%d", getExpoMixCount(expo), expo ? MAX_EXPOS : MAX_MIXERS); - lcdDrawText(MENU_TITLE_NEXT_POS, MENU_TITLE_TOP+2, str, HEADER_COLOR); - - sub = menuVerticalPosition; - s_currCh = 0; - int cur = 0; - int i = 0; - - for (int ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { - void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; - coord_t y = MENU_CONTENT_TOP + (cur-menuVerticalOffset)*FH; - if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { - if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - if (expo) { - putsMixerSource(MENUS_MARGIN_LEFT, y, ch); - } - else { - putsChn(MENUS_MARGIN_LEFT, y, ch, 0); // show CHx - } - } - uint8_t mixCnt = 0; - do { - if (s_copyMode) { - if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lineSurround(expo, y); - cur++; y+=FH; - } - if (s_currIdx == i) { - sub = menuVerticalPosition = cur; - s_currCh = ch; - } - } - else if (sub == cur) { - s_currIdx = i; - } - if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - if (expo) { - GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0); - displayExpoLine(y, ed); - } - else { - if (attr) { - displayHeaderChannelName(ch); - } - - if (mixCnt > 0) lcdDrawTextAtIndex(6, y, STR_VMLTPX2, md->mltpx, 0); - - putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw); - - gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event); - - displayMixLine(y, md); - - char cs[] = " "; - if (md->speedDown || md->speedUp) - cs[0] = 'S'; - if (md->delayUp || md->delayDown) - cs[0] = (cs[0] =='S' ? '*' : 'D'); - lcdDrawText(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) */ - lineSurround(expo, y); - } - if (cur == sub) { - /* invert the raw when it's the current one */ - lineSurround(expo, y, ALARM_COLOR); - } - } - } - 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 && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lineSurround(expo, y); - cur++; y+=FH; - } - } - else { - uint8_t attr = 0; - if (sub == cur) { - s_currIdx = i; - s_currCh = ch; - if (!s_copyMode) { - attr = INVERS; - } - } - if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - if (expo) { - putsMixerSource(MENUS_MARGIN_LEFT, y, ch, attr); - } - else { - putsChn(MENUS_MARGIN_LEFT, y, ch, attr); // show CHx - if (attr) { - displayHeaderChannelName(ch); - } - } - if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { - lineSurround(expo, y); - } - } - cur++; y+=FH; - } - } - - if (sub >= linesCount-1) menuVerticalPosition = linesCount-1; - - return true; -} - -bool menuModelExposAll(evt_t event) -{ - return menuModelExpoMix(1, event); -} - -bool menuModelMixAll(evt_t event) -{ - return menuModelExpoMix(0, event); -} diff --git a/radio/src/gui/horus/menu_model_mixes.cpp b/radio/src/gui/horus/menu_model_mixes.cpp new file mode 100644 index 0000000000..ae02a1c0ce --- /dev/null +++ b/radio/src/gui/horus/menu_model_mixes.cpp @@ -0,0 +1,571 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "../../opentx.h" +#include + +int getMixesLinesCount() +{ + int lastch = -1; + uint8_t count = NUM_CHNOUT; + for (int i=0; isrcRaw; + if (!valid) + break; + int ch = mixAddress(i)->destCh; + if (ch == lastch) { + count++; + } + else { + lastch = ch; + } + } + return count; +} + +uint8_t getMixesCount() +{ + uint8_t count = 0; + uint8_t ch ; + + for (int i=MAX_MIXERS-1; i>=0; i--) { + ch = mixAddress(i)->srcRaw; + if (ch != 0) { + count++; + } + } + return count; +} + +bool reachMixesLimit() +{ + if (getMixesCount() >= MAX_MIXERS) { + POPUP_WARNING(STR_NOFREEMIXER); + return true; + } + return false; +} + +void deleteMix(uint8_t idx) +{ + pauseMixerCalculations(); + MixData * mix = mixAddress(idx); + memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData)); + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +void insertMix(uint8_t idx) +{ + pauseMixerCalculations(); + MixData * mix = mixAddress(idx); + memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + memclear(mix, sizeof(MixData)); + mix->destCh = s_currCh-1; + 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)); + while (!isSourceAvailable(mix->srcRaw)) { + mix->srcRaw += 1; + } + } + mix->weight = 100; + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +void copyMix(uint8_t idx) +{ + pauseMixerCalculations(); + MixData * mix = mixAddress(idx); + memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +bool swapMixes(uint8_t & idx, uint8_t up) +{ + MixData * x, * y; + int8_t tgt_idx = (up ? idx-1 : idx+1); + + x = mixAddress(idx); + + if (tgt_idx < 0) { + if (x->destCh == 0) + return false; + x->destCh--; + return true; + } + + if (tgt_idx == MAX_MIXERS) { + if (x->destCh == NUM_CHNOUT-1) + return false; + x->destCh++; + return true; + } + + y = mixAddress(tgt_idx); + uint8_t destCh = x->destCh; + if(!y->srcRaw || destCh != y->destCh) { + if (up) { + if (destCh>0) x->destCh--; + else return false; + } + else { + if (destChdestCh++; + else return false; + } + return true; + } + + pauseMixerCalculations(); + memswap(x, y, sizeof(MixData)); + resumeMixerCalculations(); + + idx = tgt_idx; + return true; +} + +enum MixFields { + MIX_FIELD_NAME, + MIX_FIELD_SOURCE, + MIX_FIELD_WEIGHT, + MIX_FIELD_OFFSET, + MIX_FIELD_TRIM, + CASE_CURVES(MIX_FIELD_CURVE) + CASE_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(coord_t x, coord_t y, MixData *md, uint8_t attr, evt_t event) +{ + u_int8int16_t weight; + MD_WEIGHT_TO_UNION(md, weight); + weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event); + MD_UNION_TO_WEIGHT(weight, md); +} + +bool menuModelMixOne(evt_t event) +{ + MixData *md2 = mixAddress(s_currIdx) ; + + SUBMENU(STR_MIXER, MIX_FIELD_COUNT, 0, { 0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/ }); + + putsChn(MENU_TITLE_NEXT_POS, MENU_TITLE_TOP+1, md2->destCh+1, TEXT_COLOR); + + // The separation line between 2 columns + lcdDrawSolidVerticalLine(MENU_COLUMN2_X-20, DEFAULT_SCROLLBAR_Y, DEFAULT_SCROLLBAR_H+5, TEXT_COLOR); + + int8_t sub = menuVerticalPosition; + int8_t editMode = s_editMode; + + for (int k=0; k<2*NUM_BODY_LINES; k++) { + coord_t y; + if (k >= NUM_BODY_LINES) { + y = MENU_CONTENT_TOP + (k-NUM_BODY_LINES)*FH + 2; + } + else { + y = MENU_CONTENT_TOP + k*FH + 2; + } + int8_t i = k; + + LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); + switch(i) { + case MIX_FIELD_NAME: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MIXNAME); + editName(MIXES_2ND_COLUMN, y, md2->name, sizeof(md2->name), event, attr); + break; + case MIX_FIELD_SOURCE: + lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_SOURCE)); + putsMixerSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); + if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); + break; + case MIX_FIELD_WEIGHT: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_WEIGHT); + gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); + break; + case MIX_FIELD_OFFSET: + { + lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_OFFSET)); + u_int8int16_t offset; + MD_OFFSET_TO_UNION(md2, offset); + offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event); + MD_UNION_TO_OFFSET(offset, md2); +#if 0 + drawOffsetBar(x+MIXES_2ND_COLUMN+22, y, md2); +#endif + break; + } + case MIX_FIELD_TRIM: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRIM); + drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr); + if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1); + break; +#if defined(CURVES) + case MIX_FIELD_CURVE: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CURVE); + editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr); + break; +#endif +#if defined(FLIGHT_MODES) + case MIX_FIELD_FLIGHT_PHASE: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FLMODE); + md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr); + break; +#endif + case MIX_FIELD_SWITCH: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_SWITCH); + md2->swtch = switchMenuItem(MIXES_2ND_COLUMN, y, md2->swtch, attr, event); + break; + case MIX_FIELD_MLTPX: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MULTPX); + md2->mltpx = selectMenuItem(MIXES_2ND_COLUMN, y, STR_VMLTPX, md2->mltpx, 0, 2, attr, event); + break; + case MIX_FIELD_DELAY_UP: + lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_DELAYUP); + md2->delayUp = editDelay(MENU_COLUMN2_X, y, event, attr, md2->delayUp); + break; + case MIX_FIELD_DELAY_DOWN: + lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_DELAYDOWN); + md2->delayDown = editDelay(MENU_COLUMN2_X, y, event, attr, md2->delayDown); + break; + case MIX_FIELD_SLOW_UP: + lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_SLOWUP); + md2->speedUp = editDelay(MENU_COLUMN2_X, y, event, attr, md2->speedUp); + break; + case MIX_FIELD_SLOW_DOWN: + lcdDrawText(MENU_COLUMN2_X+MENUS_MARGIN_LEFT, y, STR_SLOWDOWN); + md2->speedDown = editDelay(MENU_COLUMN2_X, y, event, attr, md2->speedDown); + break; + } + } + + return true; +} + +#define _STR_MAX(x) PSTR("/" #x) +#define STR_MAX(x) _STR_MAX(x) + +#define MIX_LINE_WEIGHT_POS 92 +#define MIX_LINE_SRC_POS 115 +#define MIX_LINE_CURVE_POS 162 +#define MIX_LINE_SWITCH_POS 210 +#define MIX_LINE_DELAY_POS 255 +#define MIX_LINE_FM_POS 270 +#define MIX_LINE_NAME_POS 384 +#define MIX_LINE_SELECT_POS 50 +#define MIX_LINE_SELECT_POS 50 +#define MIX_LINE_SELECT_WIDTH (LCD_W-MIX_LINE_SELECT_POS-15) + +void lineMixSurround(coord_t y, LcdFlags flags=CURVE_AXIS_COLOR) +{ + lcdDrawRect(MIX_LINE_SELECT_POS, y-INVERT_VERT_MARGIN+1, MIX_LINE_SELECT_WIDTH, INVERT_LINE_HEIGHT, s_copyMode == COPY_MODE ? SOLID : DOTTED, flags); +} + +void onMixesMenu(const char * result) +{ + uint8_t chn = mixAddress(s_currIdx)->destCh + 1; + + if (result == STR_EDIT) { + pushMenu(menuModelMixOne); + } + else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { + if (!reachMixesLimit()) { + s_currCh = chn; + if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; } + insertMix(s_currIdx); + pushMenu(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 = menuVerticalPosition; + } + else if (result == STR_DELETE) { + deleteMix(s_currIdx); + } +} + +void displayHeaderChannelName(uint8_t ch) +{ + uint8_t len = zlen(g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name)); + if (len) { + lcdDrawSizedText(COLUMN_HEADER_X, MENU_FOOTER_TOP, g_model.limitData[ch-1].name, len, HEADER_COLOR|ZCHAR); + } +} + +void displayMixInfos(coord_t y, MixData *md) +{ + putsCurveRef(MIX_LINE_CURVE_POS, y, md->curve); + + if (md->swtch) { + putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); + } +} + +void displayMixLine(coord_t y, MixData *md) +{ + if (md->name[0]) { + lcdDrawSizedText(MIX_LINE_NAME_POS, y+2, md->name, sizeof(md->name), ZCHAR | SMLSIZE); + } + displayMixInfos(y, md); + displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes, 0); +} + +bool menuModelMixAll(evt_t event) +{ + int sub = menuVerticalPosition; + + if (s_editMode > 0) { + s_editMode = 0; + } + + uint8_t chn = mixAddress(s_currIdx)->destCh + 1; + + int linesCount = getMixesLinesCount(); + SIMPLE_MENU(STR_MIXER, menuTabModel, e_MixAll, linesCount, DEFAULT_SCROLLBAR_X); + + 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) { + deleteMix(s_currIdx); + killEvents(event); + event = 0; + } + // no break + case EVT_KEY_BREAK(KEY_EXIT): + if (s_copyMode) { + if (s_copyTgtOfs) { + // cancel the current copy / move operation + if (s_copyMode == COPY_MODE) { + deleteMix(s_currIdx); + } + else { + do { + swapMixes(s_currIdx, s_copyTgtOfs > 0); + s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); + } while (s_copyTgtOfs != 0); + storageDirty(EE_MODEL); + } + menuVerticalPosition = s_copySrcRow; + s_copyTgtOfs = 0; + } + s_copyMode = 0; + event = 0; + } + break; + case EVT_KEY_BREAK(KEY_ENTER): + if ((!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_KEY_LONG(KEY_ENTER): + killEvents(event); + if (s_copyTgtOfs) { + s_copyMode = 0; + s_copyTgtOfs = 0; + } + else { + if (READ_ONLY()) { + if (!s_currCh) { + pushMenu(menuModelMixOne); + } + } + else { + if (s_copyMode) s_currCh = 0; + if (s_currCh) { + if (reachMixesLimit()) break; + insertMix(s_currIdx); + pushMenu(menuModelMixOne); + s_copyMode = 0; + } + else { + event = 0; + s_copyMode = 0; + POPUP_MENU_ADD_ITEM(STR_EDIT); + POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); + POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); + POPUP_MENU_ADD_ITEM(STR_COPY); + POPUP_MENU_ADD_ITEM(STR_MOVE); + POPUP_MENU_ADD_ITEM(STR_DELETE); + popupMenuHandler = onMixesMenu; + } + } + } + break; + case EVT_KEY_LONG(KEY_LEFT): + case EVT_KEY_LONG(KEY_RIGHT): + if (s_copyMode && !s_copyTgtOfs) { + if (reachMixesLimit()) break; + s_currCh = chn; + if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; } + insertMix(s_currIdx); + pushMenu(menuModelMixOne); + s_copyMode = 0; + killEvents(event); + } + break; + case EVT_KEY_FIRST(KEY_UP): + case EVT_KEY_REPT(KEY_UP): + case EVT_KEY_FIRST(KEY_DOWN): + case EVT_KEY_REPT(KEY_DOWN): + if (s_copyMode) { + uint8_t key = (event & 0x1f); + uint8_t next_ofs = ((event==EVT_ROTARY_LEFT || key==KEY_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 (reachMixesLimit()) break; + copyMix(s_currIdx); + if (event==EVT_ROTARY_RIGHT || key==KEY_DOWN) s_currIdx++; + else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; + } + else if (next_ofs==0 && s_copyMode==COPY_MODE) { + // delete the mix + deleteMix(s_currIdx); + if (event==EVT_ROTARY_LEFT || key==KEY_UP) s_currIdx--; + } + else { + // only swap the mix with its neighbor + if (!swapMixes(s_currIdx, event==EVT_ROTARY_LEFT || key==KEY_UP)) break; + storageDirty(EE_MODEL); + } + + s_copyTgtOfs = next_ofs; + } + break; + } + + char str[6]; + sprintf(str, "%d/%d", getMixesCount(), MAX_MIXERS); + lcdDrawText(MENU_TITLE_NEXT_POS, MENU_TITLE_TOP+2, str, HEADER_COLOR); + + sub = menuVerticalPosition; + s_currCh = 0; + int cur = 0; + int i = 0; + + for (int ch=1; ch<=NUM_CHNOUT; ch++) { + MixData * md; + coord_t y = MENU_CONTENT_TOP + (cur-menuVerticalOffset)*FH; + if (isrcRaw && md->destCh+1 == ch) { + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsChn(MENUS_MARGIN_LEFT, y, ch, 0); // show CHx + } + uint8_t mixCnt = 0; + do { + if (s_copyMode) { + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lineMixSurround(y); + cur++; y+=FH; + } + if (s_currIdx == i) { + sub = menuVerticalPosition = cur; + s_currCh = ch; + } + } + else if (sub == cur) { + s_currIdx = i; + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS); + if (attr) { + displayHeaderChannelName(ch); + } + + if (mixCnt > 0) lcdDrawTextAtIndex(6, y, STR_VMLTPX2, md->mltpx, 0); + + putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw); + + gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event); + + displayMixLine(y, md); + + char cs[] = " "; + if (md->speedDown || md->speedUp) + cs[0] = 'S'; + if (md->delayUp || md->delayDown) + cs[0] = (cs[0] =='S' ? '*' : 'D'); + lcdDrawText(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) */ + lineMixSurround(y); + } + if (cur == sub) { + /* invert the raw when it's the current one */ + lineMixSurround(y, ALARM_COLOR); + } + } + } + cur++; y+=FH; mixCnt++; i++; md++; + } while (isrcRaw && md->destCh+1 == ch); + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lineMixSurround(y); + cur++; y+=FH; + } + } + else { + uint8_t attr = 0; + if (sub == cur) { + s_currIdx = i; + s_currCh = ch; + if (!s_copyMode) { + attr = INVERS; + } + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsChn(MENUS_MARGIN_LEFT, y, ch, attr); // show CHx + if (attr) { + displayHeaderChannelName(ch); + } + if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { + lineMixSurround(y); + } + } + cur++; y+=FH; + } + } + + if (sub >= linesCount-1) menuVerticalPosition = linesCount-1; + + return true; +} diff --git a/radio/src/gui/horus/menu_model_setup.cpp b/radio/src/gui/horus/menu_model_setup.cpp index 252257e56d..078fa09733 100644 --- a/radio/src/gui/horus/menu_model_setup.cpp +++ b/radio/src/gui/horus/menu_model_setup.cpp @@ -50,7 +50,7 @@ enum menuModelSetupItems { ITEM_MODEL_DISPLAY_TRIMS, ITEM_MODEL_TRIM_INC, ITEM_MODEL_THROTTLE_LABEL, - // ITEM_MODEL_THROTTLE_REVERSED, + ITEM_MODEL_THROTTLE_REVERSED, ITEM_MODEL_THROTTLE_TRACE, ITEM_MODEL_THROTTLE_TRIM, ITEM_MODEL_PREFLIGHT_LABEL, @@ -60,6 +60,11 @@ enum menuModelSetupItems { ITEM_MODEL_POT_WARNING, ITEM_MODEL_BEEP_CENTER, ITEM_MODEL_USE_GLOBAL_FUNCTIONS, + 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, @@ -134,7 +139,7 @@ void editTimerMode(int timerIdx, coord_t y, LcdFlags attr, evt_t event) } } -#define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : EXTERNAL_MODULE) +#define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE)) int getSwitchWarningsCount() { @@ -147,29 +152,48 @@ int getSwitchWarningsCount() return count; } +#define INTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(INTERNAL_MODULE) ? (uint8_t)1 : (uint8_t)0) // Module type + RF protocols +#define IF_INTERNAL_MODULE_ON(x) (g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF ? HIDDEN_ROW : (uint8_t)(x)) +#define IF_EXTERNAL_MODULE_ON(x) (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x)) +#define IF_TRAINER_ON(x) (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)(x) : HIDDEN_ROW) +#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) +#define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW) +#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1) +#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON((IS_MODULE_DSM2(EXTERNAL_MODULE) || IS_MODULE_CROSSFIRE(EXTERNAL_MODULE)) ? (uint8_t)0 : (uint8_t)1) +#define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) +#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : TRAINER_CHANNELS_ROWS())) +#define FAILSAFE_ROWS(x) (HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) +#define TIMER_ROWS NAVIGATION_LINE_BY_LINE|1, 0, CASE_PERSISTENT_TIMERS(0) 0, 0 +#define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0 +#if TIMERS == 1 + #define TIMERS_ROWS TIMER_ROWS +#elif TIMERS == 2 + #define TIMERS_ROWS TIMER_ROWS, TIMER_ROWS +#elif TIMERS == 3 + #define TIMERS_ROWS TIMER_ROWS, TIMER_ROWS, TIMER_ROWS +#endif +#define SW_WARN_ITEMS() uint8_t(NAVIGATION_LINE_BY_LINE|(getSwitchWarningsCount()-1)) +#define POT_WARN_ITEMS() ((g_model.potsWarnMode >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0) bool menuModelSetup(evt_t event) { horzpos_t l_posHorz = menuHorizontalPosition; - #define IF_EXTERNAL_MODULE_ON(x) (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x)) - #define IF_TRAINER_ON(x) (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)(x) : HIDDEN_ROW) - #define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)x : HIDDEN_ROW) - #define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) - #define EXTERNAL_MODULE_CHANNELS_ROWS() IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1) - #define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) - #define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_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 POT_WARN_ITEMS() ((g_model.potsWarnMode >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0) - #define TIMER_ROWS NAVIGATION_LINE_BY_LINE|1, 0, CASE_PERSISTENT_TIMERS(0) 0, 0 - #if TIMERS == 1 - #define TIMERS_ROWS TIMER_ROWS - #elif TIMERS == 2 - #define TIMERS_ROWS TIMER_ROWS, TIMER_ROWS - #elif TIMERS == 3 - #define TIMERS_ROWS TIMER_ROWS, TIMER_ROWS, TIMER_ROWS - #endif bool CURSOR_ON_CELL = (menuHorizontalPosition >= 0); - MENU(STR_MENUSETUP, menuTabModel, e_ModelSetup, ITEM_MODEL_SETUP_MAX, DEFAULT_SCROLLBAR_X, { 0, 0, TIMERS_ROWS, 0, 1, 0, 0, LABEL(Throttle), 0, 0, LABEL(PreflightCheck), 0, 0, uint8_t(NAVIGATION_LINE_BY_LINE|(getSwitchWarningsCount()-1)), POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), 0, LABEL(ExternalModule), (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, EXTERNAL_MODULE_CHANNELS_ROWS(), (IS_MODULE_XJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2) }); + MENU(STR_MENUSETUP, menuTabModel, e_ModelSetup, ITEM_MODEL_SETUP_MAX, DEFAULT_SCROLLBAR_X, + { 0, 0, TIMERS_ROWS, 0, 1, 0, 0, + LABEL(Throttle), 0, 0, 0, + LABEL(PreflightCheck), 0, 0, SW_WARN_ITEMS(), POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), 0, + LABEL(InternalModule), + INTERNAL_MODULE_MODE_ROWS, + INTERNAL_MODULE_CHANNELS_ROWS, + IF_INTERNAL_MODULE_ON(IS_MODULE_XJT(INTERNAL_MODULE) ? (HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[INTERNAL_MODULE].rfProtocol) ? (uint8_t)2 : (uint8_t)1) : (IS_MODULE_PPM(INTERNAL_MODULE) ? (uint8_t)1 : HIDDEN_ROW)), + IF_INTERNAL_MODULE_ON((IS_MODULE_XJT(INTERNAL_MODULE)) ? FAILSAFE_ROWS(INTERNAL_MODULE) : HIDDEN_ROW), + LABEL(ExternalModule), + (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, + EXTERNAL_MODULE_CHANNELS_ROWS, + (IS_MODULE_XJT(EXTERNAL_MODULE) && !HAS_RF_PROTOCOL_MODELINDEX(g_model.moduleData[EXTERNAL_MODULE].rfProtocol)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW, + IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), + LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2) }); #if (defined(DSM2) || defined(PXX)) if (menuEvent) { @@ -227,7 +251,7 @@ bool menuModelSetup(evt_t event) case ITEM_MODEL_TIMER1_MINUTE_BEEP: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MINUTEBEEP); - g_model.timers[0].minuteBeep = onoffMenuItem(g_model.timers[0].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.timers[0].minuteBeep = editCheckBox(g_model.timers[0].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP: @@ -252,7 +276,7 @@ bool menuModelSetup(evt_t event) case ITEM_MODEL_TIMER2_MINUTE_BEEP: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MINUTEBEEP); - g_model.timers[1].minuteBeep = onoffMenuItem(g_model.timers[1].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.timers[1].minuteBeep = editCheckBox(g_model.timers[1].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP: @@ -278,7 +302,7 @@ bool menuModelSetup(evt_t event) case ITEM_MODEL_TIMER3_MINUTE_BEEP: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MINUTEBEEP); - g_model.timers[2].minuteBeep = onoffMenuItem(g_model.timers[2].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.timers[2].minuteBeep = editCheckBox(g_model.timers[2].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_TIMER3_COUNTDOWN_BEEP: @@ -294,12 +318,12 @@ bool menuModelSetup(evt_t event) case ITEM_MODEL_EXTENDED_LIMITS: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ELIMITS); - g_model.extendedLimits = onoffMenuItem(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.extendedLimits = editCheckBox(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_EXTENDED_TRIMS: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ETRIMS); - g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, menuHorizontalPosition<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0); + g_model.extendedTrims = editCheckBox(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, menuHorizontalPosition<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0); lcdDrawText(MODEL_SETUP_2ND_COLUMN+18, y, STR_RESET_BTN, menuHorizontalPosition>0 && !NO_HIGHLIGHT() ? attr : 0); if (attr && menuHorizontalPosition>0) { s_editMode = 0; @@ -328,11 +352,10 @@ bool menuModelSetup(evt_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_THROTTLE_LABEL); break; -#if 0 case ITEM_MODEL_THROTTLE_REVERSED: - ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ; + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_THROTTLEREVERSE); + g_model.throttleReversed = editCheckBox(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; -#endif case ITEM_MODEL_THROTTLE_TRACE: { @@ -349,7 +372,7 @@ bool menuModelSetup(evt_t event) case ITEM_MODEL_THROTTLE_TRIM: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TTRIM); - g_model.thrTrim = onoffMenuItem(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.thrTrim = editCheckBox(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_PREFLIGHT_LABEL: @@ -358,12 +381,12 @@ bool menuModelSetup(evt_t event) case ITEM_MODEL_CHECKLIST_DISPLAY: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_CHECKLIST); - g_model.displayChecklist = onoffMenuItem(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.displayChecklist = editCheckBox(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_THROTTLE_WARNING: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_THROTTLEWARNING); - g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, attr, event); + g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, attr, event); break; case ITEM_MODEL_SWITCHES_WARNING: @@ -379,7 +402,7 @@ bool menuModelSetup(evt_t event) } if (attr && menuHorizontalPosition < 0) { - lcdDrawSolidFilledRect(MODEL_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN, NUM_SWITCHES*18+INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); + lcdDrawSolidFilledRect(MODEL_SETUP_2ND_COLUMN-INVERT_HORZ_MARGIN, y-INVERT_VERT_MARGIN+1, (NUM_SWITCHES-1)*25+INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); } unsigned int newStates = 0; @@ -395,16 +418,12 @@ bool menuModelSetup(evt_t event) color |= INVERS; } char s[3]; - s[0] = 'A' + i + (i >= 3 ? 1 : 0 /* skip SD which is a POT*/); + s[0] = 'A' + i; int max; if (state == 0) { s[1] = 'x'; max = 2; } - else if (i == 2) { - s[1] = '0' + state; - max = 6; - } else if (IS_3POS(i)) { s[1] = "\300-\301"[state-1]; max = 3; @@ -414,7 +433,7 @@ bool menuModelSetup(evt_t event) max = 2; } s[2] = '\0'; - lcdDrawText(MODEL_SETUP_2ND_COLUMN+i*18, y, s, color|(menuHorizontalPosition==current ? attr : 0)); + lcdDrawText(MODEL_SETUP_2ND_COLUMN+i*25, y, s, color|(menuHorizontalPosition==current ? attr : 0)); if (attr && menuHorizontalPosition==current) CHECK_INCDEC_MODELVAR_ZERO(event, state, max); newStates |= (state << (3*i)); ++current; @@ -488,11 +507,28 @@ bool menuModelSetup(evt_t event) break; case ITEM_MODEL_USE_GLOBAL_FUNCTIONS: - lcdDrawText(MENUS_MARGIN_LEFT, y, "Use Global Funcs"); + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_USE_GLOBAL_FUNCS); drawCheckBox(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr); if (attr) g_model.noGlobalFunctions = !checkIncDecModel(event, !g_model.noGlobalFunctions, 0, 1); break; + case ITEM_MODEL_INTERNAL_MODULE_LABEL: + lcdDrawText(MENUS_MARGIN_LEFT, y, TR_INTERNALRF); + break; + + case ITEM_MODEL_INTERNAL_MODULE_MODE: + lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODE); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[0].rfProtocol, attr); + if (attr) { + g_model.moduleData[INTERNAL_MODULE].rfProtocol = checkIncDec(event, g_model.moduleData[INTERNAL_MODULE].rfProtocol, RF_PROTO_OFF, RF_PROTO_LAST, EE_MODEL, isRfProtocolAvailable); + if (checkIncDec_Ret) { + g_model.moduleData[0].type = MODULE_TYPE_XJT; + g_model.moduleData[0].channelsStart = 0; + g_model.moduleData[0].channelsCount = 0; + } + } + break; + case ITEM_MODEL_TRAINER_MODE: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODE); g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerMode, TRAINER_MODE_MASTER, TRAINER_MODE_SLAVE, attr, event); @@ -539,6 +575,7 @@ bool menuModelSetup(evt_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TRAINER); break; + case ITEM_MODEL_INTERNAL_MODULE_CHANNELS: case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS: case ITEM_MODEL_TRAINER_CHANNELS: { @@ -567,6 +604,7 @@ bool menuModelSetup(evt_t event) break; } + case ITEM_MODEL_INTERNAL_MODULE_BIND: case ITEM_MODEL_EXTERNAL_MODULE_BIND: case ITEM_MODEL_TRAINER_SETTINGS: { @@ -624,6 +662,7 @@ bool menuModelSetup(evt_t event) break; } + case ITEM_MODEL_INTERNAL_MODULE_FAILSAFE: case ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE: { uint8_t moduleIdx = CURRENT_MODULE_EDITED(k); diff --git a/radio/src/gui/horus/menu_model_telemetry.cpp b/radio/src/gui/horus/menu_model_telemetry.cpp index 99aef636be..21aa3d7f90 100644 --- a/radio/src/gui/horus/menu_model_telemetry.cpp +++ b/radio/src/gui/horus/menu_model_telemetry.cpp @@ -207,19 +207,19 @@ bool menuModelSensor(evt_t event) // lcdDrawNumber(MENUS_MARGIN_LEFT+getTextWidth(TR_MENUSENSOR)+5, MENU_FOOTER_TOP, s_currIdx+1, HEADER_COLOR|LEFT); // putsTelemetryChannelValue(SENSOR_2ND_COLUMN, MENU_FOOTER_TOP, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), HEADER_COLOR|LEFT); - int sub = menuVerticalPosition; - for (unsigned int i=0; i= (int)DIM(mstate_tab)) { + return true; + } } } - LcdFlags attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0); + LcdFlags attr = (menuVerticalPosition==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0); switch (k) { @@ -409,27 +409,27 @@ bool menuModelSensor(evt_t event) case SENSOR_FIELD_AUTOOFFSET: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_AUTOOFFSET); - sensor->autoOffset = onoffMenuItem(sensor->autoOffset, SENSOR_2ND_COLUMN, y, attr, event); + sensor->autoOffset = editCheckBox(sensor->autoOffset, SENSOR_2ND_COLUMN, y, attr, event); break; case SENSOR_FIELD_ONLYPOSITIVE: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_ONLYPOSITIVE); - sensor->onlyPositive = onoffMenuItem(sensor->onlyPositive, SENSOR_2ND_COLUMN, y, attr, event); + sensor->onlyPositive = editCheckBox(sensor->onlyPositive, SENSOR_2ND_COLUMN, y, attr, event); break; case SENSOR_FIELD_FILTER: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FILTER); - sensor->filter = onoffMenuItem(sensor->filter, SENSOR_2ND_COLUMN, y, attr, event); + sensor->filter = editCheckBox(sensor->filter, SENSOR_2ND_COLUMN, y, attr, event); break; case SENSOR_FIELD_PERSISTENT: lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_PERSISTENT)); - sensor->persistent = onoffMenuItem(sensor->persistent, SENSOR_2ND_COLUMN, y, attr, event); + sensor->persistent = editCheckBox(sensor->persistent, SENSOR_2ND_COLUMN, y, attr, event); break; case SENSOR_FIELD_LOGS: lcdDrawText(MENUS_MARGIN_LEFT, y, STR_LOGS); - sensor->logs = onoffMenuItem(sensor->logs, SENSOR_2ND_COLUMN, y, attr, event); + sensor->logs = editCheckBox(sensor->logs, SENSOR_2ND_COLUMN, y, attr, event); if (attr && checkIncDec_Ret) { closeLogs(); } @@ -478,8 +478,7 @@ void onSensorMenu(const char *result) #if defined(LUA) void onTelemetryScriptFileSelectionMenu(const char *result) { - int sub = menuVerticalPosition; - int screenIndex = TELEMETRY_CURRENT_SCREEN(sub); + int screenIndex = TELEMETRY_CURRENT_SCREEN(menuVerticalPosition); if (result == STR_UPDATE_LIST) { if (!sdListFiles(SCRIPTS_TELEM_PATH, SCRIPTS_EXT, sizeof(g_model.frsky.screens[screenIndex].script.file), NULL)) { @@ -506,8 +505,6 @@ bool menuModelTelemetry(evt_t event) MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX, DEFAULT_SCROLLBAR_X, { TELEMETRY_TYPE_ROWS RSSI_ROWS SENSORS_ROWS VARIO_ROWS LABEL(TopBar), 0, 0, TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), TELEMETRY_SCREEN_ROWS(2), TELEMETRY_SCREEN_ROWS(3) }); - int sub = menuVerticalPosition; - for (int i=0; i0) ? BLINK|INVERS : INVERS); - LcdFlags attr = (sub == k ? blink : 0); + LcdFlags attr = (menuVerticalPosition == k ? blink : 0); if (k>=ITEM_TELEMETRY_SENSOR1 && k0) { - int8_t swtch = getMovedSwitch(); + swsrc_t swtch = getMovedSwitch(); if (swtch) { div_t info = switchInfo(swtch); if (IS_TOGGLE(info.quot)) { if (info.rem != 0) { - val = (val == swtch ? swtch+2 : swtch); + val = (val == swtch ? swtch-2 : swtch); } } else { @@ -54,6 +55,57 @@ INIT_STOPS(stops100, 3, -100, 0, 100) INIT_STOPS(stops1000, 3, -1000, 0, 1000) INIT_STOPS(stopsSwitch, 15, SWSRC_FIRST, CATEGORY_END(-SWSRC_FIRST_LOGICAL_SWITCH), CATEGORY_END(-SWSRC_FIRST_TRIM), CATEGORY_END(-SWSRC_LAST_SWITCH+1), 0, CATEGORY_END(SWSRC_LAST_SWITCH), CATEGORY_END(SWSRC_FIRST_TRIM-1), CATEGORY_END(SWSRC_FIRST_LOGICAL_SWITCH-1), SWSRC_LAST) +void onSourceLongEnterPress(const char * result) +{ + if (result == STR_MENU_INPUTS) + checkIncDecSelection = getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable)+1; +#if defined(LUA_MODEL_SCRIPTS) + else if (result == STR_MENU_LUA) + checkIncDecSelection = getFirstAvailable(MIXSRC_FIRST_LUA, MIXSRC_LAST_LUA, isSourceAvailable); +#endif + else if (result == STR_MENU_STICKS) + checkIncDecSelection = MIXSRC_FIRST_STICK; + else if (result == STR_MENU_POTS) + checkIncDecSelection = MIXSRC_FIRST_POT; + else if (result == STR_MENU_MAX) + checkIncDecSelection = MIXSRC_MAX; + else if (result == STR_MENU_HELI) + checkIncDecSelection = MIXSRC_FIRST_HELI; + else if (result == STR_MENU_TRIMS) + checkIncDecSelection = MIXSRC_FIRST_TRIM; + else if (result == STR_MENU_SWITCHES) + checkIncDecSelection = MIXSRC_FIRST_SWITCH; + else if (result == STR_MENU_TRAINER) + checkIncDecSelection = MIXSRC_FIRST_TRAINER; + else if (result == STR_MENU_CHANNELS) + checkIncDecSelection = getFirstAvailable(MIXSRC_FIRST_CH, MIXSRC_LAST_CH, isSourceAvailable); + else if (result == STR_MENU_GVARS) + checkIncDecSelection = MIXSRC_FIRST_GVAR; + else if (result == STR_MENU_TELEMETRY) { + for (int i = 0; i < MAX_SENSORS; i++) { + TelemetrySensor * sensor = & g_model.telemetrySensors[i]; + if (sensor->isAvailable()) { + checkIncDecSelection = MIXSRC_FIRST_TELEM + 3*i; + break; + } + } + } +} + +void onSwitchLongEnterPress(const char *result) +{ + if (result == STR_MENU_SWITCHES) + checkIncDecSelection = SWSRC_FIRST_SWITCH; + else if (result == STR_MENU_TRIMS) + checkIncDecSelection = SWSRC_FIRST_TRIM; + else if (result == STR_MENU_LOGICAL_SWITCHES) + checkIncDecSelection = SWSRC_FIRST_LOGICAL_SWITCH + getFirstAvailable(0, NUM_LOGICAL_SWITCH, isLogicalSwitchAvailable); + else if (result == STR_MENU_OTHER) + checkIncDecSelection = SWSRC_ON; + else if (result == STR_MENU_INVERT) + checkIncDecSelection = SWSRC_INVERT; +} + int checkIncDec(evt_t event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops) { int newval = val; @@ -192,6 +244,85 @@ int checkIncDec(evt_t event, int val, int i_min, int i_max, unsigned int i_flags else { checkIncDec_Ret = 0; } + + if (i_flags & INCDEC_SOURCE) { + if (event == EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + checkIncDecSelection = MIXSRC_NONE; + + TRACE("count items avant = %d", popupMenuNoItems); + + if (i_min <= MIXSRC_FIRST_INPUT && i_max >= MIXSRC_FIRST_INPUT) { + if (getFirstAvailable(MIXSRC_FIRST_INPUT, MIXSRC_LAST_INPUT, isInputAvailable) != MIXSRC_NONE) { + POPUP_MENU_ADD_ITEM(STR_MENU_INPUTS); + } + } +#if defined(LUA_MODEL_SCRIPTS) + if (i_min <= MIXSRC_FIRST_LUA && i_max >= MIXSRC_FIRST_LUA) { + if (getFirstAvailable(MIXSRC_FIRST_LUA, MIXSRC_LAST_LUA, isSourceAvailable) != MIXSRC_NONE) { + POPUP_MENU_ADD_ITEM(STR_MENU_LUA); + } + } +#endif + if (i_min <= MIXSRC_FIRST_STICK && i_max >= MIXSRC_FIRST_STICK) POPUP_MENU_ADD_ITEM(STR_MENU_STICKS); + if (i_min <= MIXSRC_FIRST_POT && i_max >= MIXSRC_FIRST_POT) POPUP_MENU_ADD_ITEM(STR_MENU_POTS); + if (i_min <= MIXSRC_MAX && i_max >= MIXSRC_MAX) POPUP_MENU_ADD_ITEM(STR_MENU_MAX); +#if defined(HELI) + if (i_min <= MIXSRC_FIRST_HELI && i_max >= MIXSRC_FIRST_HELI) POPUP_MENU_ADD_ITEM(STR_MENU_HELI); +#endif + if (i_min <= MIXSRC_FIRST_TRIM && i_max >= MIXSRC_FIRST_TRIM) POPUP_MENU_ADD_ITEM(STR_MENU_TRIMS); + if (i_min <= MIXSRC_FIRST_SWITCH && i_max >= MIXSRC_FIRST_SWITCH) POPUP_MENU_ADD_ITEM(STR_MENU_SWITCHES); + if (i_min <= MIXSRC_FIRST_TRAINER && i_max >= MIXSRC_FIRST_TRAINER) POPUP_MENU_ADD_ITEM(STR_MENU_TRAINER); + if (i_min <= MIXSRC_FIRST_CH && i_max >= MIXSRC_FIRST_CH) POPUP_MENU_ADD_ITEM(STR_MENU_CHANNELS); + if (i_min <= MIXSRC_FIRST_GVAR && i_max >= MIXSRC_FIRST_GVAR && isValueAvailable(MIXSRC_FIRST_GVAR)) { + POPUP_MENU_ADD_ITEM(STR_MENU_GVARS); + } + + if (i_min <= MIXSRC_FIRST_TELEM && i_max >= MIXSRC_FIRST_TELEM) { + for (int i = 0; i < MAX_SENSORS; i++) { + TelemetrySensor * sensor = & g_model.telemetrySensors[i]; + if (sensor->isAvailable()) { + POPUP_MENU_ADD_ITEM(STR_MENU_TELEMETRY); + break; + } + } + } + popupMenuHandler = onSourceLongEnterPress; + + TRACE("count items apres = %d", popupMenuNoItems); + } + if (checkIncDecSelection != 0) { + newval = checkIncDecSelection; + if (checkIncDecSelection != MIXSRC_MAX) + s_editMode = EDIT_MODIFY_FIELD; + checkIncDecSelection = 0; + } + } + else if (i_flags & INCDEC_SWITCH) { + if (event == EVT_KEY_LONG(KEY_ENTER)) { + killEvents(event); + checkIncDecSelection = SWSRC_NONE; + if (i_min <= SWSRC_FIRST_SWITCH && i_max >= SWSRC_LAST_SWITCH) POPUP_MENU_ADD_ITEM(STR_MENU_SWITCHES); + if (i_min <= SWSRC_FIRST_TRIM && i_max >= SWSRC_LAST_TRIM) POPUP_MENU_ADD_ITEM(STR_MENU_TRIMS); + if (i_min <= SWSRC_FIRST_LOGICAL_SWITCH && i_max >= SWSRC_LAST_LOGICAL_SWITCH) { + for (int i = 0; i < NUM_LOGICAL_SWITCH; i++) { + if (isValueAvailable && isValueAvailable(SWSRC_FIRST_LOGICAL_SWITCH+i)) { + POPUP_MENU_ADD_ITEM(STR_MENU_LOGICAL_SWITCHES); + break; + } + } + } + if (isValueAvailable && isValueAvailable(SWSRC_ON)) POPUP_MENU_ADD_ITEM(STR_MENU_OTHER); + if (isValueAvailable && isValueAvailable(-newval)) POPUP_MENU_ADD_ITEM(STR_MENU_INVERT); + popupMenuHandler = onSwitchLongEnterPress; + s_editMode = EDIT_MODIFY_FIELD; + } + if (checkIncDecSelection != 0) { + newval = (checkIncDecSelection == SWSRC_INVERT ? -newval : checkIncDecSelection); + s_editMode = EDIT_MODIFY_FIELD; + checkIncDecSelection = 0; + } + } return newval; } @@ -319,8 +450,7 @@ bool check(check_event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, u menuPageCount = menuTabSize; } - switch(event) - { + switch(event) { case EVT_ENTRY: menuVerticalPosition = (menuTab ? -1 : MENU_FIRST_LINE_EDIT); menuHorizontalPosition = POS_HORZ_INIT(0); @@ -353,6 +483,10 @@ bool check(check_event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, u break; } + if (s_copyMode > 0) { + break; + } + if (menuHorizontalPosition >= 0 && (COLATTR(menuVerticalPosition) & NAVIGATION_LINE_BY_LINE)) { menuHorizontalPosition = -1; } diff --git a/radio/src/gui/horus/popups.cpp b/radio/src/gui/horus/popups.cpp index 9d17260813..b3f06c6fae 100644 --- a/radio/src/gui/horus/popups.cpp +++ b/radio/src/gui/horus/popups.cpp @@ -29,12 +29,13 @@ uint8_t warningInfoFlags = ZCHAR; int16_t warningInputValue; int16_t warningInputValueMin; int16_t warningInputValueMax; -void (*popupFunc)(evt_t event) = NULL; +void (*popupFunc)(evt_t event) = NULL; const char *popupMenuItems[POPUP_MENU_MAX_LINES]; -uint8_t s_menu_item = 0; -uint16_t popupMenuNoItems = 0; -uint16_t popupMenuOffset = 0; -void (*popupMenuHandler)(const char *result); +uint8_t s_menu_item = 0; +uint16_t popupMenuNoItems = 0; +uint16_t popupMenuOffset = 0; +uint8_t popupMenuOffsetType = MENU_OFFSET_INTERNAL; +void (*popupMenuHandler)(const char * result); void displayAlertBox() { @@ -61,7 +62,7 @@ void displayMessageBox() // lcdDrawBitmap(POPUP_X+15, POPUP_Y+20, LBM_MESSAGE); } -void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SOUND_ARG) +void drawMessageBox(const char * title, const char * t, const char * last, uint8_t sound) { displayAlertBox(); @@ -78,7 +79,11 @@ void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SO lcdDrawText(WARNING_LINE_X, WARNING_INFOLINE_Y+16, last); AUDIO_ERROR_MESSAGE(sound); } +} +void message(const pm_char * title, const pm_char * t, const char * last, uint8_t sound) +{ + drawMessageBox(title, t, last, sound); lcdRefresh(); lcdSetContrast(); clearKeyEvents(); @@ -125,7 +130,8 @@ void displayWarning(evt_t event) const char * displayPopupMenu(evt_t event) { const char * result = NULL; - uint8_t display_count = min(popupMenuNoItems, (uint16_t)POPUP_MENU_MAX_LINES); + + uint8_t display_count = min(popupMenuNoItems, MENU_MAX_DISPLAY_LINES); switch (event) { case EVT_ROTARY_LEFT: @@ -139,9 +145,9 @@ const char * displayPopupMenu(evt_t event) result = STR_UPDATE_LIST; } else { - s_menu_item = display_count - 1; - if (popupMenuNoItems > POPUP_MENU_MAX_LINES) { - popupMenuOffset = popupMenuNoItems - display_count; + s_menu_item = min(display_count, MENU_MAX_DISPLAY_LINES) - 1; + if (popupMenuNoItems > MENU_MAX_DISPLAY_LINES) { + popupMenuOffset = popupMenuNoItems - MENU_MAX_DISPLAY_LINES; result = STR_UPDATE_LIST; } } @@ -166,7 +172,7 @@ const char * displayPopupMenu(evt_t event) } break; case EVT_KEY_BREAK(KEY_ENTER): - result = popupMenuItems[s_menu_item]; + result = popupMenuItems[s_menu_item + (popupMenuOffsetType == MENU_OFFSET_INTERNAL ? popupMenuOffset : 0)]; // no break case EVT_KEY_BREAK(KEY_EXIT): popupMenuNoItems = 0; @@ -183,10 +189,10 @@ const char * displayPopupMenu(evt_t event) for (uint8_t i=0; i 0) { - s_gvar_timer = 0; + if (gvarDisplayTimer > 0) { + gvarDisplayTimer = 0; } #endif AUDIO_KEYPAD_UP(); @@ -388,12 +388,12 @@ bool menuMainView(evt_t event) } #if 0 - if (s_gvar_timer > 0) { - s_gvar_timer--; + if (gvarDisplayTimer > 0) { + gvarDisplayTimer--; displayMessageBox(); - putsStrIdx(WARNING_LINE_X, WARNING_LINE_Y, STR_GV, s_gvar_last+1, DBLSIZE|YELLOW); - lcdDrawSizedText(WARNING_LINE_X+45, WARNING_LINE_Y, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, DBLSIZE|YELLOW|ZCHAR); - lcdDrawNumber(WARNING_LINE_X, WARNING_INFOLINE_Y, GVAR_VALUE(s_gvar_last, getGVarFlightPhase(mixerCurrentFlightMode, s_gvar_last)), DBLSIZE|LEFT); + putsStrIdx(WARNING_LINE_X, WARNING_LINE_Y, STR_GV, gvarLastChanged+1, DBLSIZE|YELLOW); + lcdDrawSizedText(WARNING_LINE_X+45, WARNING_LINE_Y, g_model.gvars[gvarLastChanged].name, LEN_GVAR_NAME, DBLSIZE|YELLOW|ZCHAR); + lcdDrawNumber(WARNING_LINE_X, WARNING_INFOLINE_Y, GVAR_VALUE(gvarLastChanged, getGVarFlightMode(mixerCurrentFlightMode, gvarLastChanged)), DBLSIZE|LEFT); } #endif diff --git a/radio/src/gui/horus/widgets.cpp b/radio/src/gui/horus/widgets.cpp index 175d4a949e..a76bc3ee6b 100644 --- a/radio/src/gui/horus/widgets.cpp +++ b/radio/src/gui/horus/widgets.cpp @@ -238,7 +238,7 @@ select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char * values, return value; } -uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, LcdFlags attr, evt_t event ) +uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, LcdFlags attr, evt_t event ) { drawCheckBox(x, y, value, attr); return selectMenuItem(x, y, NULL, value, 0, 1, attr, event); @@ -269,12 +269,12 @@ bool noZero(int val) return val != 0; } -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, evt_t event) +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, evt_t event) { uint16_t delta = GV_GET_GV1_VALUE(max); bool invers = (attr & INVERS); - // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + // TRACE("editGVarFieldValue(val=%d min=%d max=%d)", value, min, max); if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { s_editMode = !s_editMode; @@ -316,7 +316,7 @@ int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t m return value; } #else -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, evt_t event) +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, evt_t event) { if (attr & INVERS) value = checkIncDec(event, value, min, max, EE_MODEL); lcdDrawNumber(x, y, value, attr, 0, NULL, "%"); @@ -324,8 +324,8 @@ int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t m } #endif -#define SLEEP_BITMAP_WIDTH 60 -#define SLEEP_BITMAP_HEIGHT 60 +#define SLEEP_BITMAP_WIDTH 110 +#define SLEEP_BITMAP_HEIGHT 110 void drawSleepBitmap() { lcdClear(); @@ -333,11 +333,12 @@ void drawSleepBitmap() lcdRefresh(); } -#define SHUTDOWN_BITMAP_WIDTH 60 -#define SHUTDOWN_BITMAP_HEIGHT 60 +#define SHUTDOWN_BITMAP_WIDTH 110 +#define SHUTDOWN_BITMAP_HEIGHT 110 void drawShutdownBitmap(uint8_t index) { - lcdClear(); + // lcdClear(); lcdDrawBitmap((LCD_W-SHUTDOWN_BITMAP_WIDTH)/2, (LCD_H-SHUTDOWN_BITMAP_HEIGHT)/2, LBM_SHUTDOWN, index*SHUTDOWN_BITMAP_WIDTH, SHUTDOWN_BITMAP_WIDTH); + lcdDrawBitmapPatternPie((LCD_W-150)/2, (LCD_H-150)/2, LBM_BIGRSCALE, TEXT_COLOR, 0, 360/4*index); lcdRefresh(); } diff --git a/radio/src/gui/taranis/gui.h b/radio/src/gui/taranis/gui.h index d22ca07566..159742fa9a 100644 --- a/radio/src/gui/taranis/gui.h +++ b/radio/src/gui/taranis/gui.h @@ -70,3 +70,10 @@ extern coord_t scrollbar_X; extern const pm_uchar sticks[] PROGMEM; +#if defined(FLIGHT_MODES) +void displayFlightModes(coord_t x, coord_t y, FlightModesType value); +FlightModesType editFlightModes(coord_t x, coord_t y, uint8_t event, FlightModesType value, uint8_t attr); +#else + #define displayFlightModes(...) +#endif + diff --git a/radio/src/gui/taranis/lcd.cpp b/radio/src/gui/taranis/lcd.cpp index c159e80424..9e7697f901 100644 --- a/radio/src/gui/taranis/lcd.cpp +++ b/radio/src/gui/taranis/lcd.cpp @@ -404,22 +404,21 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags, uint8_t le xn = x; } else if (smlsize) { - x -= 2; - lcdDrawPoint(x+1, y+5); + x -= 1; + lcdDrawPoint(x-1, y+5); if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) { - lcdDrawSolidVerticalLine(x+1, y, 7); + lcdDrawSolidVerticalLine(x-1, y, 7); } } else if (tinsize) { - x--; - lcdDrawPoint(x-1, y+4); + x -= 2; + lcdDrawPoint(x, y+4); if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) { - lcdDrawSolidVerticalLine(x-1, y-1, 7); + lcdDrawSolidVerticalLine(x, y-1, 7); } - x--; } else { - x -= 2; + x -= (flags & BOLD) ? 3 : 2; lcdDrawChar(x, y, '.', f); } } @@ -952,10 +951,9 @@ void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, int32_t va } else { LcdFlags flags = att; - if (telemetrySensor.prec==2) - flags |= PREC2; - else if (telemetrySensor.prec==1) - flags |= PREC1; + if (telemetrySensor.prec > 0) { + flags |= (telemetrySensor.prec==1 ? PREC1 : PREC2); + } putsValueWithUnit(x, y, value, telemetrySensor.unit == UNIT_CELLS ? UNIT_VOLTS : telemetrySensor.unit, flags); } } diff --git a/radio/src/gui/taranis/lcd.h b/radio/src/gui/taranis/lcd.h index d6ac16340b..4b84f0c4da 100644 --- a/radio/src/gui/taranis/lcd.h +++ b/radio/src/gui/taranis/lcd.h @@ -46,7 +46,7 @@ /* lcd text flags */ #define INVERS 0x02 #if defined(BOLD_FONT) - #define BOLD 0x40 + #define BOLD 0x04 #else #define BOLD 0x00 #endif @@ -71,7 +71,7 @@ #define FORCE 0x02 #define ERASE 0x04 #define ROUND 0x08 -#define FILL_WHITE 0x10 +#define FILL_WHITE 0x10 /* telemetry flags */ #define NO_UNIT 0x40 diff --git a/radio/src/gui/taranis/menu_general_hardware.cpp b/radio/src/gui/taranis/menu_general_hardware.cpp index 0a20b9dbfc..b45a1a3101 100644 --- a/radio/src/gui/taranis/menu_general_hardware.cpp +++ b/radio/src/gui/taranis/menu_general_hardware.cpp @@ -198,7 +198,7 @@ void menuGeneralHardware(uint8_t event) #if defined(REV9E) case ITEM_SETUP_HW_BLUETOOTH: lcd_putsLeft(y, "Bluetooth"); - menu_lcd_onoff(HW_SETTINGS_COLUMN, y, g_eeGeneral.bluetoothEnable, menuHorizontalPosition == 0 ? attr : 0); + drawCheckBox(HW_SETTINGS_COLUMN, y, g_eeGeneral.bluetoothEnable, menuHorizontalPosition == 0 ? attr : 0); if (attr && menuHorizontalPosition == 0) { g_eeGeneral.bluetoothEnable = checkIncDecGen(event, g_eeGeneral.bluetoothEnable, 0, 1); } diff --git a/radio/src/gui/taranis/menu_general_setup.cpp b/radio/src/gui/taranis/menu_general_setup.cpp index a24d2ebf3a..4af5ab2a62 100644 --- a/radio/src/gui/taranis/menu_general_setup.cpp +++ b/radio/src/gui/taranis/menu_general_setup.cpp @@ -310,14 +310,14 @@ void menuGeneralSetup(uint8_t event) case ITEM_SETUP_MEMORY_WARNING: { uint8_t b = 1-g_eeGeneral.disableMemoryWarning; - g_eeGeneral.disableMemoryWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event); + g_eeGeneral.disableMemoryWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event); break; } case ITEM_SETUP_ALARM_WARNING: { uint8_t b = 1-g_eeGeneral.disableAlarmWarning; - g_eeGeneral.disableAlarmWarning = 1 - onoffMenuItem(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event); + g_eeGeneral.disableAlarmWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event); break; } @@ -337,7 +337,7 @@ void menuGeneralSetup(uint8_t event) break; case ITEM_SETUP_FLASH_BEEP: - g_eeGeneral.alarmsFlash = onoffMenuItem(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ; + g_eeGeneral.alarmsFlash = editCheckBox(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ; break; case ITEM_SETUP_BACKLIGHT_DELAY: @@ -393,7 +393,7 @@ void menuGeneralSetup(uint8_t event) break; case ITEM_SETUP_ADJUST_RTC: - g_eeGeneral.adjustRTC = onoffMenuItem(g_eeGeneral.adjustRTC, RADIO_SETUP_2ND_COLUMN, y, STR_ADJUST_RTC, attr, event); + g_eeGeneral.adjustRTC = editCheckBox(g_eeGeneral.adjustRTC, RADIO_SETUP_2ND_COLUMN, y, STR_ADJUST_RTC, attr, event); break; case ITEM_SETUP_GPSFORMAT: @@ -425,7 +425,7 @@ void menuGeneralSetup(uint8_t event) #if defined(FAI_CHOICE) case ITEM_SETUP_FAI: - onoffMenuItem(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event); + editCheckBox(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event); if (attr && checkIncDec_Ret) { if (g_eeGeneral.fai) POPUP_WARNING(PSTR("FAI\001mode blocked!")); diff --git a/radio/src/gui/taranis/menu_model.cpp b/radio/src/gui/taranis/menu_model.cpp index 9864538c11..0eca0511ef 100644 --- a/radio/src/gui/taranis/menu_model.cpp +++ b/radio/src/gui/taranis/menu_model.cpp @@ -43,6 +43,9 @@ uint8_t editDelay(const coord_t y, const uint8_t event, const uint8_t attr, cons uint8_t s_copyMode = 0; int8_t s_copySrcRow; int8_t s_copyTgtOfs; +uint8_t s_maxLines = 8; +uint8_t s_copySrcIdx; +uint8_t s_copySrcCh; uint8_t editNameCursorPos = 0; diff --git a/radio/src/gui/taranis/menu_model_curves.cpp b/radio/src/gui/taranis/menu_model_curves.cpp index ea3145c191..6790b21ff1 100644 --- a/radio/src/gui/taranis/menu_model_curves.cpp +++ b/radio/src/gui/taranis/menu_model_curves.cpp @@ -125,17 +125,17 @@ void onCurveOneMenu(const char *result) void menuModelCurveOne(uint8_t event) { static uint8_t pointsOfs = 0; - CurveInfo & crv = g_model.curves[s_curveChan]; + CurveData & crv = g_model.curves[s_curveChan]; int8_t * points = curveAddress(s_curveChan); - lcdDrawText(9*FW, 0, TR_PT "\003X\006Y"); + lcdDrawText(11*FW+FW/2, 0, TR_PT "\002X\006Y"); + putsStrIdx(PSIZE(TR_MENUCURVES)*FW+FW, 0, "CV", s_curveChan+1); lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); - SIMPLE_SUBMENU(STR_MENUCURVE, 4 + 5+crv.points + (crv.type==CURVE_TYPE_CUSTOM ? 5+crv.points-2 : 0)); - lcdDrawNumber(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT); + SIMPLE_SUBMENU(STR_MENUCURVES, 4 + 5+crv.points + (crv.type==CURVE_TYPE_CUSTOM ? 5+crv.points-2 : 0)); lcd_putsLeft(FH+1, STR_NAME); - editName(INDENT_WIDTH, 2*FH+1, g_model.curveNames[s_curveChan], sizeof(g_model.curveNames[s_curveChan]), event, menuVerticalPosition==0); + editName(INDENT_WIDTH, 2*FH+1, crv.name, sizeof(crv.name), event, menuVerticalPosition==0); uint8_t attr = (menuVerticalPosition==1 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); lcd_putsLeft(3*FH+1, STR_TYPE); @@ -177,7 +177,7 @@ void menuModelCurveOne(uint8_t event) } lcd_putsLeft(7*FH+1, STR_SMOOTH); - menu_lcd_onoff(7*FW, 7*FH+1, crv.smooth, menuVerticalPosition==3 ? INVERS : 0); + drawCheckBox(7 * FW, 7 * FH + 1, crv.smooth, menuVerticalPosition == 3 ? INVERS : 0); if (menuVerticalPosition==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1); switch(event) { @@ -219,9 +219,9 @@ void menuModelCurveOne(uint8_t event) if (i>=pointsOfs && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; - lcdDrawNumber(6+8*FW, posY, i+1, LEFT); - lcdDrawNumber(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); - lcdDrawNumber(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); + lcdDrawNumber(6+10*FW+FW/2, posY, i+1, LEFT); + lcdDrawNumber(3+14*FW, posY, x, LEFT|(selectionMode==1?attr:0)); + lcdDrawNumber(3+18*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); posY += FH; } @@ -253,10 +253,10 @@ void editCurveRef(coord_t x, coord_t y, CurveRef & curve, uint8_t event, uint8_t switch (curve.type) { case CURVE_REF_DIFF: case CURVE_REF_EXPO: - curve.value = GVAR_MENU_ITEM(x+5*FW, y, curve.value, -100, 100, menuHorizontalPosition==1 ? LEFT|attr : LEFT, 0, event); + curve.value = GVAR_MENU_ITEM(x+5*FW+2, y, curve.value, -100, 100, menuHorizontalPosition==1 ? LEFT|attr : LEFT, 0, event); break; case CURVE_REF_FUNC: - lcdDrawTextAtIndex(x+5*FW, y, STR_VCURVEFUNC, curve.value, menuHorizontalPosition==1 ? attr : 0); + lcdDrawTextAtIndex(x+5*FW+2, y, STR_VCURVEFUNC, curve.value, menuHorizontalPosition==1 ? attr : 0); if (attr && menuHorizontalPosition==1) CHECK_INCDEC_MODELVAR_ZERO(event, curve.value, CURVE_BASE-1); break; case CURVE_REF_CUSTOM: @@ -295,8 +295,8 @@ void menuModelCurvesAll(uint8_t event) LcdFlags attr = (sub == k ? INVERS : 0); { putsStrIdx(0, y, STR_CV, k+1, attr); - editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); - CurveInfo & crv = g_model.curves[k]; + CurveData & crv = g_model.curves[k]; + editName(4*FW, y, crv.name, sizeof(crv.name), 0, 0); lcdDrawNumber(11*FW, y, 5+crv.points, LEFT); lcdDrawText(lcdLastPos, y, STR_PTS, 0); } diff --git a/radio/src/gui/taranis/menu_model_custom_functions.cpp b/radio/src/gui/taranis/menu_model_custom_functions.cpp index 417a6a1dd4..5ce51db8eb 100644 --- a/radio/src/gui/taranis/menu_model_custom_functions.cpp +++ b/radio/src/gui/taranis/menu_model_custom_functions.cpp @@ -26,7 +26,7 @@ #define MODEL_CUSTOM_FUNC_4TH_COLUMN (33*FW-3) #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (34*FW-3) -void onCustomFunctionsFileSelectionMenu(const char *result) +void onCustomFunctionsFileSelectionMenu(const char * result) { int sub = menuVerticalPosition; CustomFunctionData * cfn; @@ -66,7 +66,7 @@ void onCustomFunctionsFileSelectionMenu(const char *result) } } -void onCustomFunctionsMenu(const char *result) +void onCustomFunctionsMenu(const char * result) { int sub = menuVerticalPosition; CustomFunctionData * cfn; @@ -125,7 +125,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result) storageDirty(EE_MODEL); } else if (result == STR_INCDEC) { - CFN_GVAR_MODE(cfn) = FUNC_ADJUST_GVAR_INC; + CFN_GVAR_MODE(cfn) = FUNC_ADJUST_GVAR_INCDEC; CFN_PARAM(cfn) = 0; storageDirty(EE_MODEL); } @@ -134,6 +134,16 @@ void onAdjustGvarSourceLongEnterPress(const char * result) } } +enum CustomFunctionsItems { + ITEM_CUSTOM_FUNCTIONS_SWITCH, + ITEM_CUSTOM_FUNCTIONS_FUNCTION, + ITEM_CUSTOM_FUNCTIONS_PARAM1, + ITEM_CUSTOM_FUNCTIONS_PARAM2, + ITEM_CUSTOM_FUNCTIONS_REPEAT, + ITEM_CUSTOM_FUNCTIONS_COUNT, + ITEM_CUSTOM_FUNCTIONS_LAST = ITEM_CUSTOM_FUNCTIONS_COUNT-1 +}; + void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFunctionsContext * functionsContext) { int sub = menuVerticalPosition; @@ -170,7 +180,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); uint8_t active = (attr && s_editMode>0); switch (j) { - case 0: + case ITEM_CUSTOM_FUNCTIONS_SWITCH: putsSwitches(MODEL_CUSTOM_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0)); if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_SWITCH(event, CFN_SWITCH(cfn), SWSRC_FIRST, SWSRC_LAST, eeFlags, isSwitchAvailableInCustomFunctions); if (func == FUNC_OVERRIDE_CHANNEL && functions != g_model.customFn) { @@ -178,7 +188,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu } break; - case 1: + case ITEM_CUSTOM_FUNCTIONS_FUNCTION: if (CFN_SWITCH(cfn)) { lcdDrawTextAtIndex(MODEL_CUSTOM_FUNC_2ND_COLUMN, y, STR_VFSWFUNC, func, attr); if (active) { @@ -187,14 +197,14 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu } } else { - j = 4; // skip other fields + j = ITEM_CUSTOM_FUNCTIONS_LAST; // skip other fields if (sub==k && menuHorizontalPosition > 0) { REPEAT_LAST_CURSOR_MOVE(); } } break; - case 2: + case ITEM_CUSTOM_FUNCTIONS_PARAM1: { int8_t maxParam = NUM_CHNOUT-1; #if defined(OVERRIDE_CHANNEL_FUNCTION) @@ -204,7 +214,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu else #endif if (func == FUNC_TRAINER) { - maxParam = 4; + maxParam = NUM_STICKS; putsMixerSource(lcdNextPos, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr); } #if defined(GVARS) @@ -228,7 +238,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu break; } - case 3: + case ITEM_CUSTOM_FUNCTIONS_PARAM2: { INCDEC_DECLARE_VARS(eeFlags); int16_t val_displayed = CFN_PARAM(cfn); @@ -335,7 +345,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu switch (CFN_GVAR_MODE(cfn)) { case FUNC_ADJUST_GVAR_CONSTANT: val_displayed = (int16_t)CFN_PARAM(cfn); - val_min = -CFN_GVAR_CST_MAX; val_max = +CFN_GVAR_CST_MAX; + val_min = CFN_GVAR_CST_MIN; val_max = CFN_GVAR_CST_MAX; lcdDrawNumber(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); break; case FUNC_ADJUST_GVAR_SOURCE: @@ -351,17 +361,12 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed+1, attr); break; default: // FUNC_ADJUST_GVAR_INC -#if 0 // TODO 2.2.X val_min = -100; val_max = +100; if (val_displayed < 0) - lcdDrawText(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, "-=", attr); + lcdDrawText(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, "-= ", attr); else - lcdDrawText(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, "+=", attr); - lcdDrawNumber(lcdNextPos, y, abs(val_displayed), attr|LEFT); -#endif - val_max = 1; - lcdDrawTextAtIndex(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, PSTR("\003-=1+=1"), val_displayed, attr); - break; + lcdDrawText(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, "+= ", attr); + drawGVarValue(lcdNextPos, y, CFN_GVAR_INDEX(cfn), abs(val_displayed), attr|LEFT); } } #endif @@ -379,7 +384,7 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu POPUP_MENU_ADD_ITEM(STR_MIXSOURCE); if (CFN_GVAR_MODE(cfn) != FUNC_ADJUST_GVAR_GVAR) POPUP_MENU_ADD_ITEM(STR_GLOBALVAR); - if (CFN_GVAR_MODE(cfn) != FUNC_ADJUST_GVAR_INC) + if (CFN_GVAR_MODE(cfn) != FUNC_ADJUST_GVAR_INCDEC) POPUP_MENU_ADD_ITEM(STR_INCDEC); popupMenuHandler = onAdjustGvarSourceLongEnterPress; s_editMode = EDIT_MODIFY_FIELD; @@ -388,9 +393,9 @@ void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFu break; } - case 4: + case ITEM_CUSTOM_FUNCTIONS_REPEAT: if (HAS_ENABLE_PARAM(func)) { - menu_lcd_onoff(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); + drawCheckBox(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr); if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags); } else if (HAS_REPEAT_PARAM(func)) { diff --git a/radio/src/gui/taranis/menu_model_custom_scripts.cpp b/radio/src/gui/taranis/menu_model_custom_scripts.cpp index 9ddca2460b..1bc30eb302 100644 --- a/radio/src/gui/taranis/menu_model_custom_scripts.cpp +++ b/radio/src/gui/taranis/menu_model_custom_scripts.cpp @@ -49,13 +49,12 @@ enum menuModelCustomScriptItems { void menuModelCustomScriptOne(uint8_t event) { - TITLE(STR_MENUCUSTOMSCRIPT); + ScriptData & sd = g_model.scriptsData[s_currIdx]; - ScriptData &sd = g_model.scriptsData[s_currIdx]; + putsStrIdx(PSIZE(TR_MENUCUSTOMSCRIPTS)*FW+FW, 0, "LUA", s_currIdx+1, 0); + lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); - putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); - - SUBMENU_NOTITLE(3+scriptInputsOutputs[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); + SUBMENU(STR_MENUCUSTOMSCRIPTS, 3+scriptInputsOutputs[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); int8_t sub = menuVerticalPosition; diff --git a/radio/src/gui/taranis/menu_model_flightmodes.cpp b/radio/src/gui/taranis/menu_model_flightmodes.cpp index e8840648f2..13c9f33ea7 100644 --- a/radio/src/gui/taranis/menu_model_flightmodes.cpp +++ b/radio/src/gui/taranis/menu_model_flightmodes.cpp @@ -30,6 +30,36 @@ void displayFlightModes(coord_t x, coord_t y, FlightModesType value) } } +FlightModesType editFlightModes(coord_t x, coord_t y, uint8_t event, FlightModesType value, uint8_t attr) +{ + lcd_putsColumnLeft(x, y, STR_FLMODE); + + int posHorz = menuHorizontalPosition; + + for (int p=0; pgvars[gvar]; + int16_t vmin, vmax; + if (v > GVAR_MAX) { + uint8_t fm = v - GVAR_MAX - 1; + if (fm >= flightMode) fm++; + putsFlightMode(x, y, fm + 1, flags&(~LEFT)); + vmin = GVAR_MAX + 1; + vmax = GVAR_MAX + MAX_FLIGHT_MODES - 1; + } + else { + drawGVarValue(x, y, gvar, v, flags); + vmin = GVAR_MIN + g_model.gvars[gvar].min; + vmax = GVAR_MAX - g_model.gvars[gvar].max; + } + + if (flags & INVERS) { + if (event == EVT_KEY_LONG(KEY_ENTER)) { + v = (v > GVAR_MAX ? 0 : GVAR_MAX+1); + storageDirty(EE_MODEL); + } + else if (s_editMode > 0) { + v = checkIncDec(event, v, vmin, vmax, EE_MODEL); + } + } +} + +enum GVarFields { + GVAR_FIELD_NAME, + GVAR_FIELD_UNIT, + GVAR_FIELD_PREC, + GVAR_FIELD_MIN, + GVAR_FIELD_MAX, + GVAR_FIELD_POPUP, + GVAR_FIELD_FM0, + GVAR_FIELD_LAST=GVAR_FIELD_FM0+MAX_FLIGHT_MODES +}; + +#define GVAR_2ND_COLUMN (12*FW) + +void menuModelGVarOne(uint8_t event) +{ + GVarData * gvar = &g_model.gvars[s_currIdx]; + + putsStrIdx(PSIZE(TR_GVARS)*FW+FW, 0, STR_GV, s_currIdx+1, 0); + drawGVarValue(32*FW, 0, s_currIdx, getGVarValue(s_currIdx, getFlightMode())); + lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); + + SIMPLE_SUBMENU(STR_GVARS, GVAR_FIELD_LAST); + + for (int i=0; i 0 ? BLINK | INVERS : INVERS) : 0); + + switch (k) { + case GVAR_FIELD_NAME: + editSingleName(GVAR_2ND_COLUMN, y, STR_NAME, gvar->name, LEN_GVAR_NAME, event, attr); + break; + + case GVAR_FIELD_UNIT: + gvar->unit = selectMenuItem(GVAR_2ND_COLUMN, y, STR_UNIT, "\001-%", gvar->unit, 0, 1, attr, event); + break; + + case GVAR_FIELD_PREC: + gvar->prec = selectMenuItem(GVAR_2ND_COLUMN, y, STR_PRECISION, STR_VPREC, gvar->prec, 0, 1, attr, event); + break; + + case GVAR_FIELD_MIN: + lcdDrawText(0, y, STR_MIN); + drawGVarValue(GVAR_2ND_COLUMN, y, s_currIdx, GVAR_MIN+gvar->min, LEFT|attr); + if (attr) gvar->min = checkIncDec(event, GVAR_MIN+gvar->min, GVAR_MIN, GVAR_MAX-gvar->max, EE_MODEL) - GVAR_MIN; + break; + + case GVAR_FIELD_MAX: + lcdDrawText(0, y, STR_MAX); + drawGVarValue(GVAR_2ND_COLUMN, y, s_currIdx, GVAR_MAX-gvar->max, LEFT|attr); + if (attr) gvar->max = GVAR_MAX - checkIncDec(event, GVAR_MAX-gvar->max, GVAR_MIN+gvar->min, GVAR_MAX, EE_MODEL); + break; + + case GVAR_FIELD_POPUP: + ON_OFF_MENU_ITEM(gvar->popup, GVAR_2ND_COLUMN, y, STR_POPUP, attr, event); + break; + + default: + putsStrIdx(0, y, STR_FP, k-GVAR_FIELD_FM0); + editGVarValue(GVAR_2ND_COLUMN, y, event, s_currIdx, k-GVAR_FIELD_FM0, LEFT|attr); + break; + } + } +} + void onGVARSMenu(const char *result) { int sub = menuVerticalPosition; - if (result == STR_ENABLE_POPUP) { - g_model.gvars[sub].popup = true; - storageDirty(EE_MODEL); - } - else if (result == STR_DISABLE_POPUP) { - g_model.gvars[sub].popup = false; - storageDirty(EE_MODEL); + if (result == STR_EDIT) { + s_currIdx = sub; + pushMenu(menuModelGVarOne); } else if (result == STR_CLEAR) { for (int i=0; i 200); /*2 seconds*/ + bool after2seconds = (tmr10ms - menuEntryTime > 200); /*2 seconds*/ - if (first2seconds) { - menuTitle = STR_GLOBAL_V; + if (after2seconds) { + menuTitle = STR_GVARS; for (int i=0; i0) ? BLINK|INVERS : INVERS) : 0); - coord_t x = GVARS_FM_COLUMN(j-1); + for (int j=0; jgvars[i]; - 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) - lcdDrawNumber(x, y+1, v, attr | TINSIZE); - else - lcdDrawNumber(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); - storageDirty(EE_MODEL); - } - else if (s_editMode>0) { - v = checkIncDec(event, v, vmin, vmax, EE_MODEL); - } - } - break; - } + LcdFlags attr = ((sub == i && menuHorizontalPosition == j) ? (s_editMode > 0 ? BLINK | INVERS : INVERS) : 0); + coord_t x = GVARS_FM_COLUMN(j); + if (v > GVAR_MAX) { + x -= 16; + attr |= SMLSIZE; } + else if (g_model.gvars[i].prec > 0 || abs(v) >= 100) { + attr |= TINSIZE | NO_UNIT; + } + else { + attr |= SMLSIZE | NO_UNIT; + } + editGVarValue(x, y, event, i, j, attr); } } - if (menuHorizontalPosition < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { + if (menuHorizontalPosition<0 && event==EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); - if (g_model.gvars[sub].popup) - POPUP_MENU_ADD_ITEM(STR_DISABLE_POPUP); - else - POPUP_MENU_ADD_ITEM(STR_ENABLE_POPUP); + POPUP_MENU_ADD_ITEM(STR_EDIT); POPUP_MENU_ADD_ITEM(STR_CLEAR); popupMenuHandler = onGVARSMenu; } diff --git a/radio/src/gui/taranis/menu_model_heli.cpp b/radio/src/gui/taranis/menu_model_heli.cpp index c2b72ea255..2a33e0aff4 100644 --- a/radio/src/gui/taranis/menu_model_heli.cpp +++ b/radio/src/gui/taranis/menu_model_heli.cpp @@ -32,7 +32,7 @@ enum menuModelHeliItems { ITEM_HELI_MAX }; -#define MODEL_HELI_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH) +#define MODEL_HELI_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH) void menuModelHeli(uint8_t event) { @@ -42,7 +42,7 @@ void menuModelHeli(uint8_t event) for (unsigned int i=0; i0) ? BLINK|INVERS : INVERS); LcdFlags attr = (sub == k ? blink : 0); @@ -92,7 +92,6 @@ void menuModelHeli(uint8_t event) lcdDrawNumber(MODEL_HELI_2ND_COLUMN, y, g_model.swashR.collectiveWeight, LEFT|attr); if (attr) CHECK_INCDEC_MODELVAR(event, g_model.swashR.collectiveWeight, -100, 100); break; - } } } diff --git a/radio/src/gui/taranis/menu_model_inputs.cpp b/radio/src/gui/taranis/menu_model_inputs.cpp new file mode 100644 index 0000000000..b9999a8bb1 --- /dev/null +++ b/radio/src/gui/taranis/menu_model_inputs.cpp @@ -0,0 +1,574 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "../../opentx.h" + +#define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90) +#define EXPO_ONE_FM_WIDTH (9*FW) + +int16_t expoFn(int16_t x) +{ + ExpoData * ed = expoAddress(s_currIdx); + int16_t anas[NUM_INPUTS] = {0}; + applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x); + return anas[ed->chn]; +} + +void drawFunction(FnFuncP fn, uint8_t offset) +{ + lcdDrawVerticalLine(X0-offset, 0/*TODO Y0-WCHART*/, WCHART*2, 0xee); + lcdDrawHorizontalLine(X0-WCHART-offset, Y0, WCHART*2, 0xee); + + coord_t prev_yv = (coord_t)-1; + + for (int xv=-WCHART; xv<=WCHART; xv++) { + coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/WCHART))) / 2 * (LCD_H-1) / RESX); + if (prev_yv != (coord_t)-1) { + if (abs((int8_t)yv-prev_yv) <= 1) { + lcdDrawPoint(X0+xv-offset-1, prev_yv, FORCE); + } + else { + uint8_t tmp = (prev_yv < yv ? 0 : 1); + lcdDrawSolidVerticalLine(X0+xv-offset-1, yv+tmp, prev_yv-yv); + } + } + prev_yv = yv; + } +} + +uint8_t getExposCount() +{ + uint8_t count = 0; + uint8_t ch ; + + for (int i=MAX_EXPOS-1 ; i>=0; i--) { + ch = EXPO_VALID(expoAddress(i)); + if (ch != 0) { + count++; + } + } + return count; +} + +bool reachExposLimit() +{ + if (getExposCount() >= MAX_EXPOS) { + POPUP_WARNING(STR_NOFREEEXPO); + return true; + } + return false; +} + +void deleteExpo(uint8_t idx) +{ + pauseMixerCalculations(); + ExpoData * expo = expoAddress(idx); + int input = expo->chn; + memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); + if (!isInputAvailable(input)) { + memclear(&g_model.inputNames[input], LEN_INPUT_NAME); + } + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +// TODO avoid this global s_currCh on ARM boards ... +int8_t s_currCh; +void insertExpo(uint8_t idx) +{ + pauseMixerCalculations(); + ExpoData * expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + memclear(expo, sizeof(ExpoData)); + expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); + expo->curve.type = CURVE_REF_EXPO; + expo->mode = 3; // pos+neg + expo->chn = s_currCh - 1; + expo->weight = 100; + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +void copyExpo(uint8_t idx) +{ + pauseMixerCalculations(); + ExpoData * expo = expoAddress(idx); + memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +bool swapExpos(uint8_t & idx, uint8_t up) +{ + ExpoData * x, * y; + int8_t tgt_idx = (up ? idx-1 : idx+1); + + x = expoAddress(idx); + + if (tgt_idx < 0) { + if (x->chn == 0) + return false; + x->chn--; + return true; + } + + if (tgt_idx == MAX_EXPOS) { + if (x->chn == NUM_INPUTS-1) + return false; + x->chn++; + return true; + } + + y = expoAddress(tgt_idx); + if (x->chn != y->chn || !EXPO_VALID(y)) { + if (up) { + if (x->chn>0) x->chn--; + else return false; + } + else { + if (x->chnchn++; + else return false; + } + return true; + } + + pauseMixerCalculations(); + memswap(x, y, sizeof(ExpoData)); + resumeMixerCalculations(); + + idx = tgt_idx; + return true; +} + +enum ExposFields { + EXPO_FIELD_INPUT_NAME, + EXPO_FIELD_NAME, + EXPO_FIELD_SOURCE, + EXPO_FIELD_SCALE, + EXPO_FIELD_WEIGHT, + EXPO_FIELD_OFFSET, + CASE_CURVES(EXPO_FIELD_CURVE) + CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES) + EXPO_FIELD_SWITCH, + EXPO_FIELD_SIDE, + EXPO_FIELD_TRIM, + EXPO_FIELD_MAX +}; + +#define CURVE_ROWS 1 + +void menuModelExpoOne(uint8_t event) +{ + if (event == EVT_KEY_LONG(KEY_MENU)) { + pushMenu(menuChannelsView); + killEvents(event); + } + + ExpoData * ed = expoAddress(s_currIdx); + putsMixerSource(PSIZE(TR_MENUINPUTS)*FW+FW, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); + lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); + + SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); + + SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); + + int8_t sub = menuVerticalPosition; + + coord_t y = MENU_HEADER_HEIGHT + 1; + + for (unsigned int k=0; k0 ? BLINK|INVERS : INVERS) : 0); + + switch(i) { + case EXPO_FIELD_INPUT_NAME: + editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); + break; + + case EXPO_FIELD_NAME: + editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); + break; + + 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); + putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, 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); + break; + + 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, LEFT|attr, 0, event); + break; + + 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; + +#if defined(CURVES) + case EXPO_FIELD_CURVE: + lcd_putsLeft(y, STR_CURVE); + editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); + break; +#endif + +#if defined(FLIGHT_MODES) + case EXPO_FIELD_FLIGHT_MODES: + ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr); + break; +#endif + + case EXPO_FIELD_SWITCH: + ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); + break; + + case EXPO_FIELD_SIDE: + ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); + break; + + case EXPO_FIELD_TRIM: + uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); + int8_t carryTrim = -ed->carryTrim; + lcd_putsLeft(y, STR_TRIM); + lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0); + if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); + break; + } + y += FH; + } + + drawFunction(expoFn); + + int x512 = getValue(ed->srcRaw); + if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { + putsTelemetryChannelValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); + if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); + } + else { + lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); + } + x512 = limit(-1024, x512, 1024); + int y512 = expoFn(x512); + y512 = limit(-1024, y512, 1024); + lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); + + x512 = X0+x512/(RESX/WCHART); + y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; + + lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1); + lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1); +} + +#define _STR_MAX(x) PSTR("/" #x) +#define STR_MAX(x) _STR_MAX(x) + +#define EXPO_LINE_WEIGHT_POS 8*FW+8 +#define EXPO_LINE_SRC_POS 9*FW+3 +#define EXPO_LINE_CURVE_POS 12*FW+11 +#define EXPO_LINE_TRIM_POS 19*FW-4 +#define EXPO_LINE_SWITCH_POS 20*FW-1 +#define EXPO_LINE_SIDE_POS 25*FW +#define EXPO_LINE_FM_POS 12*FW+11 +#define EXPO_LINE_SELECT_POS 5*FW+2 +#define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH + +void onExposMenu(const char * result) +{ + uint8_t chn = expoAddress(s_currIdx)->chn + 1; + + if (result == STR_EDIT) { + pushMenu(menuModelExpoOne); + } + else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { + if (!reachExposLimit()) { + s_currCh = chn; + if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; } + insertExpo(s_currIdx); + pushMenu(menuModelExpoOne); + } + } + 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 = menuVerticalPosition; + } + else if (result == STR_DELETE) { + deleteExpo(s_currIdx); + } +} + +void displayExpoInfos(coord_t y, ExpoData *ed) +{ + putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0); + putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); +} + +void displayExpoLine(coord_t y, ExpoData *ed) +{ + putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0); + + if (ed->carryTrim != TRIM_ON) { + lcdDrawChar(EXPO_LINE_TRIM_POS, y, ed->carryTrim > 0 ? '-' : STR_RETA123[-ed->carryTrim]); + } + + if (!ed->flightModes || ((ed->curve.value || ed->swtch) && ((get_tmr10ms() / 200) & 1))) + displayExpoInfos(y, ed); + else + displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes); + + if (ed->name[0]) { + lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR); + } +} + +void menuModelExposAll(uint8_t event) +{ + uint8_t sub = menuVerticalPosition; + + if (s_editMode > 0) { + s_editMode = 0; + } + + uint8_t chn = expoAddress(s_currIdx)->chn + 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) { + deleteExpo(s_currIdx); + killEvents(event); + event = 0; + } + // no break + case EVT_KEY_BREAK(KEY_EXIT): + if (s_copyMode) { + if (s_copyTgtOfs) { + // cancel the current copy / move operation + if (s_copyMode == COPY_MODE) { + deleteExpo(s_currIdx); + } + else { + do { + swapExpos(s_currIdx, s_copyTgtOfs > 0); + s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); + } while (s_copyTgtOfs != 0); + storageDirty(EE_MODEL); + } + menuVerticalPosition = s_copySrcRow; + s_copyTgtOfs = 0; + } + s_copyMode = 0; + event = 0; + } + break; + case EVT_KEY_BREAK(KEY_ENTER): + if ((!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_KEY_LONG(KEY_ENTER): + killEvents(event); + if (s_copyTgtOfs) { + s_copyMode = 0; + s_copyTgtOfs = 0; + } + else { + if (READ_ONLY()) { + if (!s_currCh) { + pushMenu(menuModelExpoOne); + } + } + else { + if (s_copyMode) s_currCh = 0; + if (s_currCh) { + if (reachExposLimit()) break; + insertExpo(s_currIdx); + pushMenu(menuModelExpoOne); + s_copyMode = 0; + } + else { + event = 0; + s_copyMode = 0; + POPUP_MENU_ADD_ITEM(STR_EDIT); + POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); + POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); + POPUP_MENU_ADD_ITEM(STR_COPY); + POPUP_MENU_ADD_ITEM(STR_MOVE); + POPUP_MENU_ADD_ITEM(STR_DELETE); + popupMenuHandler = onExposMenu; + } + } + } + break; + case EVT_KEY_LONG(KEY_LEFT): + case EVT_KEY_LONG(KEY_RIGHT): + if (s_copyMode && !s_copyTgtOfs) { + if (reachExposLimit()) break; + s_currCh = chn; + if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; } + insertExpo(s_currIdx); + pushMenu(menuModelExpoOne); + s_copyMode = 0; + killEvents(event); + } + break; + case EVT_KEY_FIRST(KEY_UP): + case EVT_KEY_REPT(KEY_UP): + case EVT_KEY_FIRST(KEY_DOWN): + case EVT_KEY_REPT(KEY_DOWN): + if (s_copyMode) { + uint8_t key = (event & 0x1f); + uint8_t next_ofs = (key==KEY_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 (reachExposLimit()) break; + copyExpo(s_currIdx); + if (key==KEY_DOWN) s_currIdx++; + else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; + } + else if (next_ofs==0 && s_copyMode==COPY_MODE) { + // delete the mix + deleteExpo(s_currIdx); + if (key==KEY_UP) s_currIdx--; + } + else { + // only swap the mix with its neighbor + if (!swapExpos(s_currIdx, key==KEY_UP)) break; + storageDirty(EE_MODEL); + } + + s_copyTgtOfs = next_ofs; + } + break; + } + + lcdDrawNumber(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, getExposCount()); + lcdDrawText(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, STR_MAX(MAX_EXPOS)); + + // Value + uint8_t index = expoAddress(s_currIdx)->chn; + if (!s_currCh) { + lcdDrawNumber(127, 2, calcRESXto1000(anas[index]), PREC1|TINSIZE); + } + + SIMPLE_MENU(STR_MENUINPUTS, menuTabModel, e_InputsAll, s_maxLines); + + // Gauge + if (!s_currCh) { + drawGauge(127, 1, 58, 6, anas[index], 1024); + } + + sub = menuVerticalPosition; + s_currCh = 0; + int cur = 0; + int i = 0; + + for (int ch=1; ch<=NUM_INPUTS; ch++) { + ExpoData * ed; + coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH; + if (ichn+1 == ch && EXPO_VALID(ed)) { + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsMixerSource(0, y, ch, 0); + } + uint8_t mixCnt = 0; + do { + if (s_copyMode) { + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lcdDrawRect(18, y-1, LCD_W-18, 9, DOTTED); + cur++; y+=FH; + } + if (s_currIdx == i) { + sub = menuVerticalPosition = cur; + s_currCh = ch; + } + } + else if (sub == cur) { + s_currIdx = i; + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); + + GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0); + displayExpoLine(y, ed); + if (ed->mode!=3) { + lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); + } + + 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) */ + lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); + } + if (cur == sub) { + /* invert the raw when it's the current one */ + lcdDrawFilledRect(EXPO_LINE_SELECT_POS+1, y, LCD_W-EXPO_LINE_SELECT_POS-2, 7); + } + } + } + cur++; y+=FH; mixCnt++; i++; ed++; + } while (ichn+1 == ch && EXPO_VALID(ed)); + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, DOTTED); + cur++; + } + } + else { + uint8_t attr = 0; + if (sub == cur) { + s_currIdx = i; + s_currCh = ch; + if (!s_copyMode) { + attr = INVERS; + } + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsMixerSource(0, y, ch, attr); + if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { + lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, DOTTED); + } + } + cur++; + } + } + s_maxLines = cur; + if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1; +} diff --git a/radio/src/gui/taranis/menu_model_inputs_mixes.cpp b/radio/src/gui/taranis/menu_model_inputs_mixes.cpp deleted file mode 100644 index 935cd8e776..0000000000 --- a/radio/src/gui/taranis/menu_model_inputs_mixes.cpp +++ /dev/null @@ -1,964 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "../../opentx.h" - -#define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90) -#define EXPO_ONE_FM_WIDTH (9*FW) - -#if defined(FLIGHT_MODES) -void displayFlightModes(coord_t x, coord_t y, FlightModesType value); -FlightModesType editFlightModes(coord_t x, coord_t y, uint8_t event, FlightModesType value, uint8_t attr) -{ - lcd_putsColumnLeft(x, y, STR_FLMODE); - - int posHorz = menuHorizontalPosition; - - for (int p=0; psrcRaw, x); - return anas[ed->chn]; -} - -void drawFunction(FnFuncP fn, uint8_t offset) -{ - lcdDrawVerticalLine(X0-offset, 0/*TODO Y0-WCHART*/, WCHART*2, 0xee); - lcdDrawHorizontalLine(X0-WCHART-offset, Y0, WCHART*2, 0xee); - - coord_t prev_yv = (coord_t)-1; - - for (int xv=-WCHART; xv<=WCHART; xv++) { - coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/WCHART))) / 2 * (LCD_H-1) / RESX); - if (prev_yv != (coord_t)-1) { - if (abs((int8_t)yv-prev_yv) <= 1) { - lcdDrawPoint(X0+xv-offset-1, prev_yv, FORCE); - } - else { - uint8_t tmp = (prev_yv < yv ? 0 : 1); - lcdDrawSolidVerticalLine(X0+xv-offset-1, yv+tmp, prev_yv-yv); - } - } - prev_yv = yv; - } -} - -uint8_t getExpoMixCount(uint8_t expo) -{ - uint8_t count = 0; - uint8_t ch ; - - for (int i=(expo ? MAX_EXPOS-1 : MAX_MIXERS-1); 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); - int input = expo->chn; - memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); - if (!isInputAvailable(input)) { - memclear(&g_model.inputNames[input], LEN_INPUT_NAME); - } - } - 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(); - storageDirty(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)); - expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); - expo->curve.type = CURVE_REF_EXPO; - expo->mode = 3; // pos&neg - 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; - 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)); - while (!isSourceAvailable(mix->srcRaw)) { - mix->srcRaw += 1; - } - } - mix->weight = 100; - } - resumeMixerCalculations(); - storageDirty(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(); - storageDirty(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_INPUTS-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 { - EXPO_FIELD_INPUT_NAME, - EXPO_FIELD_NAME, - EXPO_FIELD_SOURCE, - EXPO_FIELD_SCALE, - EXPO_FIELD_WEIGHT, - EXPO_FIELD_OFFSET, - CASE_CURVES(EXPO_FIELD_CURVE) - CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES) - EXPO_FIELD_SWITCH, - EXPO_FIELD_SIDE, - EXPO_FIELD_TRIM, - EXPO_FIELD_MAX -}; - -#define CURVE_ROWS 1 - -void menuModelExpoOne(uint8_t event) -{ - if (event == EVT_KEY_LONG(KEY_MENU)) { - pushMenu(menuChannelsView); - killEvents(event); - } - - ExpoData *ed = expoAddress(s_currIdx); - putsMixerSource(7*FW+FW/2, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); - - SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); - - SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); - - int8_t sub = menuVerticalPosition; - - coord_t y = MENU_HEADER_HEIGHT + 1; - - for (unsigned int k=0; k0 ? BLINK|INVERS : INVERS) : 0); - switch(i) - { - case EXPO_FIELD_INPUT_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); - break; - - case EXPO_FIELD_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); - break; - - 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); - putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, 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); - break; - - 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, LEFT|attr, 0, event); - break; - - 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; - -#if defined(CURVES) - case EXPO_FIELD_CURVE: - lcd_putsLeft(y, STR_CURVE); - editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); - break; -#endif - -#if defined(FLIGHT_MODES) - case EXPO_FIELD_FLIGHT_MODES: - ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr); - break; -#endif - - case EXPO_FIELD_SWITCH: - ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); - break; - - case EXPO_FIELD_SIDE: - ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); - break; - - case EXPO_FIELD_TRIM: - uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); - int8_t carryTrim = -ed->carryTrim; - lcd_putsLeft(y, STR_TRIM); - lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0); - if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - break; - } - y += FH; - } - - drawFunction(expoFn); - - int x512 = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannelValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); - if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); - } - else { - lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); - } - x512 = limit(-1024, x512, 1024); - int y512 = expoFn(x512); - y512 = limit(-1024, y512, 1024); - lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); - - x512 = X0+x512/(RESX/WCHART); - y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; - - lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1); - lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1); -} - -enum MixFields { - MIX_FIELD_NAME, - MIX_FIELD_SOURCE, - MIX_FIELD_WEIGHT, - MIX_FIELD_OFFSET, - MIX_FIELD_TRIM, - CASE_CURVES(MIX_FIELD_CURVE) - CASE_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(coord_t x, coord_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, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event); - MD_UNION_TO_WEIGHT(weight, md); -} - -#define GAUGE_WIDTH 33 -#define GAUGE_HEIGHT 6 -void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) -{ - int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); - int weight = abs(GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode)); - int barMin = offset - weight; - int barMax = offset + weight; - if (y > 15) { - lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT); - lcdDrawNumber(x+GAUGE_WIDTH+1, y-6, barMax, TINSIZE); - } - if (barMin < -101) - barMin = -101; - if (barMax > 101) - barMax = 101; - lcdDrawHorizontalLine(x-2, y, GAUGE_WIDTH+2, DOTTED); - lcdDrawHorizontalLine(x-2, y+GAUGE_HEIGHT, GAUGE_WIDTH+2, DOTTED); - lcdDrawSolidVerticalLine(x-2, y+1, GAUGE_HEIGHT-1); - lcdDrawSolidVerticalLine(x+GAUGE_WIDTH-1, y+1, GAUGE_HEIGHT-1); - if (barMin <= barMax) { - int8_t right = (barMax * GAUGE_WIDTH) / 200; - int8_t left = ((barMin * GAUGE_WIDTH) / 200)-1; - lcdDrawFilledRect(x+GAUGE_WIDTH/2+left, y+2, right-left, GAUGE_HEIGHT-3); - } - lcdDrawSolidVerticalLine(x+GAUGE_WIDTH/2-1, y, GAUGE_HEIGHT+1); - if (barMin == -101) { - for (uint8_t i=0; i<3; ++i) { - lcdDrawPoint(x+i, y+4-i); - lcdDrawPoint(x+3+i, y+4-i); - } - } - if (barMax == 101) { - for (uint8_t i=0; i<3; ++i) { - lcdDrawPoint(x+GAUGE_WIDTH-8+i, y+4-i); - lcdDrawPoint(x+GAUGE_WIDTH-5+i, y+4-i); - } - } -} -#undef GAUGE_WIDTH -#undef GAUGE_HEIGHT - -void menuModelMixOne(uint8_t event) -{ - if (event == EVT_KEY_LONG(KEY_MENU)) { - pushMenu(menuChannelsView); - killEvents(event); - } - - TITLE(s_currCh ? STR_INSERTMIX : STR_EDITMIX); - MixData *md2 = mixAddress(s_currIdx) ; - putsChn(lcdLastPos+1*FW, 0, md2->destCh+1,0); - - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); - -#if MENU_COLUMNS > 1 - lcdDrawSolidVerticalLine(MENU_COLUMN2_X-4, FH+1, LCD_H-FH-1); - SET_SCROLLBAR_X(0); -#endif - - int8_t sub = menuVerticalPosition; - int8_t editMode = s_editMode; - - for (int k=0; 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; - -#if MENU_COLUMNS < 2 - i = i + menuVerticalOffset; -#endif - - LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); - switch(i) { - case MIX_FIELD_NAME: - editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr); - break; - 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_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); - drawOffsetBar(COLUMN_X+MIXES_2ND_COLUMN+22, y, md2); - break; - } - - case MIX_FIELD_TRIM: - lcd_putsColumnLeft(COLUMN_X, y, STR_TRIM); - menu_lcd_onoff(COLUMN_X+MIXES_2ND_COLUMN, y, !md2->carryTrim, attr); - if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1); - break; - -#if defined(CURVES) - case MIX_FIELD_CURVE: - { - lcd_putsColumnLeft(COLUMN_X, y, STR_CURVE); - editCurveRef(COLUMN_X+MIXES_2ND_COLUMN, y, md2->curve, event, attr); - break; - } -#endif -#if defined(FLIGHT_MODES) - case MIX_FIELD_FLIGHT_PHASE: - md2->flightModes = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->flightModes, 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) - lcdDrawNumber(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT); - else - lcdDrawText(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 EXPO_LINE_WEIGHT_POS 8*FW+8 -#define EXPO_LINE_SRC_POS 9*FW+3 -#define EXPO_LINE_CURVE_POS 12*FW+11 -#define EXPO_LINE_TRIM_POS 19*FW-4 -#define EXPO_LINE_SWITCH_POS 20*FW-1 -#define EXPO_LINE_SIDE_POS 25*FW -#define EXPO_LINE_FM_POS 12*FW+11 -#define EXPO_LINE_SELECT_POS 5*FW+2 -#define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH -#define MIX_LINE_WEIGHT_POS 6*FW+8 -#define MIX_LINE_SRC_POS 7*FW+3 -#define MIX_LINE_CURVE_POS 13*FW+3 -#define MIX_LINE_SWITCH_POS 19*FW+1 -#define MIX_LINE_FM_POS 13*FW+3 -#define MIX_LINE_DELAY_POS 24*FW+3 - -void onExpoMixMenu(const char *result) -{ - bool expo = (menuHandlers[menuLevel] == 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++; menuVerticalPosition++; } - 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 = menuVerticalPosition; - } - else if (result == STR_DELETE) { - deleteExpoMix(expo, s_currIdx); - } -} - -void displayHeaderChannelName(uint8_t ch) -{ - uint8_t len = zlen(g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name)); - if (len) { - lcdDrawSizedText(80, 1, g_model.limitData[ch].name, len, ZCHAR|SMLSIZE); - } -} - -void displayMixInfos(coord_t y, MixData *md) -{ - putsCurveRef(MIX_LINE_CURVE_POS, y, md->curve, 0); - - if (md->swtch) { - putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); - } -} - -void displayMixLine(coord_t y, MixData *md) -{ - if (md->name[0]) - lcdDrawSizedText(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR); - if (!md->flightModes || ((md->curve.value || md->swtch) && ((get_tmr10ms() / 200) & 1))) - displayMixInfos(y, md); - else - displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes); -} - -void displayExpoInfos(coord_t y, ExpoData *ed) -{ - putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0); - putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); -} - -void displayExpoLine(coord_t y, ExpoData *ed) -{ - putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0); - - if (ed->carryTrim != TRIM_ON) { - lcdDrawChar(EXPO_LINE_TRIM_POS, y, ed->carryTrim > 0 ? '-' : STR_RETA123[-ed->carryTrim]); - } - - if (!ed->flightModes || ((ed->curve.value || ed->swtch) && ((get_tmr10ms() / 200) & 1))) - displayExpoInfos(y, ed); - else - displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes); - - if (ed->name[0]) { - lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR); - } -} - -void menuModelExpoMix(uint8_t expo, uint8_t event) -{ - uint8_t sub = menuVerticalPosition; - - 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 - 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); - storageDirty(EE_MODEL); - } - menuVerticalPosition = s_copySrcRow; - s_copyTgtOfs = 0; - } - s_copyMode = 0; - event = 0; - } - break; - case EVT_KEY_BREAK(KEY_ENTER): - if ((!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_KEY_LONG(KEY_ENTER): - killEvents(event); - if (s_copyTgtOfs) { - s_copyMode = 0; - s_copyTgtOfs = 0; - } - else { - if (READ_ONLY()) { - if (!s_currCh) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - } - else { - if (s_copyMode) s_currCh = 0; - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - } - else { - event = 0; - s_copyMode = 0; - POPUP_MENU_ADD_ITEM(STR_EDIT); - POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); - POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); - POPUP_MENU_ADD_ITEM(STR_COPY); - POPUP_MENU_ADD_ITEM(STR_MOVE); - POPUP_MENU_ADD_ITEM(STR_DELETE); - popupMenuHandler = onExpoMixMenu; - } - } - } - 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++; menuVerticalPosition++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - killEvents(event); - } - break; - case EVT_KEY_FIRST(KEY_UP): - case EVT_KEY_REPT(KEY_UP): - case EVT_KEY_FIRST(KEY_DOWN): - case EVT_KEY_REPT(KEY_DOWN): - if (s_copyMode) { - uint8_t key = (event & 0x1f); - uint8_t next_ofs = (key==KEY_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 (key==KEY_DOWN) s_currIdx++; - else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; - } - else if (next_ofs==0 && s_copyMode==COPY_MODE) { - // delete the mix - deleteExpoMix(expo, s_currIdx); - if (key==KEY_UP) s_currIdx--; - } - else { - // only swap the mix with its neighbor - if (!swapExpoMix(expo, s_currIdx, key==KEY_UP)) break; - storageDirty(EE_MODEL); - } - - s_copyTgtOfs = next_ofs; - } - break; - } - - if (expo) { - lcdDrawNumber(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, getExpoMixCount(true)); - lcdDrawText(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, STR_MAX(MAX_EXPOS)); - - // Value - uint8_t index = expoAddress(s_currIdx)->chn; - if (!s_currCh) { - lcdDrawNumber(127, 2, calcRESXto1000(anas[index]), PREC1|TINSIZE); - } - - SIMPLE_MENU(STR_MENUINPUTS, menuTabModel, e_InputsAll, s_maxLines); - - // Gauge - if (!s_currCh) { - drawGauge(127, 1, 58, 6, anas[index], 1024); - } - } - else { - lcdDrawNumber(FW*sizeof(TR_MIXER)+FW+FW/2, 0, getExpoMixCount(false)); - lcdDrawText(FW*sizeof(TR_MIXER)+FW+FW/2, 0, STR_MAX(MAX_MIXERS)); - - // Value - uint8_t index = mixAddress(s_currIdx)->destCh; - if (!s_currCh) { - displayHeaderChannelName(index); - lcdDrawNumber(127, 2, calcRESXto1000(ex_chans[index]), PREC1|TINSIZE); - } - - SIMPLE_MENU(STR_MIXER, menuTabModel, e_MixAll, s_maxLines); - - // Gauge - if (!s_currCh) { - drawGauge(127, 1, 58, 6, ex_chans[index], 1024); - } - } - - sub = menuVerticalPosition; - s_currCh = 0; - int cur = 0; - int i = 0; - - for (int ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { - void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; - coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH; - if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { - if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - if (expo) { - putsMixerSource(0, y, ch, 0); - } - else { - putsChn(0, y, ch, 0); // show CHx - } - } - uint8_t mixCnt = 0; - do { - if (s_copyMode) { - if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcdDrawRect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - if (s_currIdx == i) { - sub = menuVerticalPosition = cur; - s_currCh = ch; - } - } - else if (sub == cur) { - s_currIdx = i; - } - if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - if (expo) { - GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0); - displayExpoLine(y, ed); - if (ed->mode!=3) { - lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); - } - } - else { - if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0); - - putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0); - - gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), 0); - - displayMixLine(y, md); - - char cs = ' '; - if (md->speedDown || md->speedUp) - cs = 'S'; - if (md->delayUp || md->delayDown) - cs = (cs =='S' ? '*' : 'D'); - lcdDrawChar(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) */ - lcdDrawRect(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 */ - lcdDrawFilledRect(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 && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcdDrawRect(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 (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { - if (expo) { - putsMixerSource(0, y, ch, attr); - } - else { - putsChn(0, y, ch, attr); // show CHx - } - if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { - lcdDrawRect(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) menuVerticalPosition = s_maxLines-1; -} - -void menuModelExposAll(uint8_t event) -{ - return menuModelExpoMix(1, event); -} - -void menuModelMixAll(uint8_t event) -{ - return menuModelExpoMix(0, event); -} diff --git a/radio/src/gui/taranis/menu_model_mixes.cpp b/radio/src/gui/taranis/menu_model_mixes.cpp new file mode 100644 index 0000000000..8eba8a5a89 --- /dev/null +++ b/radio/src/gui/taranis/menu_model_mixes.cpp @@ -0,0 +1,604 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "../../opentx.h" + +uint8_t getMixesCount() +{ + uint8_t count = 0; + uint8_t ch ; + + for (int i=MAX_MIXERS-1; i>=0; i--) { + ch = mixAddress(i)->srcRaw; + if (ch != 0) { + count++; + } + } + return count; +} + +bool reachMixesLimit() +{ + if (getMixesCount() >= MAX_MIXERS) { + POPUP_WARNING(STR_NOFREEMIXER); + return true; + } + return false; +} + +void deleteMix(uint8_t idx) +{ + pauseMixerCalculations(); + MixData * mix = mixAddress(idx); + memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData)); + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +void insertMix(uint8_t idx) +{ + pauseMixerCalculations(); + MixData * mix = mixAddress(idx); + memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + memclear(mix, sizeof(MixData)); + mix->destCh = s_currCh-1; + 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)); + while (!isSourceAvailable(mix->srcRaw)) { + mix->srcRaw += 1; + } + } + mix->weight = 100; + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +void copyMix(uint8_t idx) +{ + pauseMixerCalculations(); + MixData * mix = mixAddress(idx); + memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); + resumeMixerCalculations(); + storageDirty(EE_MODEL); +} + +bool swapMixes(uint8_t & idx, uint8_t up) +{ + MixData * x, * y; + int8_t tgt_idx = (up ? idx-1 : idx+1); + + x = mixAddress(idx); + + if (tgt_idx < 0) { + if (x->destCh == 0) + return false; + x->destCh--; + return true; + } + + if (tgt_idx == MAX_MIXERS) { + if (x->destCh == NUM_CHNOUT-1) + return false; + x->destCh++; + return true; + } + + y = mixAddress(tgt_idx); + uint8_t destCh = x->destCh; + if(!y->srcRaw || destCh != y->destCh) { + if (up) { + if (destCh>0) x->destCh--; + else return false; + } + else { + if (destChdestCh++; + else return false; + } + return true; + } + + pauseMixerCalculations(); + memswap(x, y, sizeof(MixData)); + resumeMixerCalculations(); + + idx = tgt_idx; + return true; +} + +enum MixFields { + MIX_FIELD_NAME, + MIX_FIELD_SOURCE, + MIX_FIELD_WEIGHT, + MIX_FIELD_OFFSET, + MIX_FIELD_TRIM, + CASE_CURVES(MIX_FIELD_CURVE) + CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_MODE) + 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(coord_t x, coord_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, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event); + MD_UNION_TO_WEIGHT(weight, md); +} + +void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) +{ + const int gaugeWidth = 33; + const int gaugeHeight = 6; + + int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + int weight = abs(GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode)); + int barMin = offset - weight; + int barMax = offset + weight; + if (y > 15) { + lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT); + lcdDrawNumber(x+gaugeWidth+1, y-6, barMax, TINSIZE); + } + if (barMin < -101) + barMin = -101; + if (barMax > 101) + barMax = 101; + lcdDrawHorizontalLine(x-2, y, gaugeWidth+2, DOTTED); + lcdDrawHorizontalLine(x-2, y+gaugeHeight, gaugeWidth+2, DOTTED); + lcdDrawSolidVerticalLine(x-2, y+1, gaugeHeight-1); + lcdDrawSolidVerticalLine(x+gaugeWidth-1, y+1, gaugeHeight-1); + if (barMin <= barMax) { + int8_t right = (barMax * gaugeWidth) / 200; + int8_t left = ((barMin * gaugeWidth) / 200)-1; + lcdDrawFilledRect(x+gaugeWidth/2+left, y+2, right-left, gaugeHeight-3); + } + lcdDrawSolidVerticalLine(x+gaugeWidth/2-1, y, gaugeHeight+1); + if (barMin == -101) { + for (uint8_t i=0; i<3; ++i) { + lcdDrawPoint(x+i, y+4-i); + lcdDrawPoint(x+3+i, y+4-i); + } + } + if (barMax == 101) { + for (uint8_t i=0; i<3; ++i) { + lcdDrawPoint(x+gaugeWidth-8+i, y+4-i); + lcdDrawPoint(x+gaugeWidth-5+i, y+4-i); + } + } +} + +void menuModelMixOne(uint8_t event) +{ + if (event == EVT_KEY_LONG(KEY_MENU)) { + pushMenu(menuChannelsView); + killEvents(event); + } + + MixData * md2 = mixAddress(s_currIdx) ; + putsChn(PSIZE(TR_MIXER)*FW+FW, 0, md2->destCh+1,0); + lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); + + SUBMENU(STR_MIXER, MIX_FIELD_COUNT, {0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); + +#if MENU_COLUMNS > 1 + SET_SCROLLBAR_X(0); +#endif + + int8_t sub = menuVerticalPosition; + int8_t editMode = s_editMode; + + for (int k=0; k= LCD_LINES-1) + y = 1 + (k-LCD_LINES+2)*FH; + else + y = 1 + (k+1)*FH; + int8_t i = k; + +#if MENU_COLUMNS < 2 + i = i + menuVerticalOffset; +#endif + + LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); + switch(i) { + case MIX_FIELD_NAME: + editSingleName(MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr); + break; + + case MIX_FIELD_SOURCE: + lcd_putsLeft(y, NO_INDENT(STR_SOURCE)); + putsMixerSource(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_putsLeft(y, STR_WEIGHT); + gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); + break; + + case MIX_FIELD_OFFSET: + { + lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); + u_int8int16_t offset; + MD_OFFSET_TO_UNION(md2, offset); + offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event); + MD_UNION_TO_OFFSET(offset, md2); + drawOffsetBar(MIXES_2ND_COLUMN+22, y, md2); + break; + } + + case MIX_FIELD_TRIM: + lcd_putsLeft(y, STR_TRIM); + drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr); + if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1); + break; + +#if defined(CURVES) + case MIX_FIELD_CURVE: + lcd_putsLeft(y, STR_CURVE); + editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr); + break; +#endif + +#if defined(FLIGHT_MODES) + case MIX_FIELD_FLIGHT_MODE: + md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr); + break; +#endif + + case MIX_FIELD_SWITCH: + md2->swtch = switchMenuItem(MENU_COLUMN2_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event); + break; + + case MIX_FIELD_WARNING: + lcd_putsColumnLeft(MENU_COLUMN2_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING); + if (md2->mixWarn) + lcdDrawNumber(MENU_COLUMN2_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT); + else + lcdDrawText(MENU_COLUMN2_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(MENU_COLUMN2_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(MENU_COLUMN2_X, y, event, attr, STR_DELAYUP, md2->delayUp); + break; + + case MIX_FIELD_DELAY_DOWN: + md2->delayDown = EDIT_DELAY(MENU_COLUMN2_X, y, event, attr, STR_DELAYDOWN, md2->delayDown); + break; + + case MIX_FIELD_SLOW_UP: + md2->speedUp = EDIT_DELAY(MENU_COLUMN2_X, y, event, attr, STR_SLOWUP, md2->speedUp); + break; + + case MIX_FIELD_SLOW_DOWN: + md2->speedDown = EDIT_DELAY(MENU_COLUMN2_X, y, event, attr, STR_SLOWDOWN, md2->speedDown); + break; + } + } +} + +#define _STR_MAX(x) PSTR("/" #x) +#define STR_MAX(x) _STR_MAX(x) + +#define MIX_LINE_WEIGHT_POS 6*FW+10 +#define MIX_LINE_SRC_POS 7*FW+5 +#define MIX_LINE_CURVE_POS 13*FW+3 +#define MIX_LINE_SWITCH_POS 19*FW+1 +#define MIX_LINE_FM_POS 13*FW+3 +#define MIX_LINE_DELAY_POS 24*FW+3 +#define MIX_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH + +void onMixesMenu(const char * result) +{ + uint8_t chn = mixAddress(s_currIdx)->destCh + 1; + + if (result == STR_EDIT) { + pushMenu(menuModelMixOne); + } + else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { + if (!reachMixesLimit()) { + s_currCh = chn; + if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; } + insertMix(s_currIdx); + pushMenu(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 = menuVerticalPosition; + } + else if (result == STR_DELETE) { + deleteMix(s_currIdx); + } +} + +void displayHeaderChannelName(uint8_t ch) +{ + uint8_t len = zlen(g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name)); + if (len) { + lcdDrawSizedText(80, 1, g_model.limitData[ch].name, len, ZCHAR|SMLSIZE); + } +} + +void displayMixInfos(coord_t y, MixData *md) +{ + putsCurveRef(MIX_LINE_CURVE_POS, y, md->curve, 0); + + if (md->swtch) { + putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); + } +} + +void displayMixLine(coord_t y, MixData *md) +{ + if (md->name[0]) + lcdDrawSizedText(MIX_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR); + if (!md->flightModes || ((md->curve.value || md->swtch) && ((get_tmr10ms() / 200) & 1))) + displayMixInfos(y, md); + else + displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes); +} + +void menuModelMixAll(uint8_t event) +{ + uint8_t sub = menuVerticalPosition; + + if (s_editMode > 0) { + s_editMode = 0; + } + + uint8_t chn = 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) { + deleteMix(s_currIdx); + killEvents(event); + event = 0; + } + // no break + case EVT_KEY_BREAK(KEY_EXIT): + if (s_copyMode) { + if (s_copyTgtOfs) { + // cancel the current copy / move operation + if (s_copyMode == COPY_MODE) { + deleteMix(s_currIdx); + } + else { + do { + swapMixes(s_currIdx, s_copyTgtOfs > 0); + s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); + } while (s_copyTgtOfs != 0); + storageDirty(EE_MODEL); + } + menuVerticalPosition = s_copySrcRow; + s_copyTgtOfs = 0; + } + s_copyMode = 0; + event = 0; + } + break; + case EVT_KEY_BREAK(KEY_ENTER): + if ((!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_KEY_LONG(KEY_ENTER): + killEvents(event); + if (s_copyTgtOfs) { + s_copyMode = 0; + s_copyTgtOfs = 0; + } + else { + if (READ_ONLY()) { + if (!s_currCh) { + pushMenu(menuModelMixOne); + } + } + else { + if (s_copyMode) s_currCh = 0; + if (s_currCh) { + if (reachMixesLimit()) break; + insertMix(s_currIdx); + pushMenu(menuModelMixOne); + s_copyMode = 0; + } + else { + event = 0; + s_copyMode = 0; + POPUP_MENU_ADD_ITEM(STR_EDIT); + POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE); + POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER); + POPUP_MENU_ADD_ITEM(STR_COPY); + POPUP_MENU_ADD_ITEM(STR_MOVE); + POPUP_MENU_ADD_ITEM(STR_DELETE); + popupMenuHandler = onMixesMenu; + } + } + } + break; + case EVT_KEY_LONG(KEY_LEFT): + case EVT_KEY_LONG(KEY_RIGHT): + if (s_copyMode && !s_copyTgtOfs) { + if (reachMixesLimit()) break; + s_currCh = chn; + if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; } + insertMix(s_currIdx); + pushMenu(menuModelMixOne); + s_copyMode = 0; + killEvents(event); + } + break; + case EVT_KEY_FIRST(KEY_UP): + case EVT_KEY_REPT(KEY_UP): + case EVT_KEY_FIRST(KEY_DOWN): + case EVT_KEY_REPT(KEY_DOWN): + if (s_copyMode) { + uint8_t key = (event & 0x1f); + uint8_t next_ofs = (key==KEY_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 (reachMixesLimit()) break; + copyMix(s_currIdx); + if (key==KEY_DOWN) s_currIdx++; + else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++; + } + else if (next_ofs==0 && s_copyMode==COPY_MODE) { + // delete the mix + deleteMix(s_currIdx); + if (key==KEY_UP) s_currIdx--; + } + else { + // only swap the mix with its neighbor + if (!swapMixes(s_currIdx, key==KEY_UP)) break; + storageDirty(EE_MODEL); + } + + s_copyTgtOfs = next_ofs; + } + break; + } + + lcdDrawNumber(FW*sizeof(TR_MIXER)+FW+FW/2, 0, getMixesCount()); + lcdDrawText(FW*sizeof(TR_MIXER)+FW+FW/2, 0, STR_MAX(MAX_MIXERS)); + + // Value + uint8_t index = mixAddress(s_currIdx)->destCh; + if (!s_currCh) { + displayHeaderChannelName(index); + lcdDrawNumber(127, 2, calcRESXto1000(ex_chans[index]), PREC1|TINSIZE); + } + + SIMPLE_MENU(STR_MIXER, menuTabModel, e_MixAll, s_maxLines); + + // Gauge + if (!s_currCh) { + drawGauge(127, 1, 58, 6, ex_chans[index], 1024); + } + + sub = menuVerticalPosition; + s_currCh = 0; + int cur = 0; + int i = 0; + + for (int ch=1; ch<=NUM_CHNOUT; ch++) { + MixData * md; + coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH; + if (isrcRaw && md->destCh+1 == ch) { + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsChn(0, y, ch, 0); // show CHx + } + uint8_t mixCnt = 0; + do { + if (s_copyMode) { + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lcdDrawRect(22, y-1, LCD_W-22, 9, DOTTED); + cur++; y+=FH; + } + if (s_currIdx == i) { + sub = menuVerticalPosition = cur; + s_currCh = ch; + } + } + else if (sub == cur) { + s_currIdx = i; + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); + + if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0); + + putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0); + + gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), 0); + + displayMixLine(y, md); + + char cs = ' '; + if (md->speedDown || md->speedUp) + cs = 'S'; + if (md->delayUp || md->delayDown) + cs = (cs =='S' ? '*' : 'D'); + lcdDrawChar(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) */ + lcdDrawRect(22, y-1, LCD_W-22, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); + } + if (cur == sub) { + /* invert the raw when it's the current one */ + lcdDrawFilledRect(23, y, LCD_W-24, 7); + } + } + } + cur++; y+=FH; mixCnt++; i++; md++; + } while (isrcRaw && md->destCh+1 == ch); + if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { + lcdDrawRect(22, y-1, LCD_W-22, 9, DOTTED); + cur++; + } + } + else { + uint8_t attr = 0; + if (sub == cur) { + s_currIdx = i; + s_currCh = ch; + if (!s_copyMode) { + attr = INVERS; + } + } + if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) { + putsChn(0, y, ch, attr); // show CHx + if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { + lcdDrawRect(22, y-1, LCD_W-22, 9, DOTTED); + } + } + cur++; + } + } + s_maxLines = cur; + if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1; +} diff --git a/radio/src/gui/taranis/menu_model_setup.cpp b/radio/src/gui/taranis/menu_model_setup.cpp index 3a7221d7fc..e2a8a7fe3b 100644 --- a/radio/src/gui/taranis/menu_model_setup.cpp +++ b/radio/src/gui/taranis/menu_model_setup.cpp @@ -162,7 +162,6 @@ void editTimerMode(int timerIdx, coord_t y, LcdFlags attr, uint8_t event) #define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE)) -#if defined(PCBTARANIS) int getSwitchWarningsCount() { int count = 0; @@ -173,7 +172,6 @@ int getSwitchWarningsCount() } return count; } -#endif #if !defined(TARANIS_INTERNAL_PPM) #define INTERNAL_MODULE_MODE_ROWS 0 // (OFF / RF protocols) @@ -195,7 +193,7 @@ int getSwitchWarningsCount() #define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : TRAINER_CHANNELS_ROWS())) #define FAILSAFE_ROWS(x) (HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) #define TIMER_ROWS 2|NAVIGATION_LINE_BY_LINE, 0, CASE_PERSISTENT_TIMERS(0) 0, 0 -#define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0 +#define EXTERNAL_MODULE_MODE_ROWS (IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0 #if TIMERS == 1 #define TIMERS_ROWS TIMER_ROWS #elif TIMERS == 2 @@ -218,8 +216,9 @@ void menuModelSetup(uint8_t event) horzpos_t l_posHorz = menuHorizontalPosition; bool CURSOR_ON_CELL = (menuHorizontalPosition >= 0); #if defined(TARANIS_INTERNAL_PPM) - MENU_TAB({ 0, 0, TIMERS_ROWS, TOPLCD_ROWS 0, 1, 0, 0, LABEL(Throttle), 0, 0, 0, LABEL(PreflightCheck), 0, 0, SW_WARN_ITEMS(), POT_WARN_ITEMS(), - NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), 0, + MENU_TAB({ 0, 0, TIMERS_ROWS, TOPLCD_ROWS 0, 1, 0, 0, + LABEL(Throttle), 0, 0, 0, + LABEL(PreflightCheck), 0, 0, SW_WARN_ITEMS(), POT_WARN_ITEMS(), NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), 0, LABEL(InternalModule), INTERNAL_MODULE_MODE_ROWS, INTERNAL_MODULE_CHANNELS_ROWS, @@ -300,7 +299,7 @@ void menuModelSetup(uint8_t event) break; case ITEM_MODEL_TIMER1_MINUTE_BEEP: - g_model.timers[0].minuteBeep = onoffMenuItem(g_model.timers[0].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); + g_model.timers[0].minuteBeep = editCheckBox(g_model.timers[0].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); break; case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP: @@ -321,7 +320,7 @@ void menuModelSetup(uint8_t event) break; case ITEM_MODEL_TIMER2_MINUTE_BEEP: - g_model.timers[1].minuteBeep = onoffMenuItem(g_model.timers[1].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); + g_model.timers[1].minuteBeep = editCheckBox(g_model.timers[1].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); break; case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP: @@ -343,7 +342,7 @@ void menuModelSetup(uint8_t event) break; case ITEM_MODEL_TIMER3_MINUTE_BEEP: - g_model.timers[2].minuteBeep = onoffMenuItem(g_model.timers[2].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); + g_model.timers[2].minuteBeep = editCheckBox(g_model.timers[2].minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); break; case ITEM_MODEL_TIMER3_COUNTDOWN_BEEP: @@ -427,7 +426,7 @@ void menuModelSetup(uint8_t event) break; case ITEM_MODEL_THROTTLE_WARNING: - g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); + g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); break; #if defined(REV9E) @@ -602,13 +601,14 @@ void menuModelSetup(uint8_t event) case ITEM_MODEL_USE_GLOBAL_FUNCTIONS: lcd_putsLeft(y, STR_USE_GLOBAL_FUNCS); - menu_lcd_onoff(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr); + drawCheckBox(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr); if (attr) g_model.noGlobalFunctions = !checkIncDecModel(event, !g_model.noGlobalFunctions, 0, 1); break; case ITEM_MODEL_INTERNAL_MODULE_LABEL: lcd_putsLeft(y, TR_INTERNALRF); break; + #if defined(TARANIS_INTERNAL_PPM) case ITEM_MODEL_INTERNAL_MODULE_MODE: lcd_putsLeft(y, STR_MODE); diff --git a/radio/src/gui/taranis/menu_model_telemetry.cpp b/radio/src/gui/taranis/menu_model_telemetry.cpp index b29bde9ba1..d3ba4c5407 100644 --- a/radio/src/gui/taranis/menu_model_telemetry.cpp +++ b/radio/src/gui/taranis/menu_model_telemetry.cpp @@ -204,10 +204,11 @@ void menuModelSensor(uint8_t event) { TelemetrySensor * sensor = &g_model.telemetrySensors[s_currIdx]; - SUBMENU(STR_MENUSENSOR, SENSOR_FIELD_MAX, { 0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, SENSOR_AUTOOFFSET_ROWS, SENSOR_ONLYPOS_ROWS, SENSOR_FILTER_ROWS, SENSOR_PERSISTENT_ROWS, 0 }); - lcdDrawNumber(PSIZE(TR_MENUSENSOR)*FW+1, 0, s_currIdx+1, INVERS|LEFT); + putsStrIdx(PSIZE(TR_MENUSENSOR)*FW+FW, 0, STR_SENSOR, s_currIdx+1); + putsTelemetryChannelValue(32*FW, 0, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx)); + lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); - putsTelemetryChannelValue(SENSOR_2ND_COLUMN, 0, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), LEFT); + SUBMENU(STR_MENUSENSOR, SENSOR_FIELD_MAX, { 0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, SENSOR_AUTOOFFSET_ROWS, SENSOR_ONLYPOS_ROWS, SENSOR_FILTER_ROWS, SENSOR_PERSISTENT_ROWS, 0 }); for (int i=0; i 0) #define START_NO_HIGHLIGHT() do { noHighlightCounter = 25; } while(0) -void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr); +void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr); typedef void (*MenuHandlerFunc)(uint8_t event); @@ -109,7 +109,7 @@ void menuAboutView(uint8_t event); void menuTraceBuffer(uint8_t event); #endif -enum EnumTabDiag { +enum EnumTabRadio { e_Setup, e_Sd, e_GeneralCustomFunctions, @@ -263,7 +263,7 @@ swsrc_t checkIncDecMovedSwitch(swsrc_t val); CHECK_INCDEC_SWITCH(event, var, min, max, EE_MODEL, available) #define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \ - var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable) + var = checkIncDec(event, var, min, max, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable) #define CHECK_INCDEC_GENVAR(event, var, min, max) \ var = checkIncDecGen(event, var, min, max) @@ -295,6 +295,9 @@ void title(const pm_char * s); MENU_TAB(__VA_ARGS__); \ MENU_CHECK_FLAGS(title, tab, menu, flags, lines_count) +#define SIMPLE_MENU_FLAGS(title, tab, menu, flags, lines_count, ...) \ + check(title, event, menu, tab, DIM(tab), NULL, 0, lines_count, flags) + #define SIMPLE_MENU(title, tab, menu, lines_count) \ check_simple(title, event, menu, tab, DIM(tab), lines_count) @@ -316,22 +319,20 @@ void title(const pm_char * s); typedef int select_menu_value_t; select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event); -uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event); +uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event); swsrc_t switchMenuItem(coord_t x, coord_t y, swsrc_t value, LcdFlags attr, uint8_t event); -#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = onoffMenuItem(value, x, y, label, attr, event) +#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = editCheckBox(value, x, y, label, attr, event) #if defined(GVARS) - #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, editflags, event) -#else - #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, event) -#endif - -#if defined(GVARS) - int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event); + void drawGVarName(coord_t x, coord_t y, int8_t index, LcdFlags flags=0); + void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags=0); + int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event); + #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) editGVarFieldValue(x, y, v, min, max, lcdattr, editflags, event) #define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0) #else - int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); + #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) editGVarFieldValue(x, y, v, min, max, lcdattr, event) + int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); #define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v) #endif @@ -368,6 +369,18 @@ extern uint8_t s_copyMode; extern int8_t s_copySrcRow; extern int8_t s_copyTgtOfs; extern uint8_t s_currIdx; +extern uint8_t s_maxLines; +extern uint8_t s_copySrcIdx; +extern uint8_t s_copySrcCh; +extern int8_t s_currCh; + +uint8_t getExposCount(); +void deleteExpo(uint8_t idx); +void insertExpo(uint8_t idx); + +uint8_t getMixesCount(); +void deleteMix(uint8_t idx); +void insertMix(uint8_t idx); #define MENU_X 30 #define MENU_Y 16 @@ -400,7 +413,7 @@ extern uint8_t warningInfoFlags; #define POPUP_MENU_ADD_SD_ITEM(s) POPUP_MENU_ADD_ITEM(s) #define MENU_LINE_LENGTH (LEN_MODEL_NAME+12) #define POPUP_MENU_ITEMS_FROM_BSS() -extern const char *popupMenuItems[POPUP_MENU_MAX_LINES]; +extern const char * popupMenuItems[POPUP_MENU_MAX_LINES]; extern uint16_t popupMenuNoItems; extern uint16_t popupMenuOffset; enum { diff --git a/radio/src/gui/taranis/navigation.cpp b/radio/src/gui/taranis/navigation.cpp index 86cd496b59..1df6c918d6 100644 --- a/radio/src/gui/taranis/navigation.cpp +++ b/radio/src/gui/taranis/navigation.cpp @@ -328,11 +328,11 @@ int checkIncDec(unsigned int event, int val, int i_min, int i_max, unsigned int } #define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0) -#define MAXCOL_RAW(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) -#define MAXCOL(row) (MAXCOL_RAW(row) >= HIDDEN_ROW ? MAXCOL_RAW(row) : (const uint8_t)(MAXCOL_RAW(row) & (~NAVIGATION_LINE_BY_LINE))) -#define COLATTR(row) (MAXCOL_RAW(row) == (uint8_t)-1 ? (const uint8_t)0 : (const uint8_t)(MAXCOL_RAW(row) & NAVIGATION_LINE_BY_LINE)) -#define INC(val, min, max) if (valmin) {val--;} else {val=max;} +#define MAXCOL_RAW(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0) +#define MAXCOL(row) (MAXCOL_RAW(row) >= HIDDEN_ROW ? MAXCOL_RAW(row) : (const uint8_t)(MAXCOL_RAW(row) & (~NAVIGATION_LINE_BY_LINE))) +#define COLATTR(row) (MAXCOL_RAW(row) == (uint8_t)-1 ? (const uint8_t)0 : (const uint8_t)(MAXCOL_RAW(row) & NAVIGATION_LINE_BY_LINE)) +#define INC(val, min, max) if (valmin) {val--;} else {val=max;} coord_t scrollbar_X = DEFAULT_SCROLLBAR_X; diff --git a/radio/src/gui/taranis/popups.cpp b/radio/src/gui/taranis/popups.cpp index 9c3bf3ab1d..914a369a72 100644 --- a/radio/src/gui/taranis/popups.cpp +++ b/radio/src/gui/taranis/popups.cpp @@ -35,9 +35,9 @@ uint8_t s_menu_item = 0; uint16_t popupMenuNoItems = 0; uint16_t popupMenuOffset = 0; uint8_t popupMenuOffsetType = MENU_OFFSET_INTERNAL; -void (*popupMenuHandler)(const char *result); +void (*popupMenuHandler)(const char * result); -void displayBox(const char *title) +void displayBox(const char * title) { lcdDrawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE); lcdDrawRect(10, 16, LCD_W-20, 40); @@ -45,7 +45,7 @@ void displayBox(const char *title) // could be a place for a warningInfoText } -void displayPopup(const char *title) +void displayPopup(const char * title) { displayBox(title); lcdRefresh(); @@ -55,7 +55,7 @@ const pm_uchar asterisk_lbm[] PROGMEM = { #include "asterisk.lbm" }; -void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SOUND_ARG) +void drawMessageBox(const pm_char * title, const pm_char * t, const char * last, uint8_t sound) { lcdClear(); lcdDrawBitmap(0, 0, asterisk_lbm); @@ -78,7 +78,11 @@ void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SO } #undef MESSAGE_LCD_OFFSET +} +void message(const pm_char * title, const pm_char * t, const char * last, uint8_t sound) +{ + drawMessageBox(title, t, last, sound); lcdRefresh(); lcdSetContrast(); clearKeyEvents(); @@ -129,7 +133,7 @@ const char * displayPopupMenu(uint8_t event) drawVerticalScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_DISPLAY_LINES * (FH+1), popupMenuOffset, popupMenuNoItems, display_count); } - switch(event) { + switch (event) { case EVT_KEY_FIRST(KEY_UP): case EVT_KEY_REPT(KEY_UP): if (s_menu_item > 0) { diff --git a/radio/src/gui/taranis/view_main.cpp b/radio/src/gui/taranis/view_main.cpp index c76623d0cd..24e50e5a0f 100644 --- a/radio/src/gui/taranis/view_main.cpp +++ b/radio/src/gui/taranis/view_main.cpp @@ -489,8 +489,8 @@ void menuMainView(uint8_t event) case EVT_KEY_FIRST(KEY_EXIT): #if defined(GVARS) - if (s_gvar_timer > 0) { - s_gvar_timer = 0; + if (gvarDisplayTimer > 0) { + gvarDisplayTimer = 0; } #endif AUDIO_KEYPAD_UP(); @@ -553,7 +553,7 @@ void menuMainView(uint8_t event) else { // Logical Switches lcdDrawText(TRIM_RH_X - TRIM_LEN/2 + 5, 6*FH-1, "LS 1-32"); - for (int sw=0; sw= 5 ? 3 : 0); @@ -572,14 +572,15 @@ void menuMainView(uint8_t event) } #if defined(GVARS) - if (s_gvar_timer > 0) { - s_gvar_timer--; + if (gvarDisplayTimer > 0) { + gvarDisplayTimer--; lcdDrawFilledRect(BITMAP_X, BITMAP_Y, 64, 32, SOLID, ERASE); lcdDrawRect(BITMAP_X, BITMAP_Y, 64, 32); - putsStrIdx(BITMAP_X+FW, BITMAP_Y+FH-1, STR_GV, s_gvar_last+1); - lcdDrawSizedText(BITMAP_X+4*FW+FW/2, BITMAP_Y+FH-1, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, ZCHAR); - lcdDrawText(BITMAP_X+FW, BITMAP_Y+2*FH+3, PSTR("[\010]"), BOLD); - lcdDrawNumber(BITMAP_X+5*FW+FW/2, BITMAP_Y+2*FH+3, GVAR_VALUE(s_gvar_last, getGVarFlightPhase(mixerCurrentFlightMode, s_gvar_last)), BOLD); + putsStrIdx(BITMAP_X+FW, BITMAP_Y+FH-1, STR_GV, gvarLastChanged+1); + lcdDrawSizedText(BITMAP_X+4*FW+FW/2, BITMAP_Y+FH-1, g_model.gvars[gvarLastChanged].name, LEN_GVAR_NAME, ZCHAR); + lcdDrawText(BITMAP_X+FW, BITMAP_Y+2*FH+3, PSTR("["), BOLD); + drawGVarValue(BITMAP_X+2*FW, BITMAP_Y+2*FH+3, gvarLastChanged, GVAR_VALUE(gvarLastChanged, getGVarFlightMode(mixerCurrentFlightMode, gvarLastChanged)), LEFT|BOLD); + lcdDrawText(lcdLastPos, BITMAP_Y+2*FH+3, PSTR("]"), BOLD); } #endif } diff --git a/radio/src/gui/taranis/widgets.cpp b/radio/src/gui/taranis/widgets.cpp index 48b8932101..9d7ec30138 100644 --- a/radio/src/gui/taranis/widgets.cpp +++ b/radio/src/gui/taranis/widgets.cpp @@ -63,7 +63,7 @@ void drawColumnHeader(const char * const *headers, uint8_t index) lcdDrawText(17*FW, 0, headers[index], 0); } -void menu_lcd_onoff(coord_t x, coord_t y, uint8_t value, LcdFlags attr) +void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr) { if (value) lcdDrawChar(x+1, y, '#'); @@ -133,9 +133,9 @@ select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, c return value; } -uint8_t onoffMenuItem(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) +uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event ) { - menu_lcd_onoff(x, y, value, attr); + drawCheckBox(x, y, value, attr); return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event); } @@ -160,12 +160,29 @@ bool noZero(int val) return val != 0; } -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) +void drawGVarName(coord_t x, coord_t y, int8_t index, LcdFlags flags) +{ + if (ZEXIST(g_model.gvars[index].name)) + lcdDrawSizedText(x, y, g_model.gvars[index].name, LEN_GVAR_NAME, ZCHAR|flags); + else + putsStrIdx(x, y, STR_GV, index+1, flags); +} + +void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags) +{ + uint8_t prec = g_model.gvars[gvar].prec; + if (prec > 0) { + flags |= (prec == 1 ? PREC1 : PREC2); + } + putsValueWithUnit(x, y, value, g_model.gvars[gvar].unit ? UNIT_PERCENT : UNIT_RAW, flags); +} + +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event) { uint16_t delta = GV_GET_GV1_VALUE(max); bool invers = (attr & INVERS); - // TRACE("gvarMenuItem(val=%d min=%d max=%d)", value, min, max); + // TRACE("editGVarFieldValue(val=%d min=%d max=%d)", value, min, max); if (invers && event == EVT_KEY_LONG(KEY_ENTER)) { s_editMode = !s_editMode; @@ -198,7 +215,8 @@ int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t m else { value = (int16_t) GV_CALC_VALUE_IDX_POS(idx-1, delta); } - putsStrIdx(x, y, STR_GV, idx, attr); + + drawGVarName(x, y, idx-1, attr); } else { lcdDrawNumber(x, y, value, attr); @@ -207,7 +225,7 @@ int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t m return value; } #else -int16_t gvarMenuItem(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) +int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event) { lcdDrawNumber(x, y, value, attr); if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL); diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt index 4587e8673c..635ffce050 100644 --- a/radio/src/lua/CMakeLists.txt +++ b/radio/src/lua/CMakeLists.txt @@ -11,6 +11,6 @@ macro(add_lua_export_target target) add_custom_target(lua_export_${target} DEPENDS lua_exports_${target}.inc) endmacro(add_lua_export_target) -add_lua_export_target(taranis -DCPUARM -DPCBTARANIS -DLUA -DVIRTUALINPUTS) -add_lua_export_target(taranis_x9e -DCPUARM -DPCBTARANIS -DREVPLUS -DREV9E -DLUA -DVIRTUALINPUTS) -add_lua_export_target(horus -DCPUARM -DPCBHORUS -DLUA -DVIRTUALINPUTS) +add_lua_export_target(taranis -DPCBTARANIS -DLUA -DVIRTUALINPUTS) +add_lua_export_target(taranis_x9e -DPCBTARANIS -DREVPLUS -DREV9E -DLUA -DVIRTUALINPUTS) +add_lua_export_target(horus -DPCBHORUS -DLUA -DVIRTUALINPUTS) diff --git a/radio/src/lua/api_model.cpp b/radio/src/lua/api_model.cpp index 90aa38d34b..bf5ad5bec0 100644 --- a/radio/src/lua/api_model.cpp +++ b/radio/src/lua/api_model.cpp @@ -384,10 +384,10 @@ static int luaModelInsertInput(lua_State *L) unsigned int first = getFirstInput(chn); unsigned int count = getInputsCountFromFirst(chn, first); - if (chnweight, MIN_EXPO_WEIGHT, 100, mixerCurrentFlightMode); + v = ((int32_t)v * weight) / 1000; +#else int16_t weight = GET_GVAR(ed->weight, MIN_EXPO_WEIGHT, 100, mixerCurrentFlightMode); weight = calc100to256(weight); v = ((int32_t)v * weight) >> 8; +#endif #if defined(VIRTUALINPUTS) //========== OFFSET =============== - int16_t offset = GET_GVAR(ed->offset, -100, 100, mixerCurrentFlightMode); - if (offset) v += calc100toRESX(offset); + int32_t offset = GET_GVAR_PREC1(ed->offset, -100, 100, mixerCurrentFlightMode); + if (offset) v += calc100toRESX(offset) / 10; //========== TRIMS ================ if (ed->carryTrim < TRIM_ON) @@ -293,7 +298,8 @@ getvalue_t getValue(mixsrc_t i) else if (i<=MIXSRC_LAST_CH) return ex_chans[i-MIXSRC_CH1]; #if defined(GVARS) - else if (i<=MIXSRC_LAST_GVAR) return GVAR_VALUE(i-MIXSRC_GVAR1, getGVarFlightPhase(mixerCurrentFlightMode, i-MIXSRC_GVAR1)); + else if (i<=MIXSRC_LAST_GVAR) return GVAR_VALUE(i-MIXSRC_GVAR1, + getGVarFlightMode(mixerCurrentFlightMode, i - MIXSRC_GVAR1)); #endif #if defined(CPUARM) @@ -787,10 +793,14 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) } } +#if defined(CPUARM) + int32_t weight = GET_GVAR_PREC1(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + weight = calc100to256_16Bits(weight); +#else // saves 12 bytes code if done here and not together with weight; unknown reason int16_t weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); weight = calc100to256_16Bits(weight); - +#endif //========== SPEED =============== // now its on input side, but without weight compensation. More like other remote controls // lower weight causes slower movement @@ -844,12 +854,20 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) #endif //========== WEIGHT =============== - int32_t dv = (int32_t) v * weight; + int32_t dv = (int32_t)v * weight; +#if defined(CPUARM) + dv /= 10; +#endif //========== OFFSET / AFTER =============== if (apply_offset_and_curve) { +#if defined(CPUARM) + int32_t offset = GET_GVAR_PREC1(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); + if (offset) dv += int32_t(calc100toRESX_16Bits(offset) / 10) << 8; +#else int16_t offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode); if (offset) dv += int32_t(calc100toRESX_16Bits(offset)) << 8; +#endif } //========== DIFFERENTIAL ========= diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 499a007d22..0a145cddf3 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -203,22 +203,6 @@ enum CurveType { CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM }; -#if defined(XCURVES) -PACK(typedef struct { - uint8_t type:3; - uint8_t smooth:1; - uint8_t spare:4; - int8_t points; -}) CurveInfo; -#else -struct CurveInfo { - int8_t * crv; - uint8_t points; - bool custom; -}; -extern CurveInfo curveInfo(uint8_t idx); -#endif - #if defined(PCBHORUS) #define LEN_MODEL_NAME 15 #define LEN_TIMER_NAME 8 @@ -227,9 +211,9 @@ extern CurveInfo curveInfo(uint8_t idx); #define LEN_EXPOMIX_NAME 6 #define LEN_CHANNEL_NAME 6 #define LEN_INPUT_NAME 4 + #define LEN_CURVE_NAME 3 #define MAX_CURVES 32 #define NUM_POINTS 512 - #define CURVDATA CurveInfo #elif defined(PCBFLAMENCO) #define LEN_MODEL_NAME 12 #define LEN_TIMER_NAME 8 @@ -237,9 +221,9 @@ extern CurveInfo curveInfo(uint8_t idx); #define LEN_EXPOMIX_NAME 6 #define LEN_CHANNEL_NAME 6 #define LEN_INPUT_NAME 4 + #define LEN_CURVE_NAME 3 #define MAX_CURVES 32 #define NUM_POINTS 512 - #define CURVDATA CurveInfo #elif defined(PCBTARANIS) #define LEN_MODEL_NAME 12 #define LEN_TIMER_NAME 8 @@ -248,9 +232,9 @@ extern CurveInfo curveInfo(uint8_t idx); #define LEN_EXPOMIX_NAME 8 #define LEN_CHANNEL_NAME 6 #define LEN_INPUT_NAME 4 + #define LEN_CURVE_NAME 3 #define MAX_CURVES 32 #define NUM_POINTS 512 - #define CURVDATA CurveInfo #elif defined(CPUARM) #define LEN_MODEL_NAME 10 #define LEN_TIMER_NAME 3 @@ -258,13 +242,11 @@ extern CurveInfo curveInfo(uint8_t idx); #define LEN_EXPOMIX_NAME 6 #define MAX_CURVES 16 #define NUM_POINTS 512 - #define CURVDATA int16_t #else #define LEN_MODEL_NAME 10 #define LEN_FLIGHT_MODE_NAME 6 #define MAX_CURVES 8 #define NUM_POINTS (112-MAX_CURVES) - #define CURVDATA int8_t #endif #if defined(PCBTARANIS) || defined(PCBSKY9X) || defined(PCBHORUS) @@ -273,6 +255,20 @@ extern CurveInfo curveInfo(uint8_t idx); #define NUM_MODULES 1 #endif +#if defined(XCURVES) +PACK(typedef struct { + uint8_t type:3; + uint8_t smooth:1; + uint8_t spare:4; + int8_t points; + char name[LEN_CURVE_NAME]; +}) CurveData; +#elif defined(CPUARM) +typedef int16_t CurveData; +#else +typedef int8_t CurveData; +#endif + typedef int16_t gvar_t; #if defined(PCBTARANIS) @@ -282,14 +278,18 @@ typedef int16_t gvar_t; #endif #if !defined(PCBSTD) - #define LEN_GVAR_NAME 6 - #define GVAR_MAX 1024 - #define GVAR_LIMIT 500 + #define LEN_GVAR_NAME 3 + #define GVAR_MAX 1024 + #define GVAR_MIN -GVAR_MAX PACK(typedef struct { - char name[LEN_GVAR_NAME]; - uint8_t popup:1; - uint8_t spare:7; - }) global_gvar_t; + char name[LEN_GVAR_NAME]; + uint32_t min:12; + uint32_t max:12; + uint32_t popup:1; + uint32_t prec:1; + uint32_t unit:2; + uint32_t spare:4; + }) GVarData; #endif #define RESERVE_RANGE_FOR_GVARS 10 @@ -310,9 +310,9 @@ typedef int16_t gvar_t; #else #define MAX_GVARS 5 #endif - #define MODEL_GVARS_DATA global_gvar_t gvars[MAX_GVARS]; + #define MODEL_GVARS_DATA GVarData gvars[MAX_GVARS]; #define PHASE_GVARS_DATA gvar_t gvars[MAX_GVARS] - #define GVAR_VALUE(x, p) g_model.flightModeData[p].gvars[x] + #define GVAR_VALUE(gv, fm) g_model.flightModeData[fm].gvars[gv] #endif PACK(typedef struct { @@ -391,7 +391,10 @@ enum BeeperMode { int8_t backgroundVolume; #endif -#if defined(PCBTARANIS) || defined(PCBHORUS) +#if defined(PCBHORUS) || defined(PCBFLAMENCO) + #define swconfig_t uint16_t + #define swarnstate_t uint32_t +#elif defined(PCBTARANIS) #if defined(REV9E) #define swconfig_t uint64_t #define swarnstate_t uint64_t @@ -527,7 +530,7 @@ enum PotsWarnMode { TRAINER_MODE_SLAVE }; #define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; - #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; + #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; #elif defined(PCBFLAMENCO) enum ModuleIndex { EXTERNAL_MODULE, @@ -538,7 +541,7 @@ enum PotsWarnMode { TRAINER_MODE_SLAVE }; #define MODELDATA_BITMAP uint8_t bitmap; - #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; + #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; #elif defined(PCBTARANIS) enum ModuleIndex { INTERNAL_MODULE, @@ -554,7 +557,7 @@ enum PotsWarnMode { }; #define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE) #define MODELDATA_BITMAP char bitmap[LEN_BITMAP_NAME]; - #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char curveNames[MAX_CURVES][6]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; + #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS]; #elif defined(PCBSKY9X) enum ModuleIndex { EXTERNAL_MODULE, @@ -646,39 +649,34 @@ enum Functions { FUNC_MAX }; -#if defined(OVERRIDE_CHANNEL_FUNCTION) - #define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE) -#else - #define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE && (func) != FUNC_OVERRIDE_CHANNEL) -#endif - #if defined(VOICE) - #define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE) + #define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE) #else - #define IS_PLAY_FUNC(func) ((func) == FUNC_PLAY_SOUND) + #define IS_PLAY_FUNC(func) ((func) == FUNC_PLAY_SOUND) #endif #if defined(CPUARM) - #define IS_PLAY_BOTH_FUNC(func) (0) - #define IS_VOLUME_FUNC(func) ((func) == FUNC_VOLUME) + #define IS_PLAY_BOTH_FUNC(func) (0) + #define IS_VOLUME_FUNC(func) ((func) == FUNC_VOLUME) #else - #define IS_PLAY_BOTH_FUNC(func) ((func) == FUNC_PLAY_BOTH) - #define IS_VOLUME_FUNC(func) (0) + #define IS_PLAY_BOTH_FUNC(func) ((func) == FUNC_PLAY_BOTH) + #define IS_VOLUME_FUNC(func) (0) #endif #if defined(GVARS) - #define IS_ADJUST_GV_FUNC(func) ((func) == FUNC_ADJUST_GVAR) + #define IS_ADJUST_GV_FUNC(func) ((func) == FUNC_ADJUST_GVAR) #else - #define IS_ADJUST_GV_FUNC(func) (0) + #define IS_ADJUST_GV_FUNC(func) (0) #endif #if defined(HAPTIC) - #define IS_HAPTIC_FUNC(func) ((func) == FUNC_HAPTIC) + #define IS_HAPTIC_FUNC(func) ((func) == FUNC_HAPTIC) #else - #define IS_HAPTIC_FUNC(func) (0) + #define IS_HAPTIC_FUNC(func) (0) #endif -#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func)) +#define HAS_ENABLE_PARAM(func) ((func) < FUNC_FIRST_WITHOUT_ENABLE && !IS_ADJUST_GV_FUNC(func)) +#define HAS_REPEAT_PARAM(func) (IS_PLAY_FUNC(func) || IS_HAPTIC_FUNC(func) || IS_ADJUST_GV_FUNC(func)) enum ResetFunctionParam { FUNC_RESET_TIMER1, @@ -708,16 +706,16 @@ enum AdjustGvarFunctionParam { FUNC_ADJUST_GVAR_CONSTANT, FUNC_ADJUST_GVAR_SOURCE, FUNC_ADJUST_GVAR_GVAR, - FUNC_ADJUST_GVAR_INC, + FUNC_ADJUST_GVAR_INCDEC, }; #if defined(CPUARM) #if defined(PCBTARANIS) - #define LEN_CFN_NAME 8 - #define CFN_SPARE_TYPE int32_t + #define LEN_CFN_NAME 8 + #define CFN_SPARE_TYPE int32_t #else - #define LEN_CFN_NAME 6 - #define CFN_SPARE_TYPE int16_t + #define LEN_CFN_NAME 6 + #define CFN_SPARE_TYPE int16_t #endif PACK(typedef struct { int16_t swtch:9; @@ -731,7 +729,7 @@ PACK(typedef struct { int16_t val; uint8_t mode; uint8_t param; - CFN_SPARE_TYPE spare2; + CFN_SPARE_TYPE spare; }) all; PACK(struct { @@ -741,20 +739,21 @@ PACK(typedef struct { }); uint8_t active; }) CustomFunctionData; -#define CFN_EMPTY(p) (!(p)->swtch) -#define CFN_SWITCH(p) ((p)->swtch) -#define CFN_FUNC(p) ((p)->func) -#define CFN_ACTIVE(p) ((p)->active) -#define CFN_CH_INDEX(p) ((p)->all.param) -#define CFN_GVAR_INDEX(p) ((p)->all.param) -#define CFN_TIMER_INDEX(p) ((p)->all.param) -#define CFN_PLAY_REPEAT(p) ((p)->active) -#define CFN_PLAY_REPEAT_MUL 1 -#define CFN_PLAY_REPEAT_NOSTART 0xFF -#define CFN_GVAR_MODE(p) ((p)->all.mode) -#define CFN_PARAM(p) ((p)->all.val) -#define CFN_RESET(p) ((p)->active=0, (p)->clear.val1=0, (p)->clear.val2=0) -#define CFN_GVAR_CST_MAX GVAR_LIMIT +#define CFN_EMPTY(p) (!(p)->swtch) +#define CFN_SWITCH(p) ((p)->swtch) +#define CFN_FUNC(p) ((p)->func) +#define CFN_ACTIVE(p) ((p)->active) +#define CFN_CH_INDEX(p) ((p)->all.param) +#define CFN_GVAR_INDEX(p) ((p)->all.param) +#define CFN_TIMER_INDEX(p) ((p)->all.param) +#define CFN_PLAY_REPEAT(p) ((p)->active) +#define CFN_PLAY_REPEAT_MUL 1 +#define CFN_PLAY_REPEAT_NOSTART 0xFF +#define CFN_GVAR_MODE(p) ((p)->all.mode) +#define CFN_PARAM(p) ((p)->all.val) +#define CFN_RESET(p) ((p)->active=0, (p)->clear.val1=0, (p)->clear.val2=0) +#define CFN_GVAR_CST_MIN -GVAR_MAX +#define CFN_GVAR_CST_MAX GVAR_MAX #elif defined(CPUM2560) PACK(typedef struct { int8_t swtch; @@ -976,9 +975,9 @@ PACK(typedef struct { #define LIMIT_EXT_PERCENT 150 #define LIMIT_EXT_MAX (LIMIT_EXT_PERCENT*10) #define PPM_CENTER_MAX 500 - #define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR(lim->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode)*10 : lim->max+1000) - #define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR(lim->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode)*10 : lim->min-1000) - #define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR(lim->offset, -1000, 1000, mixerCurrentFlightMode)*10 : lim->offset) + #define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR_PREC1(lim->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode) : lim->max+1000) + #define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR_PREC1(lim->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode) : lim->min-1000) + #define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR_PREC1(lim->offset, -1000, 1000, mixerCurrentFlightMode) : 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)) @@ -2312,7 +2311,7 @@ PACK(typedef struct { LimitData limitData[NUM_CHNOUT]; ExpoData expoData[MAX_EXPOS]; - CURVDATA curves[MAX_CURVES]; + CurveData curves[MAX_CURVES]; int8_t points[NUM_POINTS]; LogicalSwitchData logicalSw[NUM_LOGICAL_SWITCH]; @@ -2325,7 +2324,9 @@ PACK(typedef struct { uint8_t thrTraceSrc; swarnstate_t switchWarningState; +#if !defined(COLORLCD) swarnenable_t switchWarningEnable; +#endif MODEL_GVARS_DATA diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 7201a9a22d..fd188ed466 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -233,6 +233,19 @@ void memclear(void *ptr, uint8_t size) } #endif +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; + } +} + void generalDefault() { memclear(&g_eeGeneral, sizeof(g_eeGeneral)); @@ -655,13 +668,13 @@ void incRotaryEncoder(uint8_t idx, int8_t inc) GVAR_VALUE(idx, phase) = value; \ storageDirty(EE_MODEL); \ if (g_model.gvars[idx].popup) { \ - s_gvar_last = idx; \ - s_gvar_timer = GVAR_DISPLAY_TIME; \ + gvarLastChanged = idx; \ + gvarDisplayTimer = GVAR_DISPLAY_TIME; \ } #endif #if defined(PCBSTD) -int16_t getGVarValue(int16_t x, int16_t min, int16_t max) +int16_t getGVarFieldValue(int16_t x, int16_t min, int16_t max) { if (GV_IS_GV_VALUE(x, min, max)) { int8_t idx = GV_INDEX_CALCULATION(x, max); @@ -685,44 +698,75 @@ void setGVarValue(uint8_t idx, int8_t value) } } #else -uint8_t s_gvar_timer = 0; -uint8_t s_gvar_last = 0; +uint8_t gvarDisplayTimer = 0; +uint8_t gvarLastChanged = 0; -uint8_t getGVarFlightPhase(uint8_t phase, uint8_t idx) +uint8_t getGVarFlightMode(uint8_t fm, uint8_t gv) // TODO change params order to be consistent! { for (uint8_t i=0; i= phase) result++; - phase = result; + if (result >= fm) result++; + fm = result; } return 0; } -int16_t getGVarValue(int16_t x, int16_t min, int16_t max, int8_t phase) +int16_t getGVarValue(int8_t gv, int8_t fm) { - if (GV_IS_GV_VALUE(x, min, max)) { - int8_t idx = GV_INDEX_CALCULATION(x, max); - int8_t mul = 1; - - if (idx < 0) { - idx = -1-idx; - mul = -1; - } - - x = GVAR_VALUE(idx, getGVarFlightPhase(phase, idx)) * mul; + int8_t mul = 1; + if (gv < 0) { + gv = -1-gv; + mul = -1; } - return limit(min, x, max); + return GVAR_VALUE(gv, getGVarFlightMode(fm, gv)) * mul; } -void setGVarValue(uint8_t idx, int16_t value, int8_t phase) +int32_t getGVarValuePrec1(int8_t gv, int8_t fm) { - phase = getGVarFlightPhase(phase, idx); - if (GVAR_VALUE(idx, phase) != value) { - SET_GVAR_VALUE(idx, phase, value); + int8_t mul; + uint8_t prec = g_model.gvars[gv].prec; + if (prec == 0) + mul = 10; + else + mul = 1; + + if (gv < 0) { + gv = -1-gv; + mul = -mul; } + return GVAR_VALUE(gv, getGVarFlightMode(fm, gv)) * mul; +} + +void setGVarValue(uint8_t gv, int16_t value, int8_t fm) +{ + fm = getGVarFlightMode(fm, gv); + if (GVAR_VALUE(gv, fm) != value) { + SET_GVAR_VALUE(gv, fm, value); + } +} + +int16_t getGVarFieldValue(int16_t val, int16_t min, int16_t max, int8_t fm) +{ + if (GV_IS_GV_VALUE(val, min, max)) { + int8_t gv = GV_INDEX_CALCULATION(val, max); + val = getGVarValue(gv, fm); + } + return limit(min, val, max); +} + +int32_t getGVarFieldValuePrec1(int16_t val, int16_t min, int16_t max, int8_t fm) +{ + if (GV_IS_GV_VALUE(val, min, max)) { + int8_t gv = GV_INDEX_CALCULATION(val, max); + val = getGVarValuePrec1(gv, fm); + } + else { + val *= 10; + } + return limit(min*10, val, max*10); } #endif @@ -1320,7 +1364,7 @@ uint8_t checkTrim(uint8_t event) #if defined(PCBSTD) phase = 0; #else - phase = getGVarFlightPhase(mixerCurrentFlightMode, trimGvar[idx]); + phase = getGVarFlightMode(mixerCurrentFlightMode, trimGvar[idx]); #endif before = GVAR_VALUE(trimGvar[idx], phase); thro = false; @@ -2408,7 +2452,7 @@ void opentxInit(OPENTX_INIT_ARGS) #endif #if defined(VOICE) - setVolume(g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF); + setScaledVolume(g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF); #endif #if defined(CPUARM) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index e8db7933ac..3ee8cf5615 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -281,8 +281,6 @@ #include "targets/9x/board_stock.h" #endif -#include "debug.h" - #if defined(SIMU) #include "targets/simu/simpgmspace.h" #elif defined(CPUARM) @@ -319,6 +317,8 @@ #include #endif +#include "debug.h" + #if defined(PCBFLAMENCO) #define NUM_SWITCHES 5 #elif defined(PCBTARANIS) || defined(PCBHORUS) @@ -350,6 +350,8 @@ #define memclear(p, s) memset(p, 0, s) #endif +void memswap(void * a, void * b, uint8_t size); + #if defined(PCBHORUS) #define IS_POT_AVAILABLE(x) (true) #define IS_POT_MULTIPOS(x) ((x)==POT2) @@ -457,7 +459,7 @@ #define MAX_TRAINER_CHANNELS() (8) #endif -#if defined(PCBTARANIS) +#if defined(PCBTARANIS) || defined(PCBHORUS) #if defined(TARANIS_INTERNAL_PPM) #define IS_MODULE_PPM(idx) (idx==TRAINER_MODULE || (idx==INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type==MODULE_TYPE_PPM)|| (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_PPM)) #define IS_MODULE_XJT(idx) (((idx==INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type==MODULE_TYPE_XJT)|| (idx==EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type==MODULE_TYPE_XJT)) && (g_model.moduleData[idx].rfProtocol != RF_PROTO_OFF)) @@ -664,8 +666,12 @@ uint16_t evalChkSum(); #define ALERT(title, msg, sound) alert(title, msg) #endif -extern void message(const pm_char *title, const pm_char *s, const char *last MESSAGE_SOUND_ARG); -extern void alert(const pm_char * t, const pm_char * s MESSAGE_SOUND_ARG); +// TODO these functions in gui directories +#if defined(COLORLCD) || defined(PCBTARANIS) +void drawMessageBox(const pm_char * title, const pm_char * t, const char * last, uint8_t sound); +#endif +void message(const pm_char * title, const pm_char * s, const char * last MESSAGE_SOUND_ARG); +void alert(const pm_char * t, const pm_char * s MESSAGE_SOUND_ARG); enum PerOutMode { e_perout_mode_normal = 0, @@ -812,22 +818,27 @@ int getTrimValue(uint8_t phase, uint8_t idx); #if defined(GVARS) #if defined(PCBSTD) - int16_t getGVarValue(int16_t x, int16_t min, int16_t max); + int16_t getGVarFieldValue(int16_t x, int16_t min, int16_t max); void setGVarValue(uint8_t x, int8_t value); - #define GET_GVAR(x, min, max, p) getGVarValue(x, min, max) - #define SET_GVAR(idx, val, p) setGVarValue(idx, val) + #define GET_GVAR(x, min, max, fm) getGVarFieldValue(x, min, max) + #define SET_GVAR(idx, val, fm) setGVarValue(idx, val) #else - uint8_t getGVarFlightPhase(uint8_t phase, uint8_t idx); - int16_t getGVarValue(int16_t x, int16_t min, int16_t max, int8_t phase); - void setGVarValue(uint8_t x, int16_t value, int8_t phase); - #define GET_GVAR(x, min, max, p) getGVarValue(x, min, max, p) - #define SET_GVAR(idx, val, p) setGVarValue(idx, val, p) + uint8_t getGVarFlightMode(uint8_t fm, uint8_t gv); + int16_t getGVarFieldValue(int16_t x, int16_t min, int16_t max, int8_t fm); + int32_t getGVarFieldValuePrec1(int16_t x, int16_t min, int16_t max, int8_t fm); + int16_t getGVarValue(int8_t gv, int8_t fm); + int32_t getGVarValuePrec1(int8_t gv, int8_t fm); + void setGVarValue(uint8_t x, int16_t value, int8_t fm); + #define GET_GVAR(x, min, max, fm) getGVarFieldValue(x, min, max, fm) + #define SET_GVAR(idx, val, fm) setGVarValue(idx, val, fm) #define GVAR_DISPLAY_TIME 100 /*1 second*/; - extern uint8_t s_gvar_timer; - extern uint8_t s_gvar_last; + #define GET_GVAR_PREC1(x, min, max, fm) getGVarFieldValuePrec1(x, min, max, fm) + extern uint8_t gvarDisplayTimer; + extern uint8_t gvarLastChanged; #endif #else #define GET_GVAR(x, ...) (x) + #define GET_GVAR_PREC1(x, ...) (x*10) #endif #if defined(CPUARM) @@ -1161,6 +1172,17 @@ LimitData *limitAddress(uint8_t idx); int8_t *curveAddress(uint8_t idx); LogicalSwitchData *lswAddress(uint8_t idx); +#if defined(XCURVES) +typedef CurveData CurveInfo; +#else +struct CurveInfo { + int8_t * crv; + uint8_t points:7; + uint8_t custom:1; +}; +extern CurveInfo curveInfo(uint8_t idx); +#endif + // static variables used in evalFlightModeMixes - moved here so they don't interfere with the stack // It's also easier to initialize them here. #if defined(VIRTUALINPUTS) @@ -1175,10 +1197,6 @@ extern BeepANACenter bpanaCenter; extern uint8_t s_mixer_first_run_done; -extern int8_t s_currCh; -uint8_t getExpoMixCount(uint8_t expo); -void deleteExpoMix(uint8_t expo, uint8_t idx); -void insertExpoMix(uint8_t expo, uint8_t idx); void applyDefaultTemplate(); void incSubtrim(uint8_t idx, int16_t inc); diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index e4caa27731..d45c38de5a 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -316,7 +316,7 @@ void Open9xSim::updateKeysAndSwitches(bool start) SWITCH_KEY(P, 15, 3); SWITCH_KEY(Q, 16, 3); SWITCH_KEY(R, 17, 3); -#elif defined(PCBTARANIS) +#elif defined(PCBTARANIS) || defined(PCBHORUS) SWITCH_KEY(A, 0, 3); SWITCH_KEY(B, 1, 3); SWITCH_KEY(C, 2, 3); @@ -360,11 +360,11 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*) #if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBHORUS) static bool rotencAction = false; - if (getApp()->getKeyState(KEY_G)) { + if (getApp()->getKeyState(KEY_X)) { if (!rotencAction) ROTENC_VALUE += ROTARY_ENCODER_GRANULARITY; rotencAction = true; } - else if (getApp()->getKeyState(KEY_D)) { + else if (getApp()->getKeyState(KEY_W)) { if (!rotencAction) ROTENC_VALUE -= ROTARY_ENCODER_GRANULARITY; rotencAction = true; } @@ -392,7 +392,7 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*) SWITCH_KEY(P, 15, 3); SWITCH_KEY(Q, 16, 3); SWITCH_KEY(R, 17, 3); -#elif defined(PCBTARANIS) +#elif defined(PCBTARANIS) || defined(PCBHORUS) SWITCH_KEY(A, 0, 3); SWITCH_KEY(B, 1, 3); SWITCH_KEY(C, 2, 3); @@ -545,7 +545,7 @@ uint16_t anaIn(uint8_t chan) return th9xSim->sliders[chan]->getValue(); else if (chanknobs[chan-NUM_STICKS]->getValue(); -#if defined(PCBTARANIS) || defined(PCBFLAMENCO) +#if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) else if (chan == TX_VOLTAGE) return 1000; #elif defined(PCBSKY9X) diff --git a/radio/src/storage/eeprom_conversions.cpp b/radio/src/storage/eeprom_conversions.cpp index 8958c65ca9..df954e594e 100644 --- a/radio/src/storage/eeprom_conversions.cpp +++ b/radio/src/storage/eeprom_conversions.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "opentx.h" enum Mix216Sources { @@ -636,6 +636,21 @@ PACK(typedef struct { uint8_t rxBattAlarms[2]; #endif +#if defined(PCBTARANIS) +#define MODELDATA_EXTRA_217 \ + uint8_t spare:3; \ + uint8_t trainerMode:3; \ + uint8_t potsWarnMode:2; \ + ModuleData moduleData[NUM_MODULES+1]; \ + char curveNames[MAX_CURVES][6]; \ + ScriptData scriptsData[MAX_SCRIPTS]; \ + char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; \ + uint8_t potsWarnEnabled; \ + int8_t potsWarnPosition[NUM_POTS]; +#else +#define MODELDATA_EXTRA_217 MODELDATA_EXTRA +#endif + #if defined(PCBTARANIS) PACK(typedef struct { char name[LEN_MODEL_NAME]; @@ -670,7 +685,7 @@ PACK(typedef struct { LimitData_v216 limitData[NUM_CHNOUT]; ExpoData_v216 expoData[MAX_EXPOS]; - CURVDATA curves[MAX_CURVES]; + CurveData curves[MAX_CURVES]; int8_t points[NUM_POINTS]; LogicalSwitchData_v216 logicalSw[32]; @@ -683,7 +698,7 @@ PACK(typedef struct { uint16_t switchWarningState; uint8_t switchWarningEnable; - global_gvar_t gvars[MAX_GVARS]; + GVarData gvars[MAX_GVARS]; FrSkyData_v216 frsky; @@ -710,7 +725,7 @@ PACK(typedef struct { LimitData limitData[NUM_CHNOUT]; ExpoData_v217 expoData[MAX_EXPOS]; - CURVDATA curves[MAX_CURVES]; + CurveData curves[MAX_CURVES]; int8_t points[NUM_POINTS]; LogicalSwitchData_v217 logicalSw[32]; @@ -727,7 +742,7 @@ PACK(typedef struct { TELEMETRY_DATA - MODELDATA_EXTRA + MODELDATA_EXTRA_217 TelemetrySensor telemetrySensors[MAX_SENSORS]; @@ -1291,6 +1306,16 @@ void ConvertModel_217_to_218(ModelData & model) newModel.expoData[i].mode = oldModel.expoData[i].mode; memcpy(newModel.expoData[i].name, oldModel.expoData[i].name, sizeof(newModel.expoData[i].name)); } + for (int i=0; i> (3*i)) & 0x07); + if (state && state-1 != ((switches_states >> (i*2)) & 0x03)) { + warn = true; + } + } + } #elif defined(PCBTARANIS) for (int i=0; i> (3*i)) & 0x07); + if (state && state-1 != ((switches_states >> (i*2)) & 0x03)) { if (++numWarnings < 6) { - putsSwitches(x, y, SWSRC_FIRST_SWITCH+i*3, attr); - x += 20; + // LcdFlags attr = ((states & mask) == (switches_states & mask)) ? TEXT_COLOR : ALARM_COLOR; + LcdFlags attr = ALARM_COLOR; + putsSwitches(x, y, SWSRC_FIRST_SWITCH+i*3+state-1, attr); + x += SWITCH_WARNING_LIST_INTERVAL; } else if (numWarnings == 6) { lcdDrawText(x, y, "...", ALARM_COLOR); } } + } #else + if (SWITCH_WARNING_ALLOWED(i) && !(g_model.switchWarningEnable & (1< VOLUME_LEVEL_MAX) { volume = VOLUME_LEVEL_MAX; } - i2cWriteRegister(I2C_ADDRESS_VOLUME, 0, volumeScale[volume]); + setVolume(volumeScale[volume]); +} + +void setVolume(uint8_t volume) +{ + i2cWriteRegister(I2C_ADDRESS_VOLUME, 0, volume); +} + +int32_t getVolume() +{ + return i2cReadRegister(I2C_ADDRESS_VOLUME, 0); } diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp index 7f9b83d303..acf91feb04 100644 --- a/radio/src/targets/horus/trainer_driver.cpp +++ b/radio/src/targets/horus/trainer_driver.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "../../opentx.h" extern Fifo<32> sbusFifo; @@ -29,9 +29,9 @@ void init_trainer_ppm() { trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses; - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN ; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; configure_pins( TRAINER_GPIO_PIN_OUT, PIN_PERIPHERAL | PIN_PORTB | PIN_PER_2 | PIN_OS25 | PIN_PUSHPULL ) ; - configure_pins( TRAINER_GPIO_PIN_IN, PIN_PORTB | PIN_INPUT ) ; + configure_pins( TRAINER_GPIO_PIN_IN, PIN_PORTC | PIN_INPUT ) ; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN ; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN ; @@ -76,7 +76,7 @@ void init_trainer_capture() { GPIO_InitTypeDef GPIO_InitStructure; - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = TRAINER_GPIO_PIN_IN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 879c29b4bb..282718df87 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -198,7 +198,7 @@ void simuSetSwitch(uint8_t swtch, int8_t state) // SWITCH_3_CASE(3, SWITCHES_GPIO_REG_D_L, SWITCHES_GPIO_REG_D_H, SWITCHES_GPIO_PIN_D_L, SWITCHES_GPIO_PIN_D_H) // SWITCH_CASE(4, SWITCHES_GPIO_REG_E, SWITCHES_GPIO_PIN_E) // SWITCH_3_CASE(5, SWITCHES_GPIO_REG_F_H, SWITCHES_GPIO_REG_F_L, SWITCHES_GPIO_PIN_F_H, SWITCHES_GPIO_PIN_F_L) -#elif defined(PCBTARANIS) && defined(REV9E) +#elif defined(PCBTARANIS) || defined(PCBHORUS) SWITCH_3_CASE(0, SWITCHES_GPIO_REG_A_L, SWITCHES_GPIO_REG_A_H, SWITCHES_GPIO_PIN_A_L, SWITCHES_GPIO_PIN_A_H) SWITCH_3_CASE(1, SWITCHES_GPIO_REG_B_L, SWITCHES_GPIO_REG_B_H, SWITCHES_GPIO_PIN_B_L, SWITCHES_GPIO_PIN_B_H) SWITCH_3_CASE(2, SWITCHES_GPIO_REG_C_L, SWITCHES_GPIO_REG_C_H, SWITCHES_GPIO_PIN_C_L, SWITCHES_GPIO_PIN_C_H) @@ -207,6 +207,7 @@ void simuSetSwitch(uint8_t swtch, int8_t state) SWITCH_CASE(5, SWITCHES_GPIO_REG_F, SWITCHES_GPIO_PIN_F) SWITCH_3_CASE(6, SWITCHES_GPIO_REG_G_L, SWITCHES_GPIO_REG_G_H, SWITCHES_GPIO_PIN_G_L, SWITCHES_GPIO_PIN_G_H) SWITCH_CASE(7, SWITCHES_GPIO_REG_H, SWITCHES_GPIO_PIN_H) + #if defined(REV9E) SWITCH_3_CASE(8, SWITCHES_GPIO_REG_I_L, SWITCHES_GPIO_REG_I_H, SWITCHES_GPIO_PIN_I_L, SWITCHES_GPIO_PIN_I_H) SWITCH_3_CASE(9, SWITCHES_GPIO_REG_J_L, SWITCHES_GPIO_REG_J_H, SWITCHES_GPIO_PIN_J_L, SWITCHES_GPIO_PIN_J_H) SWITCH_3_CASE(10, SWITCHES_GPIO_REG_K_L, SWITCHES_GPIO_REG_K_H, SWITCHES_GPIO_PIN_K_L, SWITCHES_GPIO_PIN_K_H) @@ -217,15 +218,7 @@ void simuSetSwitch(uint8_t swtch, int8_t state) SWITCH_3_CASE(15, SWITCHES_GPIO_REG_P_L, SWITCHES_GPIO_REG_P_H, SWITCHES_GPIO_PIN_P_L, SWITCHES_GPIO_PIN_P_H) SWITCH_3_CASE(16, SWITCHES_GPIO_REG_Q_L, SWITCHES_GPIO_REG_Q_H, SWITCHES_GPIO_PIN_Q_L, SWITCHES_GPIO_PIN_Q_H) SWITCH_3_CASE(17, SWITCHES_GPIO_REG_R_L, SWITCHES_GPIO_REG_R_H, SWITCHES_GPIO_PIN_R_L, SWITCHES_GPIO_PIN_R_H) -#elif defined(PCBTARANIS) || defined(PCBHORUS) - SWITCH_3_CASE(0, SWITCHES_GPIO_REG_A_L, SWITCHES_GPIO_REG_A_H, SWITCHES_GPIO_PIN_A_L, SWITCHES_GPIO_PIN_A_H) - SWITCH_3_CASE(1, SWITCHES_GPIO_REG_B_L, SWITCHES_GPIO_REG_B_H, SWITCHES_GPIO_PIN_B_L, SWITCHES_GPIO_PIN_B_H) - SWITCH_3_CASE(2, SWITCHES_GPIO_REG_C_L, SWITCHES_GPIO_REG_C_H, SWITCHES_GPIO_PIN_C_L, SWITCHES_GPIO_PIN_C_H) - SWITCH_3_CASE(3, SWITCHES_GPIO_REG_D_L, SWITCHES_GPIO_REG_D_H, SWITCHES_GPIO_PIN_D_L, SWITCHES_GPIO_PIN_D_H) - SWITCH_3_CASE(4, SWITCHES_GPIO_REG_E_H, SWITCHES_GPIO_REG_E_L, SWITCHES_GPIO_PIN_E_H, SWITCHES_GPIO_PIN_E_L) - SWITCH_CASE(5, SWITCHES_GPIO_REG_F, SWITCHES_GPIO_PIN_F) - SWITCH_3_CASE(6, SWITCHES_GPIO_REG_G_L, SWITCHES_GPIO_REG_G_H, SWITCHES_GPIO_PIN_G_L, SWITCHES_GPIO_PIN_G_H) - SWITCH_CASE(7, SWITCHES_GPIO_REG_H, SWITCHES_GPIO_PIN_H) + #endif #elif defined(PCBSKY9X) SWITCH_CASE(0, PIOC->PIO_PDSR, 1<<20) SWITCH_CASE(1, PIOA->PIO_PDSR, 1<<15) @@ -467,6 +460,10 @@ bool dacQueue(AudioBuffer *buffer) } void setVolume(uint8_t volume) +{ +} + +void setScaledVolume(uint8_t volume) { simuAudio.currentVolume = min((volumeScale[min(volume, VOLUME_LEVEL_MAX)] * simuAudio.volumeGain) / 10, 127); // TRACE("setVolume(): in: %u, out: %u", volume, simuAudio.currentVolume); @@ -574,7 +571,7 @@ void StartAudioThread(int volumeGain) simuAudio.leftoverLen = 0; simuAudio.threadRunning = true; simuAudio.volumeGain = volumeGain; - setVolume(VOLUME_LEVEL_DEF); + setScaledVolume(VOLUME_LEVEL_DEF); pthread_attr_t attr; pthread_attr_init(&attr); @@ -1342,3 +1339,9 @@ void i2cWriteTW8823(unsigned char, unsigned char) { } uint8_t i2cReadBQ24195(uint8_t) { return 0; } void i2cWriteBQ24195(uint8_t, uint8_t) { } #endif + +void serialPrintf(const char * format, ...) { } +void serialCrlf() { } +void serialPutc(char c) { } +uint16_t stackSize() { return 0; } +int32_t getVolume() { return 0; } diff --git a/radio/src/targets/sky9x/audio_driver.cpp b/radio/src/targets/sky9x/audio_driver.cpp index 950f439004..3931333e51 100644 --- a/radio/src/targets/sky9x/audio_driver.cpp +++ b/radio/src/targets/sky9x/audio_driver.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "../../opentx.h" const int8_t volumeScale[VOLUME_LEVEL_MAX+1] = @@ -161,7 +161,7 @@ void audioEnd() PMC->PMC_PCER0 &= ~0x40000000L ; // Disable peripheral clock to DAC } -void setVolume(uint8_t volume) +void setScaledVolume(uint8_t volume) { #if !defined(NO_HARDWARE_VOLUME) volumeRequired = volumeScale[min(volume, VOLUME_LEVEL_MAX)]; @@ -171,6 +171,5 @@ void setVolume(uint8_t volume) #endif } - #endif // #if !defined(SIMU) diff --git a/radio/src/targets/sky9x/audio_driver.h b/radio/src/targets/sky9x/audio_driver.h index 0a12e02f6c..6cd790d672 100644 --- a/radio/src/targets/sky9x/audio_driver.h +++ b/radio/src/targets/sky9x/audio_driver.h @@ -20,27 +20,27 @@ #ifndef _AUDIO_DRIVER_H_ #define _AUDIO_DRIVER_H_ - -void audioInit( void ) ; -void audioEnd( void ) ; - -void setSampleRate( uint32_t frequency ) ; - -inline void dacStart() -{ - PMC->PMC_PCER0 |= 0x40000000L ; // Enable peripheral clock to DAC - DACC->DACC_IER = DACC_IER_ENDTX ; -} - -inline void dacStop() -{ - DACC->DACC_IDR = DACC_IDR_ENDTX ; // Disable interrupt -} - -#define VOLUME_LEVEL_MAX 23 -#define VOLUME_LEVEL_DEF 12 -extern const int8_t volumeScale[]; - -void setVolume(uint8_t volume); - + +void audioInit( void ) ; +void audioEnd( void ) ; + +void setSampleRate( uint32_t frequency ) ; + +inline void dacStart() +{ + PMC->PMC_PCER0 |= 0x40000000L ; // Enable peripheral clock to DAC + DACC->DACC_IER = DACC_IER_ENDTX ; +} + +inline void dacStop() +{ + DACC->DACC_IDR = DACC_IDR_ENDTX ; // Disable interrupt +} + +#define VOLUME_LEVEL_MAX 23 +#define VOLUME_LEVEL_DEF 12 +extern const int8_t volumeScale[]; + +void setScaledVolume(uint8_t volume); + #endif // _AUDIO_DRIVER_H_ diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 54a2976258..8b758a28af 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -1,25 +1,25 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _BOARD_TARANIS_H_ -#define _BOARD_TARANIS_H_ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _BOARD_TARANIS_H_ +#define _BOARD_TARANIS_H_ #include "stddef.h" @@ -328,7 +328,9 @@ void setSampleRate(uint32_t frequency); extern const int8_t volumeScale[]; #define VOLUME_LEVEL_MAX 23 #define VOLUME_LEVEL_DEF 12 +void setScaledVolume(uint8_t volume); void setVolume(uint8_t volume); +int32_t getVolume(void); // Haptic driver void hapticInit(void); @@ -384,4 +386,4 @@ void usbJoystickUpdate(void); extern uint8_t currentTrainerMode; void checkTrainerSettings(void); -#endif // _BOARD_TARANIS_H_ +#endif // _BOARD_TARANIS_H_ diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 25a738b9cf..47da1de48b 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -1,25 +1,25 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _HAL_H_ -#define _HAL_H_ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _HAL_H_ +#define _HAL_H_ // Keys #define KEYS_GPIO_REG_MENU GPIOD->IDR @@ -148,10 +148,10 @@ #define SWITCHES_GPIO_REG_E_L GPIOE->IDR #define SWITCHES_GPIO_PIN_E_L GPIO_Pin_13 // PE.13 #else - #define SWITCHES_GPIO_REG_E_L GPIOB->IDR - #define SWITCHES_GPIO_PIN_E_L GPIO_Pin_3 // PB.03 #define SWITCHES_GPIO_REG_E_H GPIOB->IDR - #define SWITCHES_GPIO_PIN_E_H GPIO_Pin_4 // PB.04 + #define SWITCHES_GPIO_PIN_E_H GPIO_Pin_3 // PB.03 + #define SWITCHES_GPIO_REG_E_L GPIOB->IDR + #define SWITCHES_GPIO_PIN_E_L GPIO_Pin_4 // PB.04 #endif #if defined(REV9E) @@ -587,4 +587,4 @@ #define TIMER_2MHz_APB1Periph RCC_APB1Periph_TIM7 #define TIMER_2MHz_TIMER TIM7 -#endif // _HAL_H_ +#endif // _HAL_H_ diff --git a/radio/src/targets/taranis/i2c_driver.cpp b/radio/src/targets/taranis/i2c_driver.cpp index 9ab7a0a305..e6cf932ded 100644 --- a/radio/src/targets/taranis/i2c_driver.cpp +++ b/radio/src/targets/taranis/i2c_driver.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "board_taranis.h" void eepromPageWrite(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t NumByteToWrite); @@ -243,12 +243,17 @@ void eepromWaitEepromStandbyState(void) } #if !defined(BOOT) -void setVolume(uint8_t volume) +void setScaledVolume(uint8_t volume) { if (volume > VOLUME_LEVEL_MAX) { volume = VOLUME_LEVEL_MAX; } + setVolume(volumeScale[volume]); +} + +void setVolume(uint8_t volume) +{ if (!I2C_WaitEventCleared(I2C_FLAG_BUSY)) return; @@ -263,29 +268,15 @@ void setVolume(uint8_t volume) I2C_SendData(I2C, 0); if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING)) return; - I2C_SendData(I2C, volumeScale[volume]); + I2C_SendData(I2C, volume); if (!I2C_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)) return; I2C_GenerateSTOP(I2C, ENABLE); } -#endif -#if 0 -uint8_t I2C_read_volume() +int32_t getVolume() { - uint8_t volume ; - I2C_START(); - I2C_SEND_DATA(I2C_ADDRESS_VOLUME|EE_CMD_WRITE); - I2C_WAIT_ACK(); - I2C_SEND_DATA(0); - I2C_WAIT_ACK(); - I2C_START(); - I2C_SEND_DATA(I2C_ADDRESS_VOLUME|EE_CMD_READ); - I2C_WAIT_ACK(); - volume = I2C_READ(); - I2C_NO_ACK(); - I2C_STOP(); - return volume ; + return 0; // TODO } #endif diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp index 7ee37aa30d..2ff459e64f 100644 --- a/radio/src/targets/taranis/keys_driver.cpp +++ b/radio/src/targets/taranis/keys_driver.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "../../opentx.h" uint32_t readKeys() @@ -175,7 +175,6 @@ void readKeysAndTrims() case SW_S ## x ## 2: \ xxx = (~SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H) && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \ break - #define ADD_3POS_INVERTED_CASE(x, i) ADD_3POS_CASE(x, i) #else #define ADD_2POS_CASE(x) \ case SW_S ## x ## 0: \ @@ -200,22 +199,6 @@ void readKeysAndTrims() xxx = xxx && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \ } \ break - #define ADD_3POS_INVERTED_CASE(x, i) \ - case SW_S ## x ## 0: \ - xxx = (~SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H); \ - if (IS_3POS(i)) { \ - xxx = xxx && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \ - } \ - break; \ - case SW_S ## x ## 1: \ - xxx = (SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H) && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \ - break; \ - case SW_S ## x ## 2: \ - xxx = (SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H); \ - if (IS_3POS(i)) { \ - xxx = xxx && (~SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \ - } \ - break #endif #if !defined(BOOT) @@ -230,7 +213,7 @@ bool switchState(EnumKeys enuk) ADD_3POS_CASE(B, 1); ADD_3POS_CASE(C, 2); ADD_3POS_CASE(D, 3); - ADD_3POS_INVERTED_CASE(E, 4); + ADD_3POS_CASE(E, 4); ADD_2POS_CASE(F); ADD_3POS_CASE(G, 6); ADD_2POS_CASE(H); diff --git a/radio/src/targets/taranis/pwr_driver.c b/radio/src/targets/taranis/pwr_driver.c index bf3470813b..21854a5683 100644 --- a/radio/src/targets/taranis/pwr_driver.c +++ b/radio/src/targets/taranis/pwr_driver.c @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "../../pwr.h" #include "board_taranis.h" diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 3ec3fd7ce0..3222573537 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -1,23 +1,23 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + #include "opentx.h" #define ISTR(x) LEN_##x TR_##x @@ -172,8 +172,6 @@ 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; @@ -337,7 +335,6 @@ const pm_char STR_MENUCUSTOMFUNC[] PROGMEM = TR_MENUCUSTOMFUNC; #if defined(LUA) const pm_char STR_MENUCUSTOMSCRIPTS[] PROGMEM = TR_MENUCUSTOMSCRIPTS; -const pm_char STR_MENUCUSTOMSCRIPT[] PROGMEM = TR_MENUCUSTOMSCRIPT; #endif #if defined(FRSKY) @@ -365,6 +362,7 @@ const pm_char STR_COUNTRYCODE[] PROGMEM = TR_COUNTRYCODE; const pm_char STR_FAILSAFE[] PROGMEM = TR_FAILSAFE; const pm_char STR_FAILSAFESET[] PROGMEM = TR_FAILSAFESET; const pm_char STR_MENUSENSOR[] PROGMEM = TR_MENUSENSOR; +const pm_char STR_SENSOR[] PROGMEM = TR_SENSOR; #endif const pm_char STR_INVERT_THR[] PROGMEM = TR_INVERT_THR; @@ -408,11 +406,11 @@ const pm_char STR_PERSISTENT_MAH[] PROGMEM = TR_PERSISTENT_MAH; #if defined(NAVIGATION_MENUS) const pm_char STR_SELECT_MODEL[] PROGMEM = TR_SELECT_MODEL; -const pm_char STR_CREATE_CATEGORY[] PROGMEM = TR_CREATE_CATEGORY; -const pm_char STR_RENAME_CATEGORY[] PROGMEM = TR_RENAME_CATEGORY; -const pm_char STR_DELETE_CATEGORY[] PROGMEM = TR_DELETE_CATEGORY; +const pm_char STR_CREATE_CATEGORY[] PROGMEM = TR_CREATE_CATEGORY; +const pm_char STR_RENAME_CATEGORY[] PROGMEM = TR_RENAME_CATEGORY; +const pm_char STR_DELETE_CATEGORY[] PROGMEM = TR_DELETE_CATEGORY; const pm_char STR_CREATE_MODEL[] PROGMEM = TR_CREATE_MODEL; -const pm_char STR_DUPLICATE_MODEL[] PROGMEM = TR_DUPLICATE_MODEL; +const pm_char STR_DUPLICATE_MODEL[] PROGMEM = TR_DUPLICATE_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; @@ -477,10 +475,10 @@ 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 = TR_NO_SCRIPTS_ON_SD; -const pm_char STR_SCRIPT_SYNTAX_ERROR[] PROGMEM = TR_SCRIPT_SYNTAX_ERROR; -const pm_char STR_SCRIPT_PANIC[] PROGMEM = TR_SCRIPT_PANIC; -const pm_char STR_SCRIPT_KILLED[] PROGMEM = TR_SCRIPT_KILLED; -const pm_char STR_SCRIPT_ERROR[] PROGMEM = TR_SCRIPT_ERROR; +const pm_char STR_SCRIPT_SYNTAX_ERROR[] PROGMEM = TR_SCRIPT_SYNTAX_ERROR; +const pm_char STR_SCRIPT_PANIC[] PROGMEM = TR_SCRIPT_PANIC; +const pm_char STR_SCRIPT_KILLED[] PROGMEM = TR_SCRIPT_KILLED; +const pm_char STR_SCRIPT_ERROR[] PROGMEM = TR_SCRIPT_ERROR; 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 = TR_EXECUTE_FILE; @@ -503,7 +501,7 @@ 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_V[] PROGMEM = TR_GLOBAL_V; +const pm_char STR_GVARS[] PROGMEM = TR_GVARS; 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; @@ -545,7 +543,7 @@ const pm_char STR_BLCOLOR[] PROGMEM = TR_BLCOLOR; const pm_char STR_PREFLIGHT[] PROGMEM = TR_PREFLIGHT; const pm_char STR_CHECKLIST[] PROGMEM = TR_CHECKLIST; const pm_char STR_VIEW_NOTES[] PROGMEM = TR_VIEW_NOTES; -const pm_char STR_MODEL_SELECT[] PROGMEM = TR_MODEL_SELECT; +const pm_char STR_MODEL_SELECT[] PROGMEM = TR_MODEL_SELECT; const pm_char STR_RESET_SUBMENU[] PROGMEM = TR_RESET_SUBMENU; const pm_char STR_LOWALARM[] PROGMEM = TR_LOWALARM; const pm_char STR_CRITICALALARM[] PROGMEM = TR_CRITICALALARM; @@ -572,10 +570,10 @@ const pm_char STR_MODEL_SELECT[] PROGMEM = TR_MODEL_SELECT; const pm_char STR_TELEMETRYFULL[] PROGMEM = TR_TELEMETRYFULL; const pm_char STR_INVERTED_SERIAL[] PROGMEM = TR_INVERTED_SERIAL; const pm_char STR_IGNORE_INSTANCE[] PROGMEM = TR_IGNORE_INSTANCE; - const pm_char STR_DISCOVER_SENSORS[] PROGMEM = TR_DISCOVER_SENSORS; + const pm_char STR_DISCOVER_SENSORS[] PROGMEM = TR_DISCOVER_SENSORS; const pm_char STR_STOP_DISCOVER_SENSORS[] PROGMEM = TR_STOP_DISCOVER_SENSORS; const pm_char STR_DELETE_ALL_SENSORS[] PROGMEM = TR_DELETE_ALL_SENSORS; - const pm_char STR_CONFIRMDELETE[] PROGMEM = TR_CONFIRMDELETE; + const pm_char STR_CONFIRMDELETE[] PROGMEM = TR_CONFIRMDELETE; #endif #if defined(PCBTARANIS) || defined(PCBFLAMENCO) || defined(PCBHORUS) @@ -584,6 +582,9 @@ const pm_char STR_MODEL_SELECT[] PROGMEM = TR_MODEL_SELECT; const pm_char STR_MODULE[] PROGMEM = TR_MODULE; const pm_char STR_ENABLE_POPUP[] PROGMEM = TR_ENABLE_POPUP; const pm_char STR_DISABLE_POPUP[] PROGMEM = TR_DISABLE_POPUP; +const pm_char STR_POPUP[] PROGMEM = TR_POPUP; +const pm_char STR_MIN[] PROGMEM = TR_MIN; +const pm_char STR_MAX[] PROGMEM = TR_MAX; const pm_char STR_CURVE_PRESET[] PROGMEM = TR_CURVE_PRESET; const pm_char STR_PRESET[] PROGMEM = TR_PRESET; const pm_char STR_MIRROR[] PROGMEM = TR_MIRROR; @@ -595,10 +596,10 @@ const pm_char STR_MODEL_SELECT[] PROGMEM = TR_MODEL_SELECT; const pm_char STR_SMOOTH[] PROGMEM = TR_SMOOTH; const pm_char STR_COPY_STICKS_TO_OFS[] PROGMEM = TR_COPY_STICKS_TO_OFS; const pm_char STR_COPY_TRIMS_TO_OFS[] PROGMEM = TR_COPY_TRIMS_TO_OFS; - const pm_char STR_INCDEC[] PROGMEM = TR_INCDEC; - const pm_char STR_GLOBALVAR[] PROGMEM = TR_GLOBALVAR; - const pm_char STR_MIXSOURCE[] PROGMEM = TR_MIXSOURCE; - const pm_char STR_CONSTANT[] PROGMEM = TR_CONSTANT; + const pm_char STR_INCDEC[] PROGMEM = TR_INCDEC; + const pm_char STR_GLOBALVAR[] PROGMEM = TR_GLOBALVAR; + const pm_char STR_MIXSOURCE[] PROGMEM = TR_MIXSOURCE; + const pm_char STR_CONSTANT[] PROGMEM = TR_CONSTANT; const pm_char STR_TOP_BAR[] PROGMEM = TR_TOP_BAR; const pm_char STR_ALTITUDE[] PROGMEM = TR_ALTITUDE; const pm_char STR_SCALE[] PROGMEM = TR_SCALE; diff --git a/radio/src/translations.h b/radio/src/translations.h index 0c45ac5fb5..1c4c4f9025 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -1,25 +1,25 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _TRANSLATIONS_H_ -#define _TRANSLATIONS_H_ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _TRANSLATIONS_H_ +#define _TRANSLATIONS_H_ #if defined(TRANSLATIONS_FR) #include "translations/fr.h" @@ -370,8 +370,6 @@ extern const pm_char STR_BUZZER[]; #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[]; @@ -509,7 +507,6 @@ extern const pm_char STR_MENULOGICALSWITCH[]; extern const pm_char STR_MENULOGICALSWITCHES[]; 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[]; @@ -535,6 +532,7 @@ extern const pm_char STR_EXTERNALRF[]; extern const pm_char STR_FAILSAFE[]; extern const pm_char STR_FAILSAFESET[]; extern const pm_char STR_MENUSENSOR[]; +extern const pm_char STR_SENSOR[]; extern const pm_char STR_COUNTRYCODE[]; #endif @@ -679,7 +677,7 @@ 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_V[]; +extern const pm_char STR_GVARS[]; extern const pm_char STR_GLOBAL_VAR[]; extern const pm_char STR_OWN[]; extern const pm_char STR_ROTARY_ENCODER[]; @@ -829,6 +827,9 @@ extern const pm_char STR_BLCOLOR[]; extern const pm_char STR_MODULE[]; extern const pm_char STR_ENABLE_POPUP[]; extern const pm_char STR_DISABLE_POPUP[]; +extern const pm_char STR_POPUP[]; +extern const pm_char STR_MIN[]; +extern const pm_char STR_MAX[]; extern const pm_char STR_CURVE_PRESET[]; extern const pm_char STR_PRESET[]; extern const pm_char STR_MIRROR[]; @@ -958,4 +959,4 @@ extern const pm_char STR_BLCOLOR[]; #define CHR_HOUR TR_CHR_HOUR #define CHR_INPUT TR_CHR_INPUT -#endif // _TRANSLATIONS_H_ +#endif // _TRANSLATIONS_H_ diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 6f5c9c9c30..e30e0385ea 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -627,8 +627,6 @@ #define TR_MODE INDENT"Mód" #define TR_NOFREEEXPO "Není volné expo!" #define TR_NOFREEMIXER "Není volný mix!" -#define TR_INSERTMIX "VLOžIT MIX " -#define TR_EDITMIX "UPRAVIT MIX " #define TR_SOURCE INDENT"Zdroj" #define TR_WEIGHT "Váha" #define TR_EXPO "Expo" @@ -777,7 +775,6 @@ #define TR_MENULOGICALSWITCHES "LOGICKÉ SPÍNAčE" #define TR_MENUCUSTOMFUNC "SPECIÁLNÍ FUNKCE" #define TR_MENUCUSTOMSCRIPTS "SKRIPTY LUA" -#define TR_MENUCUSTOMSCRIPT "SKRIPT" #define TR_MENUTELEMETRY "TELEMETRIE" #define TR_MENUTEMPLATES "ŠABLONY" #define TR_MENUSTAT "STATISTIKA" @@ -876,7 +873,7 @@ #define TR_SD_SIZE "Velikost:" #define TR_TYPE INDENT TR_SD_TYPE #define TR_GLOBAL_VARS "Globální proměnné" -#define TR_GLOBAL_V "GLOB.PROM." +#define TR_GVARS "GLOB.PROM." #define TR_GLOBAL_VAR "Globální proměnná" #define TR_MENUGLOBALVARS "GLOBÁLNÍ PROMěNNÉ" #define TR_OWN " \043 " @@ -896,6 +893,7 @@ #define TR_FAILSAFE "Mód Failsafe" #define TR_FAILSAFESET "NASTAVENÍ FAILSAFE" #define TR_MENUSENSOR "SENZOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Kód regionu" #define TR_VOICELANG "Jazyk hlasu" #define TR_UNITSSYSTEM "Jednotky" @@ -939,6 +937,9 @@ #define TR_CRITICALALARM INDENT "Kritický Alarm" #define TR_ENABLE_POPUP "Povolit vyskakovací okno" #define TR_DISABLE_POPUP "Zakázat vyskakovací okno" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Šablona" #define TR_PRESET "Šablona" #define TR_MIRROR "Zrcadlit" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index 3d98e516ad..94db7068cd 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -631,8 +631,6 @@ #define TR_MODE INDENT "Modus" #define TR_NOFREEEXPO "Expos voll!" #define TR_NOFREEMIXER "Mischer voll!" -#define TR_INSERTMIX "MISCHER Hinz." -#define TR_EDITMIX "MISCHER Edit" #define TR_SOURCE INDENT "Quelle" #define TR_WEIGHT "Gewicht" #define TR_EXPO TR("Expo", "Exponential") @@ -781,7 +779,6 @@ #define TR_MENULOGICALSWITCHES "LOGIKSCHALTER" #define TR_MENUCUSTOMFUNC TR("SPEZ.-FUNKTIONEN", "SPEZIAL-FUNKTIONEN") #define TR_MENUCUSTOMSCRIPTS "LUA-SCRIPTE" -#define TR_MENUCUSTOMSCRIPT "LUA-SCRIPT" #define TR_MENUTELEMETRY "TELEMETRIE" #define TR_MENUTEMPLATES "VORLAGEN" #define TR_MENUSTAT "STAT" @@ -809,11 +806,11 @@ #define TR_VOLTAGE TR(INDENT "Spg", INDENT "Spannungsquelle") //9XR-Pro #define TR_CURRENT TR(INDENT "Strom", INDENT "Stromquelle") #define TR_SELECT_MODEL "Modell Wählen" -#define TR_CREATE_CATEGORY "Create Category" -#define TR_RENAME_CATEGORY "Rename Category" -#define TR_DELETE_CATEGORY "Delete Category" +#define TR_CREATE_CATEGORY "Create Category" +#define TR_RENAME_CATEGORY "Rename Category" +#define TR_DELETE_CATEGORY "Delete Category" #define TR_CREATE_MODEL "Neues Modell" -#define TR_DUPLICATE_MODEL "Duplicate Model" +#define TR_DUPLICATE_MODEL "Duplicate Model" #define TR_COPY_MODEL "Kopiere Modell" #define TR_MOVE_MODEL "Verschiebe Modell" #define TR_BACKUP_MODEL "Modell auf SD-Karte" //9XR-Pro @@ -880,7 +877,7 @@ #define TR_SD_SIZE "Größe:" #define TR_TYPE INDENT "Type" #define TR_GLOBAL_VARS "Globale Variablen" -#define TR_GLOBAL_V "GLOBALE V." +#define TR_GVARS "GLOBALE V." #define TR_GLOBAL_VAR "Globale Variable" #define TR_MENUGLOBALVARS "GLOBALE VARIABLEN" #define TR_OWN "Eigen" @@ -900,6 +897,7 @@ #define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe Mode") #define TR_FAILSAFESET "Failsafe setzen" #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Landescode" #define TR_VOICELANG "Sprach-Ansage" #define TR_UNITSSYSTEM "Einheiten" @@ -943,6 +941,9 @@ #define TR_CRITICALALARM INDENT "Kritisch-Alarm" #define TR_ENABLE_POPUP "Freigabe Popup-Fenster" #define TR_DISABLE_POPUP "Sperren Popup-Fenster" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Gerade 0 11 22 33 45" #define TR_PRESET "Preset" #define TR_MIRROR "Spiegeln" @@ -1071,7 +1072,7 @@ #define TR_SCALE "Skalierer" #define TR_VIEW_CHANNELS "Zeige Kanäle" #define TR_VIEW_NOTES "Zeige Notizen" -#define TR_MODEL_SELECT "Model Select" +#define TR_MODEL_SELECT "Model Select" #define TR_MODS_FORBIDDEN "Veränderungen verboten!" #define TR_UNLOCKED "Entsperrt" #define TR_ID "ID" @@ -1090,7 +1091,7 @@ #define TR_ONLYPOSITIVE "Nur Positiv" #define TR_FILTER "Filter aktiv" #define TR_TELEMETRYFULL "Telemetriezeilen voll!" -#define TR_INVERTED_SERIAL INDENT "Invert." +#define TR_INVERTED_SERIAL INDENT "Invert." #define TR_IGNORE_INSTANCE TR(INDENT "Keine ID", INDENT "Keine Multisen-ID") //unklar #define TR_DISCOVER_SENSORS INDENT "Start Sensorsuche" #define TR_STOP_DISCOVER_SENSORS INDENT "Stop Sensorsuche" @@ -1121,7 +1122,7 @@ #define ZSTR_A4 "A4" #define ZSTR_BATT "RxBt" #define ZSTR_ALT "Alt" -#define ZSTR_TEMP1 "Tmp1" +#define ZSTR_TEMP1 "Tmp1" #define ZSTR_TEMP2 "Tmp2" #define ZSTR_RPM "RPM" #define ZSTR_FUEL "Fuel" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 3bfbf4c1be..116ce7cfc6 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -129,7 +129,9 @@ #define LEN_RETA123 "\001" -#if defined(PCBFLAMENCO) +#if defined(PCBHORUS) + #define TR_RETA123 "RETA12345LR" +#elif defined(PCBFLAMENCO) #define TR_RETA123 "RETA123LR" #elif defined(PCBTARANIS) && defined(REV9E) #define TR_RETA123 "RETA1234LRLR" @@ -650,8 +652,6 @@ #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") @@ -804,7 +804,6 @@ #define TR_MENULOGICALSWITCHES "LOGICAL SWITCHES" #define TR_MENUCUSTOMFUNC "SPECIAL FUNCTIONS" #define TR_MENUCUSTOMSCRIPTS "CUSTOM SCRIPTS" -#define TR_MENUCUSTOMSCRIPT "CUSTOM SCRIPT" #define TR_MENUTELEMETRY "TELEMETRY" #define TR_MENUTEMPLATES "TEMPLATES" #define TR_MENUSTAT "STATS" @@ -904,7 +903,7 @@ #define TR_SD_SIZE "Size:" #define TR_TYPE INDENT "Type" #define TR_GLOBAL_VARS "Global Variables" -#define TR_GLOBAL_V "GLOBAL V." +#define TR_GVARS "GVARS" #define TR_GLOBAL_VAR "Global Variable" #define TR_MENUGLOBALVARS "GLOBAL VARIABLES" #define TR_OWN "Own" @@ -923,7 +922,8 @@ #define TR_EXTERNALRF "External RF" #define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe mode") #define TR_FAILSAFESET "FAILSAFE SETTINGS" -#define TR_MENUSENSOR "SENSOR" +#define TR_MENUSENSOR "SENSORS" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Country Code" #define TR_VOICELANG "Voice Language" #define TR_UNITSSYSTEM "Units" @@ -967,6 +967,9 @@ #define TR_CRITICALALARM INDENT "Critical Alarm" #define TR_ENABLE_POPUP "Enable Popup" #define TR_DISABLE_POPUP "Disable Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Preset..." #define TR_PRESET "Preset" #define TR_MIRROR "Mirror" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 1109b4c30f..ab02eaec2f 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -592,8 +592,6 @@ #define TR_MODE INDENT"Modo" #define TR_NOFREEEXPO "No expo libre!" #define TR_NOFREEMIXER "No mezcla lib!" -#define TR_INSERTMIX "INSERTAR MIX" -#define TR_EDITMIX "EDITAR MIX " #define TR_SOURCE INDENT"Fuente" #define TR_WEIGHT "Cantidad" #define TR_EXPO TR("Expo","Exponencial") @@ -735,7 +733,6 @@ #define TR_MENULOGICALSWITCHES "AJTE.INTERUPTS." #define TR_MENUCUSTOMFUNC "AJTE. FUNCIONES" #define TR_MENUCUSTOMSCRIPTS "CUSTOM SCRIPTS" -#define TR_MENUCUSTOMSCRIPT "CUSTOM SCRIPT" #define TR_MENUTELEMETRY "TELEMETRIA" #define TR_MENUTEMPLATES "PLANTILLAS" #define TR_MENUSTAT "STATS" @@ -830,7 +827,7 @@ #define TR_SD_SIZE "Tamaño:" #define TR_TYPE INDENT "Tipo" #define TR_GLOBAL_VARS "Global Variables" -#define TR_GLOBAL_V "GLOBAL V." +#define TR_GVARS "GLOBAL V." #define TR_GLOBAL_VAR "Global Variable" #define TR_MENUGLOBALVARS "GLOBAL VARIABLES" #define TR_OWN "Propio" @@ -850,6 +847,7 @@ #define TR_FAILSAFE INDENT"Modo sgdad." #define TR_FAILSAFESET "AJUSTES SGDAD." #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Codigo Pais" #define TR_VOICELANG "Idioma voces" #define TR_UNITSSYSTEM "Unidades" @@ -893,6 +891,9 @@ #define TR_CRITICALALARM INDENT "Alarma Critica" #define TR_ENABLE_POPUP "Enable Popup" #define TR_DISABLE_POPUP "Disable Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Preset..." #define TR_PRESET "Preset" #define TR_MIRROR "Mirror" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index 9c1e2cddda..0e6494ef7e 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -592,8 +592,6 @@ #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") @@ -735,7 +733,6 @@ #define TR_MENULOGICALSWITCHES "CUSTOM SWITCHES" #define TR_MENUCUSTOMFUNC "CUSTOM FUNCTIONS" #define TR_MENUCUSTOMSCRIPTS "CUSTOM SCRIPTS" -#define TR_MENUCUSTOMSCRIPT "CUSTOM SCRIPT" #define TR_MENUTELEMETRY "TELEMETRY" #define TR_MENUTEMPLATES "TEMPLATES" #define TR_MENUSTAT "STATS" @@ -830,7 +827,7 @@ #define TR_SD_SIZE "Size:" #define TR_TYPE INDENT "Type" #define TR_GLOBAL_VARS "Global Variables" -#define TR_GLOBAL_V "GLOBAL V." +#define TR_GVARS "GLOBAL V." #define TR_GLOBAL_VAR "Global Variable" #define TR_MENUGLOBALVARS "GLOBAL VARIABLES" #define TR_OWN "Own" @@ -850,6 +847,7 @@ #define TR_FAILSAFE INDENT "Failsafe mode" #define TR_FAILSAFESET "FAILSAFE SETTINGS" #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Country Code" #define TR_VOICELANG "Voice Language" #define TR_UNITSSYSTEM "Units" @@ -893,6 +891,9 @@ #define TR_CRITICALALARM INDENT "Critical Alarm" #define TR_ENABLE_POPUP "Enable Popup" #define TR_DISABLE_POPUP "Disable Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Preset..." #define TR_PRESET "Preset" #define TR_MIRROR "Mirror" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index b48dc3a871..0d1cd151a5 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -626,8 +626,6 @@ #define TR_MODE INDENT "Mode" #define TR_NOFREEEXPO "Max expos atteint!" #define TR_NOFREEMIXER "Max mixages atteint!" -#define TR_INSERTMIX "INSERER MIXAGE" -#define TR_EDITMIX "EDITER MIXAGE" #define TR_SOURCE INDENT "Source" #define TR_WEIGHT "Ratio" #define TR_EXPO TR("Expo", "Exponentiel") @@ -772,7 +770,6 @@ #define TR_MENULOGICALSWITCHES TR("INTERS LOG.", "INTERS LOGIQUES") #define TR_MENUCUSTOMFUNC TR("FONCTIONS SPEC.", "FONCTIONS SPECIALES") #define TR_MENUCUSTOMSCRIPTS "SCRIPTS PERSOS" -#define TR_MENUCUSTOMSCRIPT "SCRIPT PERSO" #define TR_MENUTELEMETRY "TELEMESURE" #define TR_MENUTEMPLATES "GABARITS" #define TR_MENUSTAT TR("STATS", "STATISTIQUES") @@ -867,7 +864,7 @@ #define TR_SD_SIZE "Taille:" #define TR_TYPE INDENT "Type" #define TR_GLOBAL_VARS "Variables Globales" -#define TR_GLOBAL_V "V. GLOBALES" +#define TR_GVARS "V. GLOBALES" #define TR_GLOBAL_VAR "Variable globale" #define TR_MENUGLOBALVARS "VARIABLES GLOBALES" #define TR_OWN "Pers" @@ -887,6 +884,7 @@ #define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Type failsafe") #define TR_FAILSAFESET "REGLAGES FAILSAFE" #define TR_MENUSENSOR "CAPTEUR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE TR("Zone géo.","Zone géographique") #define TR_VOICELANG TR("Langue voix", "Langue annonces vocales") #define TR_UNITSSYSTEM "Unités" @@ -930,6 +928,9 @@ #define TR_CRITICALALARM INDENT "Alarme critique" #define TR_ENABLE_POPUP "Activer Popup" #define TR_DISABLE_POPUP "Désactiver Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Courbe standard..." #define TR_PRESET "Pente" #define TR_MIRROR "Miroir" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 5f6ccf83a6..e3d5c8d561 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -629,8 +629,6 @@ #define TR_MODE INDENT"Modo" #define TR_NOFREEEXPO "Expo pieni!" #define TR_NOFREEMIXER "Mixer pieni!" -#define TR_INSERTMIX "INSER. MIX" -#define TR_EDITMIX "MOD. MIX" #define TR_SOURCE INDENT"Sorg." #define TR_WEIGHT "Peso" #define TR_EXPO "Espo" @@ -779,7 +777,6 @@ #define TR_MENULOGICALSWITCHES TR("INTER. LOGICI","INTERRUTTORI LOGICI") #define TR_MENUCUSTOMFUNC TR("FUNZ. SPECIALI","FUNZIONI SPECIALI") #define TR_MENUCUSTOMSCRIPTS "SCRIPTS UTENTE" -#define TR_MENUCUSTOMSCRIPT "SCRIPT UTENTE" #define TR_MENUTELEMETRY "TELEMETRIA" #define TR_MENUTEMPLATES "ESEMPI GUIDA" #define TR_MENUSTAT "STATO" @@ -807,11 +804,11 @@ #define TR_VOLTAGE TR(INDENT "Voltagg.",INDENT "Voltaggio") #define TR_CURRENT TR(INDENT "Corrente",INDENT "Corrente") #define TR_SELECT_MODEL "Scegli Memo." -#define TR_CREATE_CATEGORY "Create Category" -#define TR_RENAME_CATEGORY "Rename Category" -#define TR_DELETE_CATEGORY "Delete Category" +#define TR_CREATE_CATEGORY "Create Category" +#define TR_RENAME_CATEGORY "Rename Category" +#define TR_DELETE_CATEGORY "Delete Category" #define TR_CREATE_MODEL "Crea Modello" -#define TR_DUPLICATE_MODEL "Duplicate Model" +#define TR_DUPLICATE_MODEL "Duplicate Model" #define TR_COPY_MODEL "Copia Modello" #define TR_MOVE_MODEL "Sposta Modello" #define TR_BACKUP_MODEL "Salva Modello" @@ -878,7 +875,7 @@ #define TR_SD_SIZE "Dimens:" #define TR_TYPE INDENT "Tipo" #define TR_GLOBAL_VARS "Variabili Globali" -#define TR_GLOBAL_V "V.GLOBALI" +#define TR_GVARS "V.GLOBALI" #define TR_GLOBAL_VAR "Variabile globale" #define TR_MENUGLOBALVARS "VARIABILI GLOBALI" #define TR_OWN "Fase" @@ -898,6 +895,7 @@ #define TR_FAILSAFE "Modo failsafe" #define TR_FAILSAFESET TR("FAILSAFE","IMPOSTAZIONI FAILSAFE") #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE TR("Codice Paese","Standard 2.4Ghz") #define TR_VOICELANG "Lingua Voce" #define TR_UNITSSYSTEM "Unità" @@ -941,6 +939,9 @@ #define TR_CRITICALALARM INDENT "Allarme Critico" #define TR_ENABLE_POPUP "Abilita Popup" #define TR_DISABLE_POPUP "Disabilita Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Preimpostate..." #define TR_PRESET "Preimpostate" #define TR_MIRROR "Mirror" @@ -1069,7 +1070,7 @@ #define TR_SCALE "Scala" #define TR_VIEW_CHANNELS "Vedi Canali" #define TR_VIEW_NOTES "Vedi Note" -#define TR_MODEL_SELECT "Model Select" +#define TR_MODEL_SELECT "Model Select" #define TR_MODS_FORBIDDEN "Modifica proibita!" #define TR_UNLOCKED "Sbloccato" #define TR_ID "ID" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 51d9e7e3ed..1e59c11159 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -641,8 +641,6 @@ #define TR_MODE INDENT "Mode" #define TR_NOFREEEXPO "Geen vrije expo!" #define TR_NOFREEMIXER "Geen vrije 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", "Exponentieel") @@ -798,7 +796,6 @@ #define TR_MENULOGICALSWITCHES "LOGISCHE SCHAKELAARS" #define TR_MENUCUSTOMFUNC TR("SPEC.-FUNKTIES", "SPECIALE-FUNKTIES") #define TR_MENUCUSTOMSCRIPTS "LUA-SCRIPTS" -#define TR_MENUCUSTOMSCRIPT "LUA-SCRIPT" #define TR_MENUTELEMETRY "TELEMETRIE" #define TR_MENUTEMPLATES "SJABLONEN" #define TR_MENUSTAT "STAT" @@ -897,7 +894,7 @@ #define TR_SD_SIZE "Grootte:" #define TR_TYPE INDENT "Type" #define TR_GLOBAL_VARS "Globale Variabelen" -#define TR_GLOBAL_V "GLOBALE V." +#define TR_GVARS "GLOBALE V." #define TR_GLOBAL_VAR "Globale Variabele" #define TR_MENUGLOBALVARS "GLOBALE VARIABELEN" #define TR_OWN "Eigen" @@ -917,6 +914,7 @@ #define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe Modus") #define TR_FAILSAFESET "Failsafe instellen" #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Landcode" #define TR_VOICELANG "Taal" #define TR_UNITSSYSTEM "Eenheden" @@ -960,6 +958,9 @@ #define TR_CRITICALALARM INDENT "Kritiek Alarm" #define TR_ENABLE_POPUP "Inschakelen Popups" #define TR_DISABLE_POPUP "Uitschakelen Popups" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Preset..." #define TR_PRESET "Preset" #define TR_MIRROR "Spiegelen" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 7ca2baace9..01913a61e9 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -630,8 +630,6 @@ #define TR_MODE INDENT "Tryb" #define TR_NOFREEEXPO "BrakWoln.Expo!" #define TR_NOFREEMIXER "BrakWoln.Mixów!" -#define TR_INSERTMIX "WSTAW MIX" -#define TR_EDITMIX "EDYTUJ MIX" #define TR_SOURCE INDENT "Źródło" #define TR_WEIGHT "Waga " #define TR_EXPO TR("Expo", "Exponential") @@ -780,7 +778,6 @@ #define TR_MENULOGICALSWITCHES TR("PRZEŁ. LOG.", "PRZEŁ. LOGICZNE") #define TR_MENUCUSTOMFUNC "FUNKCJE SPECJALNE" #define TR_MENUCUSTOMSCRIPTS "WŁASNE SKRYPTY" -#define TR_MENUCUSTOMSCRIPT "WŁASNY SKRYPT" #define TR_MENUTELEMETRY "TELEMETRIA" #define TR_MENUTEMPLATES "SZABLONY" #define TR_MENUSTAT "STAT" @@ -879,7 +876,7 @@ #define TR_SD_SIZE "Wielkość:" #define TR_TYPE INDENT TR_SD_TYPE #define TR_GLOBAL_VARS "Zmienne Globalne" -#define TR_GLOBAL_V "Zmien.Glob." +#define TR_GVARS "Zmien.Glob." #define TR_GLOBAL_VAR "Zmienna Globalna" #define TR_MENUGLOBALVARS "ZMIENNE GLOBALNE" #define TR_OWN "Własność" @@ -899,6 +896,7 @@ #define TR_FAILSAFE TR(INDENT"Failsafe",INDENT"Tryb Failsafe") #define TR_FAILSAFESET "USTAWIENIE FAILSAFE" #define TR_MENUSENSOR "CZUJNIK" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Kod regionu" #define TR_VOICELANG "Język głosu" #define TR_UNITSSYSTEM "Jednostki" @@ -942,6 +940,9 @@ #define TR_CRITICALALARM INDENT "Alarm krytyczny" #define TR_ENABLE_POPUP "Aktywuj Popup" #define TR_DISABLE_POPUP "Wyłącz Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Predef..." #define TR_PRESET "Predef." #define TR_MIRROR "Lustro" diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 505c79e26b..6bee761945 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -592,8 +592,6 @@ #define TR_MODE INDENT"Modo" #define TR_NOFREEEXPO "No free expo!" #define TR_NOFREEMIXER "No free mixer!" -#define TR_INSERTMIX "INSERIR MIX" -#define TR_EDITMIX "EDITAR MIX" #define TR_SOURCE INDENT"Fonte" #define TR_WEIGHT "Quantia" #define TR_EXPO "Exponen" @@ -735,7 +733,6 @@ #define TR_MENULOGICALSWITCHES "CHAVES ESPECIAIS" #define TR_MENUCUSTOMFUNC "FUNCAO ESPECIAL" #define TR_MENUCUSTOMSCRIPTS "CUSTOM SCRIPTS" -#define TR_MENUCUSTOMSCRIPT "CUSTOM SCRIPT" #define TR_MENUTELEMETRY "TELEMETRIA" #define TR_MENUTEMPLATES "MODELOS" #define TR_MENUSTAT "REGISTROS" @@ -759,11 +756,11 @@ #define TR_VOLTAGE INDENT"Volts" #define TR_CURRENT INDENT"Amperes" #define TR_SELECT_MODEL "Selec. Modelo" -#define TR_CREATE_CATEGORY "Create Category" -#define TR_RENAME_CATEGORY "Rename Category" -#define TR_DELETE_CATEGORY "Delete Category" +#define TR_CREATE_CATEGORY "Create Category" +#define TR_RENAME_CATEGORY "Rename Category" +#define TR_DELETE_CATEGORY "Delete Category" #define TR_CREATE_MODEL "Criar Modelo" -#define TR_DUPLICATE_MODEL "Duplicate Model" +#define TR_DUPLICATE_MODEL "Duplicate Model" #define TR_COPY_MODEL "Copy Model" #define TR_MOVE_MODEL "Move Model" #define TR_BACKUP_MODEL "Salvar Modelo" @@ -830,7 +827,7 @@ #define TR_SD_SIZE "Tamanho" #define TR_TYPE INDENT "Tipe" #define TR_GLOBAL_VARS "Variaveis" -#define TR_GLOBAL_V "GLOBAL V." +#define TR_GVARS "GLOBAL V." #define TR_GLOBAL_VAR "Global Variable" #define TR_MENUGLOBALVARS "VARIAVEIS" #define TR_OWN "Propr." @@ -850,6 +847,7 @@ #define TR_FAILSAFE "Failsafe mode" #define TR_FAILSAFESET "FAILSAFE SETTINGS" #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Country Code" #define TR_VOICELANG "Voice Language" #define TR_UNITSSYSTEM "Units" @@ -893,6 +891,9 @@ #define TR_CRITICALALARM INDENT "Critical Alarm" #define TR_ENABLE_POPUP "Enable Popup" #define TR_DISABLE_POPUP "Disable Popup" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Preset..." #define TR_PRESET "Preset" #define TR_MIRROR "Mirror" @@ -1021,7 +1022,7 @@ #define TR_SCALE "Scale" #define TR_VIEW_CHANNELS "View Channels" #define TR_VIEW_NOTES "View Notes" -#define TR_MODEL_SELECT "Model Select" +#define TR_MODEL_SELECT "Model Select" #define TR_MODS_FORBIDDEN "Modifications forbidden!" #define TR_UNLOCKED "Unlocked" #define TR_ID "ID" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index fb2ebe4cf4..edb05abc9b 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -651,8 +651,6 @@ #define TR_MODE INDENT"Läge" #define TR_NOFREEEXPO "Expo saknas!" #define TR_NOFREEMIXER "Mixer saknas!" -#define TR_INSERTMIX "Addera Mix" -#define TR_EDITMIX "Redigera Mix" #define TR_SOURCE INDENT"Källa" #define TR_WEIGHT "Vikt" #define TR_EXPO TR("Expo","Exponentiell") @@ -803,7 +801,6 @@ #define TR_MENULOGICALSWITCHES "LOGISKA BRYTARE" #define TR_MENUCUSTOMFUNC "BRYTARFUNKTIONER" #define TR_MENUCUSTOMSCRIPTS "SPECIALKOD" -#define TR_MENUCUSTOMSCRIPT "SPECIALKOD" #define TR_MENUTELEMETRY "TELEMETRI" #define TR_MENUTEMPLATES "MALLAR" #define TR_MENUSTAT "STATISTIK" @@ -903,7 +900,7 @@ #define TR_SD_SIZE "Strl:" #define TR_TYPE INDENT "Typ " #define TR_GLOBAL_VARS "Globala Variabler" -#define TR_GLOBAL_V "GLOBAL V." +#define TR_GVARS "GLOBAL V." #define TR_GLOBAL_VAR "Global Variabel" #define TR_MENUGLOBALVARS "GLOBALA VARIABLER" #define TR_OWN "Egen" @@ -923,6 +920,7 @@ #define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafeläge") #define TR_FAILSAFESET "FailsafeInställning" #define TR_MENUSENSOR "SENSOR" +#define TR_SENSOR "SENSOR" #define TR_COUNTRYCODE "Landskod" #define TR_VOICELANG "Röstspråk" #define TR_UNITSSYSTEM "Enheter" @@ -966,6 +964,9 @@ #define TR_CRITICALALARM INDENT "Kritiskt alarm" #define TR_ENABLE_POPUP "Slå på Dialog" #define TR_DISABLE_POPUP "Slå av Dialog" +#define TR_POPUP "Popup" +#define TR_MIN "Min" +#define TR_MAX "Max" #define TR_CURVE_PRESET "Lutning..." #define TR_PRESET "Lutning" #define TR_MIRROR "Spegla" diff --git a/radio/util/commit-tests.sh b/radio/util/commit-tests.sh index 311a640ef3..20754bcf68 100755 --- a/radio/util/commit-tests.sh +++ b/radio/util/commit-tests.sh @@ -36,7 +36,6 @@ make -j2 gtests rm -rf * cmake -DCMAKE_BUILD_TYPE=Debug -DPCB=HORUS -DHELI=NO -DUSB=SERIAL -DCLI=YES -DDEBUG=YES .. make -j2 firmware.bin -cmake -DCMAKE_BUILD_TYPE=Debug -DPCB=HORUS -DHELI=NO -DUSB=SERIAL -DCLI=NO -DDEBUG=YES .. make -j2 simu #make gtests #./gtests diff --git a/radio/util/img2lbm.py b/radio/util/img2lbm.py index 56bc9e1ffc..dd88a8ecaa 100755 --- a/radio/util/img2lbm.py +++ b/radio/util/img2lbm.py @@ -48,6 +48,15 @@ with open(sys.argv[2], "w") as f: pixel = image.pixel(x, y) f.write("0x%1x%1x%1x%1x," % (Qt.qAlpha(pixel) // 16, Qt.qRed(pixel) // 16, Qt.qGreen(pixel) // 16, Qt.qBlue(pixel) // 16)) f.write("\n") + elif what == "5/6/5": + colors = [] + writeSize(f, width, height) + for y in range(height): + for x in range(width): + pixel = image.pixel(x, y) + val = ((Qt.qRed(pixel) >> 3) << 11) + ((Qt.qGreen(pixel) >> 2) << 5) + ((Qt.qBlue(pixel) >> 3) << 0) + f.write("%d,%d," % (val % 256, val // 256)) + f.write("\n") elif what == "5/6/5/8": colors = [] writeSize(f, width, height) @@ -55,8 +64,7 @@ with open(sys.argv[2], "w") as f: for x in range(width): pixel = image.pixel(x, y) val = ((Qt.qRed(pixel) >> 3) << 11) + ((Qt.qGreen(pixel) >> 2) << 5) + ((Qt.qBlue(pixel) >> 3) << 0) - # f.write("%d,%d,%d," % (val%256, val/256, Qt.qAlpha(pixel) >> 4)) - f.write("%d,%d," % (val % 256, val // 256)) + f.write("%d,%d,%d," % (val % 256, val // 256, Qt.qAlpha(pixel))) f.write("\n") elif what == "4bits": colors = []