From c9fb1f32ab9e388fef36964c931f0e04ec28dbed Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Fri, 28 Jul 2023 12:34:57 +0200 Subject: [PATCH 01/35] feat: flex ADC input --- radio/src/boards/generic_stm32/switches.cpp | 72 ++---- radio/src/dataconstants.h | 16 +- radio/src/datastructs_private.h | 1 + radio/src/gui/128x64/model_setup.cpp | 12 +- radio/src/gui/128x64/view_main.cpp | 4 +- radio/src/gui/212x64/model_setup.cpp | 10 +- radio/src/gui/212x64/radio_calibration.cpp | 4 +- radio/src/gui/212x64/view_main.cpp | 4 +- radio/src/gui/colorlcd/hw_inputs.cpp | 35 ++- radio/src/gui/colorlcd/layouts/sliders.cpp | 2 +- radio/src/gui/colorlcd/preflight_checks.cpp | 8 +- radio/src/gui/colorlcd/radio_diaganas.cpp | 10 +- .../src/gui/colorlcd/view_main_decoration.cpp | 2 +- .../src/gui/common/stdlcd/radio_hardware.cpp | 10 +- radio/src/gui/gui_common.cpp | 12 - radio/src/hal/CMakeLists.txt | 6 + radio/src/hal/adc_driver.cpp | 14 +- radio/src/hal/adc_driver.h | 3 +- radio/src/hal/switch_driver.cpp | 213 ++++++++++++++++++ radio/src/hal/switch_driver.h | 18 ++ radio/src/logs.cpp | 8 +- radio/src/lua/api_general.cpp | 1 + radio/src/mixer.cpp | 66 +++--- radio/src/opentx.cpp | 11 +- radio/src/opentx.h | 19 +- radio/src/opentx_constants.h | 15 +- radio/src/simu.cpp | 9 +- .../storage/yaml/yaml_datastructs_128x64.cpp | 1 + .../storage/yaml/yaml_datastructs_funcs.cpp | 99 ++++++-- .../storage/yaml/yaml_datastructs_nv14.cpp | 3 +- .../src/storage/yaml/yaml_datastructs_t20.cpp | 1 + .../storage/yaml/yaml_datastructs_tpro.cpp | 1 + .../src/storage/yaml/yaml_datastructs_x10.cpp | 3 +- .../storage/yaml/yaml_datastructs_x12s.cpp | 3 +- .../src/storage/yaml/yaml_datastructs_x9d.cpp | 1 + .../src/storage/yaml/yaml_datastructs_x9e.cpp | 1 + .../storage/yaml/yaml_datastructs_x9lite.cpp | 1 + .../storage/yaml/yaml_datastructs_xlites.cpp | 1 + radio/src/strhelpers.cpp | 17 +- radio/src/switches.cpp | 69 +++--- radio/src/switches.h | 4 + .../common/arm/stm32/stm32_switch_driver.cpp | 66 ------ .../common/arm/stm32/stm32_switch_driver.h | 13 -- radio/src/targets/horus/CMakeLists.txt | 1 + radio/src/targets/simu/opentxsimulator.cpp | 6 +- radio/src/targets/simu/switch_driver.cpp | 106 +++------ radio/src/tests/functions.cpp | 4 + radio/src/tests/switches.cpp | 164 +++++++++++--- radio/src/translations/cn.h | 2 +- radio/src/translations/cz.h | 2 +- radio/src/translations/da.h | 2 +- radio/src/translations/de.h | 2 +- radio/src/translations/en.h | 2 +- radio/src/translations/es.h | 2 +- radio/src/translations/fi.h | 2 +- radio/src/translations/fr.h | 2 +- radio/src/translations/he.h | 2 +- radio/src/translations/it.h | 2 +- radio/src/translations/jp.h | 2 +- radio/src/translations/nl.h | 2 +- radio/src/translations/pl.h | 2 +- radio/src/translations/pt.h | 2 +- radio/src/translations/se.h | 2 +- radio/src/translations/tw.h | 2 +- radio/util/hw_defs/generator.py | 18 ++ radio/util/hw_defs/hal_adc.py | 16 +- radio/util/hw_defs/hal_adc_inputs.jinja | 30 +-- radio/util/hw_defs/legacy_names.py | 4 + radio/util/hw_defs/pot_config.py | 164 +++++++------- radio/util/hw_defs/simu_switches.jinja | 2 +- radio/util/hw_defs/stm32_switches.jinja | 8 +- 71 files changed, 854 insertions(+), 570 deletions(-) create mode 100644 radio/src/hal/switch_driver.cpp diff --git a/radio/src/boards/generic_stm32/switches.cpp b/radio/src/boards/generic_stm32/switches.cpp index 5c72fb0ddf8..6946757cc6c 100644 --- a/radio/src/boards/generic_stm32/switches.cpp +++ b/radio/src/boards/generic_stm32/switches.cpp @@ -32,80 +32,34 @@ #include -void switchInit() +void boardInitSwitches() { _init_switches(); } -swconfig_t switchGetDefaultConfig() +SwitchHwPos boardSwitchGetPosition(uint8_t cat, uint8_t idx) { - return _switch_default_config; + return stm32_switch_get_position(&_switch_offsets[cat][idx]); } -switch_display_pos_t switchGetDisplayPosition(uint8_t idx) -{ - if (idx >= DIM(_switch_display)) - return {0, 0}; - - return _switch_display[idx]; -} - -uint8_t switchGetMaxSwitches() -{ - return n_switches; -} - -uint8_t getSwitchCount() -{ - int count = 0; - for (int i = 0; i < switchGetMaxSwitches(); ++i) { - if (SWITCH_EXISTS(i)) { - ++count; - } - } - return count; -} - -uint8_t switchGetMaxRow(uint8_t col) +const char* boardSwitchGetName(uint8_t cat, uint8_t idx) { - uint8_t lastrow = 0; - for (int i = 0; i < switchGetMaxSwitches(); ++i) { - if (SWITCH_EXISTS(i)) { - auto switch_display = switchGetDisplayPosition(i); - if (switch_display.col == col) - lastrow = switch_display.row > lastrow ? switch_display.row : lastrow; - } - } - return lastrow; + return _switch_offsets[cat][idx].name; } -uint8_t switchGetMaxFctSwitches() +SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx) { - return n_fct_switches; + return _switch_offsets[cat][idx].type; } -// returns state (0 / 1) of a specific switch position -uint32_t switchState(uint8_t pos_idx) -{ - auto d = div(pos_idx, 3); - if (d.quot >= n_total_switches) return 0; - return stm32_switch_get_state(&_switch_defs[d.quot], (SwitchHwPos)d.rem); -} +uint8_t boardGetMaxSwitches() { return n_switches; } +uint8_t boardGetMaxFctSwitches() { return n_fct_switches; } -SwitchHwPos switchGetPosition(uint8_t idx) -{ - if (idx >= n_total_switches) return SWITCH_HW_UP; - return stm32_switch_get_position(&_switch_defs[idx]); -} +swconfig_t boardSwitchGetDefaultConfig() { return _switch_default_config; } -const char* switchGetName(uint8_t idx) +switch_display_pos_t switchGetDisplayPosition(uint8_t idx) { - if (idx >= n_total_switches) return ""; - return _switch_defs[idx].name; -} + if (idx >= DIM(_switch_display)) return {0, 0}; -SwitchHwType switchGetHwType(uint8_t idx) -{ - if (idx >= n_total_switches) return SWITCH_HW_2POS; - return _switch_defs[idx].type; + return _switch_display[idx]; } diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 24bddd66f84..60af23702a0 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -392,19 +392,22 @@ enum PotsWarnMode { #if defined(COLORLCD) #define MAX_POTS 16 - #define MAX_AXIS 2 #else #define MAX_POTS 8 - #define MAX_AXIS 0 #endif #define MAX_VBAT 1 #define MAX_RTC_BAT 1 -#define MAX_ANALOG_INPUTS (MAX_STICKS + MAX_POTS + MAX_AXIS + MAX_VBAT + MAX_RTC_BAT) -#define MAX_CALIB_ANALOG_INPUTS (MAX_STICKS + MAX_POTS + MAX_AXIS) +#define MAX_ANALOG_INPUTS (MAX_STICKS + MAX_POTS + MAX_VBAT + MAX_RTC_BAT) +#define MAX_CALIB_ANALOG_INPUTS (MAX_STICKS + MAX_POTS) #define MAX_SWITCHES 20 + +#if !defined(MAX_FLEX_SWITCHES) +#define MAX_FLEX_SWITCHES 0 +#endif + #if defined(RADIO_T20) #define MAX_TRIMS 8 #else @@ -482,11 +485,6 @@ enum MixSources { MIXSRC_FIRST_POT SKIP, MIXSRC_LAST_POT SKIP = MIXSRC_FIRST_POT + MAX_POTS - 1, -#if MAX_AXIS > 0 - MIXSRC_FIRST_AXIS SKIP, - MIXSRC_LAST_AXIS SKIP = MIXSRC_FIRST_AXIS + MAX_AXIS - 1, -#endif - #if defined(IMU) MIXSRC_TILT_X, MIXSRC_TILT_Y, diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 9660466fb55..0582c28a43a 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -923,6 +923,7 @@ PACK(struct RadioData { CUST_ARRAY(slidersConfig, struct_sliderConfig, MAX_POTS, nullptr); potconfig_t potsConfig ARRAY(4,struct_potConfig,nullptr); swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); + CUST_ARRAY(flexSwitches, struct_flexSwitch, MAX_FLEX_SWITCHES, flex_sw_valid); EXTRA_GENERAL_FIELDS diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index ddcb6714ea4..fdc8ff04c25 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -344,7 +344,7 @@ inline uint8_t TIMER_ROW(uint8_t timer, uint8_t value) return HIDDEN_ROW; } -#define POT_WARN_ROWS PREFLIGHT_ROW(((g_model.potsWarnMode) ? adcGetMaxInputs(ADC_INPUT_POT) : (uint8_t)0)) +#define POT_WARN_ROWS PREFLIGHT_ROW(((g_model.potsWarnMode) ? adcGetMaxInputs(ADC_INPUT_FLEX) : (uint8_t)0)) #define TIMER_ROWS(x) \ 1, TIMER_ROW(x,0), \ @@ -592,7 +592,7 @@ void menuModelSetup(event_t event) PREFLIGHT_ROW(0), // Custom position for throttle warning value WARN_ROWS - uint8_t(NAVIGATION_LINE_BY_LINE | (adcGetInputOffset(ADC_INPUT_POT + 1) - 1)), // Center beeps + uint8_t(NAVIGATION_LINE_BY_LINE | (adcGetInputOffset(ADC_INPUT_FLEX + 1) - 1)), // Center beeps 0, // ADC Jitter filter @@ -899,7 +899,7 @@ void menuModelSetup(event_t event) if (attr) CHECK_INCDEC_MODELVAR_ZERO_CHECK( event, g_model.thrTraceSrc, - adcGetMaxInputs(ADC_INPUT_POT) + MAX_OUTPUT_CHANNELS, + adcGetMaxInputs(ADC_INPUT_FLEX) + MAX_OUTPUT_CHANNELS, isThrottleSourceAvailable); uint8_t idx = throttleSource2Source(g_model.thrTraceSrc); @@ -1078,7 +1078,7 @@ void menuModelSetup(event_t event) } if (g_model.potsWarnMode) { coord_t x = MODEL_SETUP_2ND_COLUMN+28; - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_POT); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (int i = 0; i < max_pots; ++i) { if (!IS_POT_SLIDER_AVAILABLE(i)) { @@ -1092,7 +1092,7 @@ void menuModelSetup(event_t event) flags |= INVERS; } if (max_pots > 3) { - lcdDrawText(x, y, getAnalogShortLabel(adcGetInputOffset(ADC_INPUT_POT) + i), flags); + lcdDrawText(x, y, getAnalogShortLabel(adcGetInputOffset(ADC_INPUT_FLEX) + i), flags); x = lcdNextPos + 1; } else { @@ -1106,7 +1106,7 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_BEEP_CENTER: { lcdDrawTextAlignedLeft(y, STR_BEEPCTR); - uint8_t input_max = adcGetMaxInputs(ADC_INPUT_MAIN) + adcGetMaxInputs(ADC_INPUT_POT); + uint8_t input_max = adcGetMaxInputs(ADC_INPUT_MAIN) + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < input_max; i++) { coord_t x = MODEL_SETUP_2ND_COLUMN + i*FW; LcdFlags flags = 0; diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index 8250bb595b3..fc343ec0366 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -81,8 +81,8 @@ void drawExternalAntennaAndRSSI() void drawPotsBars() { - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_POT); - uint8_t offset = adcGetInputOffset(ADC_INPUT_POT); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); + uint8_t offset = adcGetInputOffset(ADC_INPUT_FLEX); uint8_t configured_pots = 0; for (uint8_t i = 0; i < max_pots; i++) { diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 624d3cf3b08..5d2ceceac4d 100644 --- a/radio/src/gui/212x64/model_setup.cpp +++ b/radio/src/gui/212x64/model_setup.cpp @@ -538,7 +538,7 @@ void menuModelSetup(event_t event) SW_WARN_ROWS, // ITEM_MODEL_SETUP_SWITCHES_WARNING1 POT_WARN_ROWS, // ITEM_MODEL_SETUP_POTS_WARNING - uint8_t(NAVIGATION_LINE_BY_LINE | (adcGetInputOffset(ADC_INPUT_POT + 1) - 1)), // ITEM_MODEL_SETUP_BEEP_CENTER + uint8_t(NAVIGATION_LINE_BY_LINE | (adcGetInputOffset(ADC_INPUT_FLEX + 1) - 1)), // ITEM_MODEL_SETUP_BEEP_CENTER 0, // ITEM_MODEL_SETUP_USE_JITTER_FILTER @@ -977,7 +977,7 @@ void menuModelSetup(event_t event) } if (g_model.potsWarnMode) { coord_t x = MODEL_SETUP_2ND_COLUMN+28; - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_POT); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (int i = 0; i < max_pots; ++i) { if (!IS_POT_SLIDER_AVAILABLE(i)) { @@ -1011,8 +1011,8 @@ void menuModelSetup(event_t event) case ITEM_MODEL_SETUP_BEEP_CENTER: { lcdDrawTextAlignedLeft(y, STR_BEEPCTR); - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_POT); - uint8_t max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) + adcGetMaxInputs(ADC_INPUT_POT); + uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); + uint8_t max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) + adcGetMaxInputs(ADC_INPUT_FLEX); coord_t x = MODEL_SETUP_2ND_COLUMN; for (uint8_t i = 0; i < max_inputs; i++) { if ( i >= pot_offset && IS_POT_MULTIPOS(i - pot_offset) ) { @@ -1024,7 +1024,7 @@ void menuModelSetup(event_t event) flags = BLINK | INVERS; else if (ANALOG_CENTER_BEEP(i) || (attr && CURSOR_ON_LINE())) flags = INVERS; - if (adcGetMaxInputs(ADC_INPUT_POT) > 4 || i < pot_offset) { + if (adcGetMaxInputs(ADC_INPUT_FLEX) > 4 || i < pot_offset) { lcdDrawText(x, y, getAnalogShortLabel(i), flags); } else { diff --git a/radio/src/gui/212x64/radio_calibration.cpp b/radio/src/gui/212x64/radio_calibration.cpp index 33fb1241fc3..e3676ba39bd 100644 --- a/radio/src/gui/212x64/radio_calibration.cpp +++ b/radio/src/gui/212x64/radio_calibration.cpp @@ -31,8 +31,8 @@ void drawPotsBars() { // Optimization by Mike Blandford - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_POT); - uint8_t offset = adcGetInputOffset(ADC_INPUT_POT); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); + uint8_t offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t x = LCD_W / 2 - max_pots / 2 * BAR_SPACING + BAR_SPACING / 2, i = 0; diff --git a/radio/src/gui/212x64/view_main.cpp b/radio/src/gui/212x64/view_main.cpp index 6b78c4222ec..3a9a5a54026 100644 --- a/radio/src/gui/212x64/view_main.cpp +++ b/radio/src/gui/212x64/view_main.cpp @@ -183,8 +183,8 @@ static const coord_t _pot_slots[] = { void drawSliders() { uint8_t slot_idx = 0; - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_POT); - uint8_t offset = adcGetInputOffset(ADC_INPUT_POT); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); + uint8_t offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_pots; i++) { diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index 2bc899213bb..6e660d20c8e 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -83,7 +83,7 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) } }); - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (int i = 0; i < max_pots; i++) { // TODO: check initialised ADC inputs instead! @@ -93,7 +93,7 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) // if (!globalData.flyskygimbals && (i >= (NUM_POTS - 2))) continue; // #endif auto line = newLine(&grid); - new StaticText(line, rect_t{}, adcGetInputLabel(ADC_INPUT_POT, i), 0, + new StaticText(line, rect_t{}, adcGetInputLabel(ADC_INPUT_FLEX, i), 0, COLOR_THEME_PRIMARY1); auto box = new FormWindow(line, rect_t{}); @@ -102,10 +102,10 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) auto box_obj = box->getLvObj(); lv_obj_set_style_flex_cross_place(box_obj, LV_FLEX_ALIGN_CENTER, 0); - new HWInputEdit(box, (char*)analogGetCustomLabel(ADC_INPUT_POT, i), + new HWInputEdit(box, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, i), LEN_ANA_NAME); new Choice( - box, rect_t{}, STR_POTTYPES, POT_NONE, POT_SLIDER_WITH_DETENT, + line, rect_t{}, STR_POTTYPES, FLEX_NONE, FLEX_SWITCH, [=]() -> int { return bfGet(g_eeGeneral.potsConfig, POT_CFG_BITS * i, POT_CFG_BITS); @@ -130,7 +130,7 @@ class SwitchDynamicLabel : public StaticText std::string label() { - std::string str(switchGetName(index)); + std::string str(switchGetCanonicalName(index)); return str + getSwitchPositionSymbol(lastpos); } @@ -164,13 +164,32 @@ HWSwitches::HWSwitches(Window* parent) : FormWindow(parent, rect_t{}) FlexGridLayout grid(col_three_dsc, row_dsc, 2); setFlexLayout(); - for (int i = 0; i < switchGetMaxSwitches(); i++) { + auto max_switches = switchGetMaxSwitches(); + for (int i = 0; i < max_switches; i++) { auto line = newLine(&grid); new SwitchDynamicLabel(line, i); - new HWInputEdit(line, (char*)switchGetCustomName(i), LEN_SWITCH_NAME); + + auto box = new FormWindow(line, rect_t{}); + box->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(4)); + + auto box_obj = box->getLvObj(); + lv_obj_set_style_flex_cross_place(box_obj, LV_FLEX_ALIGN_CENTER, 0); + + if (switchIsFlex(i)) { + auto channel = new Choice( + box, rect_t{}, 0, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, + [=]() -> int { return switchGetFlexConfig(i); }, + [=](int newValue) { switchConfigFlex(i, newValue); }); + channel->setAvailableHandler( + [=](int val) { return POT_CONFIG(val) == FLEX_SWITCH; }); + channel->setTextHandler([=](int val) -> std::string { + return adcGetInputLabel(ADC_INPUT_FLEX, val); + }); + } + new Choice( - line, rect_t{}, STR_SWTYPES, SWITCH_NONE, switchGetMaxType(i), + box, rect_t{}, STR_SWTYPES, SWITCH_NONE, switchGetMaxType(i), [=]() -> int { return SWITCH_CONFIG(i); }, [=](int newValue) { swconfig_t mask = (swconfig_t)SWITCH_CONFIG_MASK(i); diff --git a/radio/src/gui/colorlcd/layouts/sliders.cpp b/radio/src/gui/colorlcd/layouts/sliders.cpp index 08519a93ba2..799540de610 100644 --- a/radio/src/gui/colorlcd/layouts/sliders.cpp +++ b/radio/src/gui/colorlcd/layouts/sliders.cpp @@ -38,7 +38,7 @@ MainViewSlider::MainViewSlider(Window* parent, const rect_t& rect, void MainViewSlider::checkEvents() { Window::checkEvents(); - auto pot_idx = adcGetInputOffset(ADC_INPUT_POT) + idx; + auto pot_idx = adcGetInputOffset(ADC_INPUT_FLEX) + idx; int16_t newValue = calibratedAnalogs[pot_idx]; if (value != newValue) { value = newValue; diff --git a/radio/src/gui/colorlcd/preflight_checks.cpp b/radio/src/gui/colorlcd/preflight_checks.cpp index 12b946f7533..b3353dfee03 100644 --- a/radio/src/gui/colorlcd/preflight_checks.cpp +++ b/radio/src/gui/colorlcd/preflight_checks.cpp @@ -163,7 +163,7 @@ PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP) new SwitchWarnMatrix(line, rect_t{}); // Pots and sliders warning - if (adcGetMaxInputs(ADC_INPUT_POT) > 0) { + if (adcGetMaxInputs(ADC_INPUT_FLEX) > 0) { line = form->newLine(&grid); new StaticText(line, rect_t{}, STR_POTWARNINGSTATE, 0, COLOR_THEME_PRIMARY1); auto pots_wm = new Choice(line, rect_t{}, STR_PREFLIGHT_POTSLIDER_CHECK, 0, 2, @@ -218,7 +218,7 @@ SwitchWarnMatrix::SwitchWarnMatrix(Window* parent, const rect_t& r) : uint8_t btn_id = 0; for (uint8_t i = 0; i < MAX_SWITCHES; i++) { if (SWITCH_EXISTS(i)) { - setTextAndState(i); + setTextAndState(btn_id); btn_id++; } } @@ -332,7 +332,7 @@ CenterBeepsMatrix::CenterBeepsMatrix(Window* parent, const rect_t& r) : uint8_t btn_cnt = 0; auto max_sticks = adcGetMaxInputs(ADC_INPUT_MAIN); - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); max_analogs = max_sticks + max_pots; for (uint8_t i = 0; i < max_analogs; i++) { @@ -373,7 +373,7 @@ void CenterBeepsMatrix::setTextAndState(uint8_t btn_id) if (ana_idx[btn_id] < max_sticks) setText(btn_id, getAnalogShortLabel(ana_idx[btn_id])); else - setText(btn_id, getAnalogLabel(ADC_INPUT_POT, ana_idx[btn_id] - max_sticks)); + setText(btn_id, getAnalogLabel(ADC_INPUT_FLEX, ana_idx[btn_id] - max_sticks)); setChecked(btn_id); } diff --git a/radio/src/gui/colorlcd/radio_diaganas.cpp b/radio/src/gui/colorlcd/radio_diaganas.cpp index 9e93cc0d427..89dc34976af 100644 --- a/radio/src/gui/colorlcd/radio_diaganas.cpp +++ b/radio/src/gui/colorlcd/radio_diaganas.cpp @@ -71,7 +71,7 @@ class AnaViewWindow: public FormWindow { char s[10]; auto max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) - + adcGetMaxInputs(ADC_INPUT_POT); + + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) { if (i > adcGetMaxInputs(ADC_INPUT_MAIN) && !IS_POT_AVAILABLE(i - adcGetMaxInputs(ADC_INPUT_MAIN))) continue; @@ -316,7 +316,7 @@ class AnaFilteredDevViewWindow: public AnaViewWindow { AnaViewWindow(parent) { auto max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) - + adcGetMaxInputs(ADC_INPUT_POT); + + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) stats[i].clear(); @@ -325,7 +325,7 @@ class AnaFilteredDevViewWindow: public AnaViewWindow { void checkEvents() override { auto max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) - + adcGetMaxInputs(ADC_INPUT_POT); + + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) { stats[i].write(getAnalogValue(i)); @@ -419,7 +419,7 @@ class AnaMinMaxViewWindow: public AnaViewWindow { AnaViewWindow(parent) { auto max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) - + adcGetMaxInputs(ADC_INPUT_POT); + + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) minmax[i].clear(); @@ -437,7 +437,7 @@ class AnaMinMaxViewWindow: public AnaViewWindow { void checkEvents() override { auto max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) - + adcGetMaxInputs(ADC_INPUT_POT); + + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) { minmax[i].write(getAnalogValue(i)); diff --git a/radio/src/gui/colorlcd/view_main_decoration.cpp b/radio/src/gui/colorlcd/view_main_decoration.cpp index e7862d418ae..efe1d151116 100644 --- a/radio/src/gui/colorlcd/view_main_decoration.cpp +++ b/radio/src/gui/colorlcd/view_main_decoration.cpp @@ -145,7 +145,7 @@ void ViewMainDecoration::createSliders(Window* ml, Window* mr, Window* bl, Windo sliders[2] = new MainViewHorizontalSlider(br, 2); // TODO: check how many pots are configured instead - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); if (max_pots > 3) { // create containers for the sliders, so that they are at the borders of the display // on top of each other, when there are two sliders to display per side diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index c085e9c6a2b..48ecdf4cc5d 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -143,7 +143,7 @@ static void _init_menu_tab_array(uint8_t* tab, size_t len) tab[i] = idx < max_sticks ? 0 : HIDDEN_ROW; } - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (int i = ITEM_RADIO_HARDWARE_POT; i <= ITEM_RADIO_HARDWARE_POT_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_POT; tab[i] = idx < max_pots ? 1 : HIDDEN_ROW; @@ -485,13 +485,13 @@ void menuRadioHardware(event_t event) // draw hw name LcdFlags flags = menuHorizontalPosition < 0 ? attr : 0; lcdDrawText(INDENT_WIDTH, y, STR_CHAR_POT, flags); - lcdDrawText(lcdNextPos, y, adcGetInputLabel(ADC_INPUT_POT, idx), flags); + lcdDrawText(lcdNextPos, y, adcGetInputLabel(ADC_INPUT_FLEX, idx), flags); // draw custom name - if (analogHasCustomLabel(ADC_INPUT_POT, idx) || + if (analogHasCustomLabel(ADC_INPUT_FLEX, idx) || (attr && s_editMode > 0 && menuHorizontalPosition == 0)) { editName(HW_SETTINGS_COLUMN1, y, - (char*)analogGetCustomLabel(ADC_INPUT_POT, idx), LEN_ANA_NAME, event, + (char*)analogGetCustomLabel(ADC_INPUT_FLEX, idx), LEN_ANA_NAME, event, attr && menuHorizontalPosition == 0, 0, old_editMode); } else { lcdDrawMMM(HW_SETTINGS_COLUMN1, y, menuHorizontalPosition==0 ? attr : 0); @@ -500,7 +500,7 @@ void menuRadioHardware(event_t event) // pot config uint8_t potType = (g_eeGeneral.potsConfig & mask) >> shift; potType = editChoice(HW_SETTINGS_COLUMN2, y, "", STR_POTTYPES, potType, - POT_NONE, POT_SLIDER_WITH_DETENT, + FLEX_NONE, FLEX_SWITCH, menuHorizontalPosition == 1 ? attr : 0, event); g_eeGeneral.potsConfig &= ~mask; g_eeGeneral.potsConfig |= (potType << shift); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 5f784b6a488..ba26d2a11d2 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -198,11 +198,6 @@ bool isSourceAvailable(int source) return IS_POT_SLIDER_AVAILABLE(source - MIXSRC_FIRST_POT); } -#if MAX_AXIS > 0 - if (source >= MIXSRC_FIRST_AXIS && source <= MIXSRC_LAST_AXIS) - return source - MIXSRC_FIRST_AXIS < adcGetMaxInputs(ADC_INPUT_AXIS); -#endif - #if defined(PCBHORUS) && !defined(SPACEMOUSE) if (source >= MIXSRC_FIRST_SPACEMOUSE && source <= MIXSRC_LAST_SPACEMOUSE) return false; @@ -298,13 +293,6 @@ bool isSourceAvailableInInputs(int source) if (source >= MIXSRC_FIRST_POT && source <= MIXSRC_LAST_POT) return IS_POT_SLIDER_AVAILABLE(source - MIXSRC_FIRST_POT); -#if MAX_AXIS > 0 - if (source >= MIXSRC_FIRST_AXIS && source <= MIXSRC_LAST_AXIS) { - auto idx = source - MIXSRC_FIRST_AXIS; - return idx < adcGetMaxInputs(ADC_INPUT_AXIS); - } -#endif - #if defined(IMU) if (source == MIXSRC_TILT_X || source == MIXSRC_TILT_Y) return true; diff --git a/radio/src/hal/CMakeLists.txt b/radio/src/hal/CMakeLists.txt index ac7c8a2329f..856bbc9763d 100644 --- a/radio/src/hal/CMakeLists.txt +++ b/radio/src/hal/CMakeLists.txt @@ -7,8 +7,14 @@ set(SRC ${SRC} hal/module_port.cpp hal/adc_driver.cpp hal/key_driver.cpp + hal/switch_driver.cpp ) +if (FLEXSW) + # define the number of allowed flexible adc entries used as switch + add_definitions(-DMAX_FLEX_SWITCHES=${FLEXSW}) +endif() + include_directories(${FATFS_DIR} ${FATFS_DIR}/option) set(BOOTLOADER_SRC ${BOOTLOADER_SRC} diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 5dd4dc03070..7b00e10618b 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -74,7 +74,7 @@ bool adcRead() void adcCalibSetMidPoint() { uint8_t max_inputs = adcGetMaxCalibratedInputs(); - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_POT); + uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) { @@ -124,7 +124,7 @@ void adcCalibSetMinMax() { // get low and high vals for sticks and pots uint8_t max_input = adcGetMaxCalibratedInputs(); - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_POT); + uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_input; i++) { @@ -192,8 +192,8 @@ void adcCalibSetMinMax() static void disableUncalibratedXPots() { - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_POT); - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_POT); + uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_pots; i++) { if (IS_POT_MULTIPOS(i)) { @@ -311,7 +311,7 @@ uint16_t getBatteryVoltage() void getADC() { uint8_t max_analogs = adcGetMaxInputs(ADC_INPUT_ALL); - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_POT); + uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); #if defined(JITTER_MEASURE) if (JITTER_MEASURE_ACTIVE() && jitterResetTime < get_tmr10ms()) { @@ -436,7 +436,7 @@ uint8_t adcGetInputOffset(uint8_t type) uint8_t adcGetMaxCalibratedInputs() { - // ADC_INPUT_MAIN + ADC_INPUT_POT + ADC_INPUT_AXIS + // ADC_INPUT_MAIN + ADC_INPUT_FLEX + ADC_INPUT_AXIS return adcGetInputOffset(ADC_INPUT_VBAT); } @@ -467,7 +467,7 @@ const char* adcGetInputName(uint8_t idx) // find the proper input type while (_hal_adc_inputs[type].offset + _hal_adc_inputs[type].n_inputs <= idx) { - if (++type > ADC_INPUT_AXIS) return nullptr; + if (++type > ADC_INPUT_FLEX) return nullptr; } idx -= _hal_adc_inputs[type].offset; diff --git a/radio/src/hal/adc_driver.h b/radio/src/hal/adc_driver.h index bf414da3fab..86e76ca9ae5 100644 --- a/radio/src/hal/adc_driver.h +++ b/radio/src/hal/adc_driver.h @@ -37,8 +37,7 @@ enum { ADC_INPUT_MAIN=0, // gimbals / wheel + throttle - ADC_INPUT_POT, - ADC_INPUT_AXIS, + ADC_INPUT_FLEX, ADC_INPUT_VBAT, ADC_INPUT_RTC_BAT, ADC_INPUT_ALL, diff --git a/radio/src/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp new file mode 100644 index 00000000000..ef3a233ee75 --- /dev/null +++ b/radio/src/hal/switch_driver.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * 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 "switch_driver.h" + +#include "definitions.h" +#include "hal/adc_driver.h" + +#include "dataconstants.h" +#include "opentx_helpers.h" +#include "opentx.h" + +// Board API +void boardInitSwitches(); + +SwitchHwPos boardSwitchGetPosition(uint8_t cat, uint8_t idx); + +const char* boardSwitchGetName(uint8_t cat, uint8_t idx); +SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx); + +uint8_t boardGetMaxSwitches(); +uint8_t boardGetMaxFctSwitches(); + +swconfig_t boardSwitchGetDefaultConfig(); + +constexpr uint8_t _INVALID_ADC_CH = 0xFF; + +#define XSTR(x) STR(x) +#define STR(x) #x +#pragma message "MAX_FLEX_SWITCHES: " XSTR(MAX_FLEX_SWITCHES) + +static uint8_t _flex_switches[MAX_FLEX_SWITCHES]; + +void switchInit() +{ + memset(_flex_switches, _INVALID_ADC_CH, sizeof(_flex_switches)); + boardInitSwitches(); +} + +swconfig_t switchGetDefaultConfig() { return boardSwitchGetDefaultConfig(); } + +uint8_t switchGetMaxSwitches() +{ + return boardGetMaxSwitches() + MAX_FLEX_SWITCHES; +} + +uint8_t switchGetMaxFctSwitches() { return boardGetMaxFctSwitches(); } + +uint32_t switchState(uint8_t pos_idx) +{ + auto d = div(pos_idx, 3); + auto idx = (uint8_t)d.quot; + auto pos = (SwitchHwPos)d.rem; + + return switchGetPosition(idx) == pos; +} + +SwitchHwPos switchGetPosition(uint8_t sw_idx) +{ + auto idx = (int)sw_idx; + auto max_switches = boardGetMaxSwitches(); + if (idx < max_switches) { + return boardSwitchGetPosition(SWITCH_PHYSICAL, idx); + } + + idx -= max_switches; + if (MAX_FLEX_SWITCHES > 0) { + if (idx < MAX_FLEX_SWITCHES) { + auto channel = _flex_switches[idx]; + SwitchHwPos ret = SWITCH_HW_UP; + + if (channel != _INVALID_ADC_CH) { + uint16_t value = getAnalogValue(channel); + if (value > 3 * 1024) { + ret = SWITCH_HW_DOWN; + } else if (value >= 1024) { + ret = SWITCH_HW_MID; + } + } + + return ret; + } + + idx -= MAX_FLEX_SWITCHES; + } + + if (idx < boardGetMaxFctSwitches()) { + return boardSwitchGetPosition(SWITCH_FUNCTION, idx); + } + + return SWITCH_HW_UP; +} + +static const char * const _flex_sw_canon_names[] = { + "FL1", "FL2", "FL3", "FL4" +}; + +static_assert(DIM(_flex_sw_canon_names) >= MAX_FLEX_SWITCHES, + "Missing canonical name for flex switches"); + +const char* switchGetName(uint8_t sw_idx) +{ + auto idx = (int)sw_idx; + auto max_switches = boardGetMaxSwitches(); + if (idx < max_switches) { + return boardSwitchGetName(SWITCH_PHYSICAL, idx); + } + + idx -= max_switches; + if (MAX_FLEX_SWITCHES > 0) { + if (idx < MAX_FLEX_SWITCHES) { + return _flex_sw_canon_names[idx]; + } + + idx -= MAX_FLEX_SWITCHES; + } + + if (idx < boardGetMaxFctSwitches()) { + return boardSwitchGetName(SWITCH_FUNCTION, idx); + } + + return nullptr; +} + +SwitchHwType switchGetHwType(uint8_t sw_idx) +{ + auto idx = (int)sw_idx; + auto max_switches = boardGetMaxSwitches(); + if (idx < max_switches) { + return boardSwitchGetType(SWITCH_PHYSICAL, idx); + } + + idx -= max_switches; + if (idx < MAX_FLEX_SWITCHES) { + return SWITCH_HW_3POS; + } + + return SWITCH_HW_2POS; +} + +bool switchIsFlex(uint8_t idx) +{ + auto max_switches = boardGetMaxSwitches(); + return idx >= max_switches && idx < max_switches + MAX_FLEX_SWITCHES; +} + +void switchConfigFlex_raw(uint8_t idx, int8_t channel) +{ + if (!MAX_FLEX_SWITCHES || idx > MAX_FLEX_SWITCHES) return; + if ((int)channel >= (int)adcGetMaxInputs(ADC_INPUT_FLEX)) return; + + auto& sw_channel = _flex_switches[idx]; + if (channel < 0) { + sw_channel = _INVALID_ADC_CH; + } else if (POT_CONFIG((uint8_t)channel) == FLEX_SWITCH) { + sw_channel = (uint8_t)channel; + } +} + +void switchConfigFlex(uint8_t idx, int8_t channel) +{ + auto max_switches = boardGetMaxSwitches(); + if (idx < max_switches) return; + idx -= max_switches; + switchConfigFlex_raw(idx, channel); +} + +int8_t switchGetFlexConfig_raw(uint8_t idx) +{ + if (!MAX_FLEX_SWITCHES || idx > MAX_FLEX_SWITCHES) return _INVALID_ADC_CH; + return (int8_t)_flex_switches[idx]; +} + +int8_t switchGetFlexConfig(uint8_t idx) +{ + auto max_switches = boardGetMaxSwitches(); + if (idx < max_switches) return _INVALID_ADC_CH; + idx -= max_switches; + return switchGetFlexConfig_raw(idx); +} + +bool switchIsFlexValid_raw(uint8_t sw_idx) +{ + auto idx = (int)sw_idx; + return MAX_FLEX_SWITCHES > 0 && idx < MAX_FLEX_SWITCHES && + _flex_switches[idx] != _INVALID_ADC_CH; +} + +bool switchIsFlexValid(uint8_t idx) +{ + auto max_switches = boardGetMaxSwitches(); + if (idx < max_switches) return false; + idx -= max_switches; + return switchIsFlexValid_raw(idx); +} diff --git a/radio/src/hal/switch_driver.h b/radio/src/hal/switch_driver.h index 149d01b38fd..ea107ef91e3 100644 --- a/radio/src/hal/switch_driver.h +++ b/radio/src/hal/switch_driver.h @@ -36,6 +36,11 @@ enum SwitchHwPos { SWITCH_HW_DOWN, }; +enum SwitchCategory { + SWITCH_PHYSICAL=0, + SWITCH_FUNCTION, +}; + #define SWITCH_HW_INVERTED 1 // init hardware for switches @@ -63,6 +68,19 @@ struct switch_display_pos_t { switch_display_pos_t switchGetDisplayPosition(uint8_t idx); +// Configure Flex switch (using unified switch index) +void switchConfigFlex(uint8_t idx, int8_t channel); +int8_t switchGetFlexConfig(uint8_t idx); + +bool switchIsFlex(uint8_t idx); +bool switchIsFlexValid(uint8_t idx); + +// "Raw" variants indexing only flex switches (used for storage) +void switchConfigFlex_raw(uint8_t idx, int8_t channel); +int8_t switchGetFlexConfig_raw(uint8_t idx); +bool switchIsFlexValid_raw(uint8_t idx); + + // The functions bellow support regular as well as customizable switches. // // Regular switches are indexed from `0` to `switchGetMaxSwitches() - 1` diff --git a/radio/src/logs.cpp b/radio/src/logs.cpp index 7d8c67d6cfd..703fc8f1b05 100644 --- a/radio/src/logs.cpp +++ b/radio/src/logs.cpp @@ -227,10 +227,10 @@ void writeHeader() f_putc(',', &g_oLogFile); } - n_inputs = adcGetMaxInputs(ADC_INPUT_POT); + n_inputs = adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < n_inputs; i++) { if (!IS_POT_AVAILABLE(i)) continue; - const char* p = analogGetCanonicalName(ADC_INPUT_POT, i); + const char* p = analogGetCanonicalName(ADC_INPUT_FLEX, i); while (*p) { f_putc(*(p++), &g_oLogFile); } f_putc(',', &g_oLogFile); } @@ -367,8 +367,8 @@ void logsWrite() f_printf(&g_oLogFile, "%d,", calibratedAnalogs[inputMappingConvertMode(offset + i)]); } - n_inputs = adcGetMaxInputs(ADC_INPUT_POT); - offset = adcGetInputOffset(ADC_INPUT_POT); + n_inputs = adcGetMaxInputs(ADC_INPUT_FLEX); + offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t i = 0; i < n_inputs; i++) { if (IS_POT_AVAILABLE(i)) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 83cec454ca8..d25971a36eb 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -466,6 +466,7 @@ bool luaFindFieldByName(const char * name, LuaField & field, unsigned int flags) return true; // check switches from 'sa' to 'sz' + // TODO: does not work with function switches! if (len == 2 && name[0] == 's' && name[1] >= 'a' && name[1] <= 'z') { auto c = name[1] - 'a' + 'A'; auto sw_idx = switchLookupIdx(c); diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 3e17919678d..cafe117d1f8 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -296,6 +296,18 @@ int16_t applyLimits(uint8_t channel, int32_t value) return ofs; } +static const getvalue_t _switch_2pos_lookup[] = { + -1024, // SWITCH_HW_UP + +1024, // SWITCH_HW_MID + +1024, // SWITCH_HW_DOWN +}; + +static const getvalue_t _switch_3pos_lookup[] = { + -1024, // SWITCH_HW_UP + 0, // SWITCH_HW_MID + +1024, // SWITCH_HW_DOWN +}; + // TODO same naming convention than the drawSource // *valid added to return status to Lua for invalid sources getvalue_t getValue(mixsrc_t i, bool* valid) @@ -329,23 +341,12 @@ getvalue_t getValue(mixsrc_t i, bool* valid) } else if (i <= MIXSRC_LAST_POT) { i -= MIXSRC_FIRST_POT; - if (i >= adcGetMaxInputs(ADC_INPUT_POT)) { - if (valid != nullptr) *valid = false; - return 0; - } - return calibratedAnalogs[i + adcGetInputOffset(ADC_INPUT_POT)]; - } - -#if MAX_AXIS > 0 - else if (i <= MIXSRC_LAST_AXIS) { - i -= MIXSRC_FIRST_AXIS; - if (i >= adcGetMaxInputs(ADC_INPUT_AXIS)) { + if (i >= adcGetMaxInputs(ADC_INPUT_FLEX)) { if (valid != nullptr) *valid = false; return 0; } - return calibratedAnalogs[i + adcGetInputOffset(ADC_INPUT_AXIS)]; + return calibratedAnalogs[i + adcGetInputOffset(ADC_INPUT_FLEX)]; } -#endif #if defined(IMU) else if (i == MIXSRC_TILT_X) { @@ -383,31 +384,30 @@ getvalue_t getValue(mixsrc_t i, bool* valid) auto trim_value = getTrimValue(mixerCurrentFlightMode, i); return calc1000toRESX((int16_t)8 * trim_value); } -#if defined(FUNCTION_SWITCHES) - else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_REGULAR_SWITCH) { - mixsrc_t sw = i - MIXSRC_FIRST_SWITCH; - if (SWITCH_EXISTS(sw)) { - return (switchState(3*sw) ? -1024 : (IS_CONFIG_3POS(sw) && switchState(3*sw+1) ? 0 : 1024)); - } - else { - if (valid != nullptr) *valid = false; - return 0; - } - } else if (i >= MIXSRC_FIRST_FS_SWITCH && i <= MIXSRC_LAST_SWITCH) { - return getFSLogicalState(i - MIXSRC_FIRST_SWITCH - switchGetMaxSwitches()) ? +1024 : -1024; - } -#else else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_SWITCH) { - mixsrc_t sw = i - MIXSRC_FIRST_SWITCH; - if (SWITCH_EXISTS(sw)) { - return (switchState(3*sw) ? -1024 : (IS_CONFIG_3POS(sw) && switchState(3*sw+1) ? 0 : 1024)); + auto sw_idx = (uint8_t)(i - MIXSRC_FIRST_SWITCH); +#if defined(FUNCTION_SWITCHES) + auto max_reg_switches = switchGetMaxSwitches(); + if (sw_idx >= max_reg_switches) { + auto fct_idx = sw_idx - max_reg_switches; + auto max_fct_switches = switchGetMaxFctSwitches(); + if (fct_idx < max_fct_switches) { + return _switch_2pos_lookup[getFSLogicalState(fct_idx)]; + } } - else { +#endif + auto sw_cfg = (SwitchConfig)SWITCH_CONFIG(sw_idx); + switch(sw_cfg) { + case SWITCH_NONE: if (valid != nullptr) *valid = false; return 0; + case SWITCH_TOGGLE: + case SWITCH_2POS: + return _switch_2pos_lookup[switchGetPosition(sw_idx)]; + case SWITCH_3POS: + return _switch_3pos_lookup[switchGetPosition(sw_idx)]; } } -#endif else if (i <= MIXSRC_LAST_LOGICAL_SWITCH) { return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + i - MIXSRC_FIRST_LOGICAL_SWITCH) ? 1024 : -1024; @@ -503,7 +503,7 @@ void evalInputs(uint8_t mode) #endif auto max_calib_analogs = adcGetInputOffset(ADC_INPUT_VBAT); - auto pots_offset = adcGetInputOffset(ADC_INPUT_POT); + auto pots_offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_calib_analogs; i++) { // normalization [0..2048] -> [-1024..1024] diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index cb1f5d39040..73e099d9f37 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -403,18 +403,11 @@ int8_t getMovedSource(uint8_t min) if (result == 0) { for (uint8_t i = 0; i < MAX_ANALOG_INPUTS; i++) { if (abs(calibratedAnalogs[i] - sourcesStates[i]) > MULTIPOS_STEP_SIZE) { - auto offset = adcGetInputOffset(ADC_INPUT_POT); + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); if (i >= offset) { result = MIXSRC_FIRST_POT + i - offset; break; } -#if MAX_AXIS > 0 - offset = adcGetInputOffset(ADC_INPUT_AXIS); - if (i >= offset) { - result = MIXSRC_FIRST_AXIS + i - offset; - break; - } -#endif result = MIXSRC_FIRST_STICK + inputMappingConvertMode(i); break; } @@ -1402,6 +1395,8 @@ void opentxInit() menuHandlers[1] = menuModelSelect; #endif + switchInit(); + #if defined(STARTUP_ANIMATION) lcdRefreshWait(); lcdClear(); diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 411bdda1352..eeb0ea6f303 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -259,12 +259,19 @@ void memswap(void * a, void * b, uint8_t size); #define POT_CONFIG(x) \ ((g_eeGeneral.potsConfig >> POT_CONFIG_POS(x)) & POT_CFG_MASK) -#define IS_POT_MULTIPOS(x) (POT_CONFIG(x) == POT_MULTIPOS_SWITCH) -#define IS_POT_WITHOUT_DETENT(x) (POT_CONFIG(x) == POT_WITHOUT_DETENT) -#define IS_SLIDER(x) (POT_CONFIG(x) == POT_SLIDER_WITH_DETENT) -#define IS_POT_AVAILABLE(x) (POT_CONFIG(x) != POT_NONE) -#define IS_POT_SLIDER_AVAILABLE(x) (IS_POT_AVAILABLE(x)) -#define IS_MULTIPOS_CALIBRATED(cal) (cal->count > 0 && cal->count < XPOTS_MULTIPOS_COUNT) +#define IS_POT_MULTIPOS(x) (POT_CONFIG(x) == FLEX_MULTIPOS) + +#define IS_POT_WITHOUT_DETENT(x) (POT_CONFIG(x) == FLEX_POT) + +#define IS_SLIDER(x) (POT_CONFIG(x) == FLEX_SLIDER) + +#define IS_POT_AVAILABLE(x) \ + (POT_CONFIG(x) != FLEX_NONE && POT_CONFIG(x) <= FLEX_MULTIPOS) + +#define IS_POT_SLIDER_AVAILABLE(x) (IS_POT_AVAILABLE(x)) + +#define IS_MULTIPOS_CALIBRATED(cal) \ + (cal->count > 0 && cal->count < XPOTS_MULTIPOS_COUNT) #define IS_SWITCH_MULTIPOS(x) \ (SWSRC_FIRST_MULTIPOS_SWITCH <= (x) && (x) <= SWSRC_LAST_MULTIPOS_SWITCH) diff --git a/radio/src/opentx_constants.h b/radio/src/opentx_constants.h index 45d40b88297..3529c4c49c0 100644 --- a/radio/src/opentx_constants.h +++ b/radio/src/opentx_constants.h @@ -29,12 +29,15 @@ enum SwitchConfig { SWITCH_3POS, }; -enum PotConfig { - POT_NONE=0, - POT_WITH_DETENT, - POT_MULTIPOS_SWITCH, - POT_WITHOUT_DETENT, - POT_SLIDER_WITH_DETENT, +enum FlexAnalogConfig { + FLEX_NONE=0, + FLEX_POT, // without detent + FLEX_POT_CENTER, // with detent + FLEX_SLIDER, + FLEX_MULTIPOS, + FLEX_AXIS_X, + FLEX_AXIS_Y, + FLEX_SWITCH, }; enum fsStartPositionType { diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index feb3cd06011..6421a5cd649 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -134,7 +134,7 @@ OpenTxSim::OpenTxSim(FXApp* a): sliders[i]->setValue(2047); } - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); memset(knobs, 0, sizeof(knobs)); for (int i = 0; i < max_pots; i++) { @@ -673,15 +673,10 @@ uint16_t simu_get_analog(uint8_t idx) idx -= max_sticks; - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); if (idx < max_pots) return opentxSim->knobs[idx]->getValue(); - idx -= max_pots; - - auto max_axes = adcGetMaxInputs(ADC_INPUT_AXIS); - if (idx < max_axes) return 0; - // probably RTC_BAT return 0; } diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index a2986cd6f31..0b32819863e 100644 --- a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp @@ -353,6 +353,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_PADDING( 8 ), YAML_STRING("bluetoothName", 10), diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 4339040977c..cf033bdf814 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -20,6 +20,7 @@ */ #include "opentx.h" +#include "opentx_constants.h" #include "yaml_bits.h" #include "yaml_tree_walker.h" @@ -254,14 +255,9 @@ static uint32_t r_mixSrcRaw(const YamlNode* node, const char* val, uint8_t val_l auto idx = analogLookupCanonicalIdx(ADC_INPUT_MAIN, val, val_len); if (idx >= 0) return idx + MIXSRC_FIRST_STICK; - idx = analogLookupCanonicalIdx(ADC_INPUT_POT, val, val_len); + idx = analogLookupCanonicalIdx(ADC_INPUT_FLEX, val, val_len); if (idx >= 0) return idx + MIXSRC_FIRST_POT; -#if MAX_AXIS > 0 - idx = analogLookupCanonicalIdx(ADC_INPUT_AXIS, val, val_len); - if (idx >= 0) return idx + MIXSRC_FIRST_POT; -#endif - idx = switchLookupIdx(val, val_len); if (idx >= 0) return idx + MIXSRC_FIRST_SWITCH; @@ -318,13 +314,8 @@ static bool w_mixSrcRaw(const YamlNode* node, uint32_t val, yaml_writer_func wf, str = analogGetCanonicalName(ADC_INPUT_MAIN, val - MIXSRC_FIRST_STICK); } else if (val <= MIXSRC_LAST_POT) { - str = analogGetCanonicalName(ADC_INPUT_POT, val - MIXSRC_FIRST_POT); + str = analogGetCanonicalName(ADC_INPUT_FLEX, val - MIXSRC_FIRST_POT); } -#if MAX_AXIS > 0 - else if (val <= MIXSRC_LAST_AXIS) { - str = analogGetCanonicalName(ADC_INPUT_AXIS, val - MIXSRC_FIRST_AXIS); - } -#endif else if (val >= MIXSRC_FIRST_HELI && val <= MIXSRC_LAST_HELI) { if (!wf(opaque, "CYC", 3)) return false; @@ -682,8 +673,8 @@ static uint32_t slider_read(void* user, const char* val, uint8_t val_len) } static const struct YamlIdStr enum_SliderConfig[] = { - { POT_NONE, "none" }, - { POT_SLIDER_WITH_DETENT, "with_detent" }, + { FLEX_NONE, "none" }, + { FLEX_SLIDER, "with_detent" }, { 0, NULL } }; @@ -704,7 +695,7 @@ static void sl_type_read(void* user, uint8_t* data, uint32_t bitoffs, static void sl_name_read(void* user, uint8_t* data, uint32_t bitoffs, const char* val, uint8_t val_len) { - _read_analog_name(ADC_INPUT_POT, user, data, bitoffs, val, val_len); + _read_analog_name(ADC_INPUT_FLEX, user, data, bitoffs, val, val_len); } static const struct YamlNode struct_sliderConfig[] = { @@ -768,10 +759,63 @@ static const struct YamlNode struct_switchConfig[] = { YAML_END }; +static bool flex_sw_valid(void* user, uint8_t* data, uint32_t bitoffs) +{ + auto tw = reinterpret_cast(user); + uint16_t idx = tw->getElmts(); + return switchIsFlexValid_raw(idx); +} + +uint8_t boardGetMaxSwitches(); + +static uint32_t flex_sw_read(void* user, const char* val, uint8_t val_len) +{ + (void)user; + auto idx = switchLookupIdx(val, val_len); + return idx - boardGetMaxSwitches(); +} + +bool flex_sw_write(void* user, yaml_writer_func wf, void* opaque) +{ + auto tw = reinterpret_cast(user); + uint16_t idx = tw->getElmts(); + + auto sw_offset = boardGetMaxSwitches(); + const char* str = switchGetCanonicalName(idx + sw_offset); + return str ? wf(opaque, str, strlen(str)) : true; +} + +static void r_flex_sw_channel(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + auto tw = reinterpret_cast(user); + uint16_t idx = tw->getElmts(1); + + auto channel = analogLookupPhysicalIdx(ADC_INPUT_FLEX, val, val_len); + switchConfigFlex_raw(idx, channel); +} + +static bool w_flex_sw_channel(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + auto tw = reinterpret_cast(user); + uint16_t idx = tw->getElmts(1); + + auto channel = switchGetFlexConfig_raw(idx); + const char* s = analogGetPhysicalName(ADC_INPUT_FLEX, channel); + return s ? wf(opaque, s, strlen(s)) : true; +} + +static const struct YamlNode struct_flexSwitch[] = { + YAML_IDX_CUST( "sw", flex_sw_read, flex_sw_write), + YAML_CUSTOM( "channel", r_flex_sw_channel, w_flex_sw_channel), + YAML_END +}; + static uint32_t pot_read(void* user, const char* val, uint8_t val_len) { (void)user; - auto idx = analogLookupPhysicalIdx(ADC_INPUT_POT, val, val_len); + auto idx = analogLookupPhysicalIdx(ADC_INPUT_FLEX, val, val_len); if (idx >= 0) return idx; idx = _legacy_mix_src(val, val_len); @@ -786,28 +830,31 @@ static bool pot_write(void* user, yaml_writer_func wf, void* opaque) auto tw = reinterpret_cast(user); uint16_t idx = tw->getElmts(); - const char* str = analogGetPhysicalName(ADC_INPUT_POT, idx); + const char* str = analogGetPhysicalName(ADC_INPUT_FLEX, idx); return str ? wf(opaque, str, strlen(str)) : true; } static void pot_name_read(void* user, uint8_t* data, uint32_t bitoffs, const char* val, uint8_t val_len) { - _read_analog_name(ADC_INPUT_POT, user, data, bitoffs, val, val_len); + _read_analog_name(ADC_INPUT_FLEX, user, data, bitoffs, val, val_len); } static bool pot_name_write(void* user, uint8_t* data, uint32_t bitoffs, yaml_writer_func wf, void* opaque) { - return _write_analog_name(ADC_INPUT_POT, user, data, bitoffs, wf, opaque); + return _write_analog_name(ADC_INPUT_FLEX, user, data, bitoffs, wf, opaque); } static const struct YamlIdStr enum_PotConfig[] = { - { POT_NONE, "none" }, - { POT_WITH_DETENT, "with_detent" }, - { POT_MULTIPOS_SWITCH, "multipos_switch" }, - { POT_WITHOUT_DETENT, "without_detent" }, - { POT_SLIDER_WITH_DETENT, "slider" }, + { FLEX_NONE, "none" }, + { FLEX_POT, "without_detent" }, + { FLEX_POT_CENTER, "with_detent" }, + { FLEX_SLIDER, "slider" }, + { FLEX_MULTIPOS, "multipos_switch" }, + { FLEX_AXIS_X, "axis_x" }, + { FLEX_AXIS_Y, "axis_y" }, + { FLEX_SWITCH, "switch" }, { 0, NULL } }; @@ -840,7 +887,9 @@ static uint32_t r_swtchSrc(const YamlNode* node, const char* val, uint8_t val_le val_len--; } - if (val_len > 3 && val[0] == 'S' && val[1] >= 'W' + if (val_len > 3 + && ((val[0] == 'S' && val[1] >= 'W') + || (val[0] == 'F' && val[1] >= 'L')) && val[2] >= '0' && val[2] <= '9' && val[3] >= '0' && val[3] <= '2') { diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index ac83379bd9e..b5e9ebcf830 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -293,7 +293,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "ppmunit", 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), - YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL), + YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL), YAML_PADDING( 16 ), YAML_SIGNED( "currModel", 8 ), YAML_UNSIGNED( "contrast", 8 ), @@ -364,6 +364,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_STRING("currModelFilename", 17), YAML_UNSIGNED( "modelQuickSelect", 1 ), YAML_UNSIGNED( "blOffBright", 7 ), diff --git a/radio/src/storage/yaml/yaml_datastructs_t20.cpp b/radio/src/storage/yaml/yaml_datastructs_t20.cpp index b6b9d9be907..bf5b1c38bf0 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t20.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t20.cpp @@ -353,6 +353,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_STRING("ownerRegistrationID", 8), YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp index 45bb5ba33b3..bdf71024050 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp @@ -353,6 +353,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_STRING("ownerRegistrationID", 8), YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index e6a3f601016..d6fef2dcecd 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -301,7 +301,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "ppmunit", 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), - YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL), + YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL), YAML_PADDING( 16 ), YAML_UNSIGNED( "vBatWarn", 8 ), YAML_SIGNED( "txVoltageCalibration", 8 ), @@ -370,6 +370,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_STRING("currModelFilename", 17), YAML_UNSIGNED( "modelQuickSelect", 1 ), YAML_UNSIGNED( "blOffBright", 7 ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp index e6a3f601016..d6fef2dcecd 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x12s.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x12s.cpp @@ -301,7 +301,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "ppmunit", 2 ), YAML_CUSTOM("semver",nullptr,w_semver), YAML_CUSTOM("board",nullptr,w_board), - YAML_ARRAY("calib", 48, 22, struct_CalibData, NULL), + YAML_ARRAY("calib", 48, 20, struct_CalibData, NULL), YAML_PADDING( 16 ), YAML_UNSIGNED( "vBatWarn", 8 ), YAML_SIGNED( "txVoltageCalibration", 8 ), @@ -370,6 +370,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 16, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_STRING("currModelFilename", 17), YAML_UNSIGNED( "modelQuickSelect", 1 ), YAML_UNSIGNED( "blOffBright", 7 ), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp index 07fecdc2c5b..d820b7d296e 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9d.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9d.cpp @@ -353,6 +353,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_PADDING( 8 ), YAML_STRING("bluetoothName", 10), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp index d23ce959b0b..a5691efe423 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9e.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9e.cpp @@ -353,6 +353,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_PADDING( 8 ), YAML_STRING("bluetoothName", 10), diff --git a/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp b/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp index 9958d7a539d..4df8ea04ff4 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x9lite.cpp @@ -353,6 +353,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_STRING("ownerRegistrationID", 8), YAML_CUSTOM("rotEncDirection",r_rotEncDirection,nullptr), diff --git a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp index 31a3fe3c71c..0d5aea1895b 100644 --- a/radio/src/storage/yaml/yaml_datastructs_xlites.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_xlites.cpp @@ -355,6 +355,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_ARRAY("slidersConfig", 0, MAX_POTS, struct_sliderConfig, nullptr), YAML_ARRAY("potsConfig", 4, 8, struct_potConfig, nullptr), YAML_ARRAY("switchConfig", 2, 32, struct_switchConfig, nullptr), + YAML_ARRAY("flexSwitches", 0, MAX_FLEX_SWITCHES, struct_flexSwitch, flex_sw_valid), YAML_UNSIGNED( "backlightColor", 8 ), YAML_PADDING( 8 ), YAML_STRING("bluetoothName", 10), diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 2e5cb1952e4..51d56d66f02 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -538,7 +538,7 @@ const char* getAnalogLabel(uint8_t type, uint8_t idx) return adcGetInputShortLabel(type, idx); } - if (type == ADC_INPUT_POT) { + if (type == ADC_INPUT_FLEX) { return adcGetInputLabel(type, idx); } @@ -562,10 +562,10 @@ const char* getAnalogShortLabel(uint8_t idx) } idx -= max; - max = adcGetMaxInputs(ADC_INPUT_POT); + max = adcGetMaxInputs(ADC_INPUT_FLEX); if (idx < max) { - return adcGetInputShortLabel(ADC_INPUT_POT, idx); + return adcGetInputShortLabel(ADC_INPUT_FLEX, idx); } // we only support short labels @@ -604,7 +604,7 @@ const char* getTrimSourceLabel(uint16_t src_raw, int8_t trim_src) const char* getPotLabel(uint8_t idx) { - return getAnalogLabel(ADC_INPUT_POT, idx); + return getAnalogLabel(ADC_INPUT_FLEX, idx); } // this should be declared in header, but it used so much foreign symbols that @@ -676,19 +676,12 @@ char *getSourceString(char (&dest)[L], mixsrc_t idx) pos = strAppend(pos, STR_CHAR_POT, sizeof(STR_CHAR_POT) - 1); dest_len -= sizeof(STR_CHAR_POT) - 1; } + // TODO: AXIS / SWITCH ??? name = getPotLabel(idx); } strncpy(pos, name, dest_len - 1); pos[dest_len - 1] = '\0'; } -#if MAX_AXIS > 0 - else if (idx <= MIXSRC_LAST_AXIS) { - idx -= MIXSRC_FIRST_AXIS; - auto name = adcGetInputName(ADC_INPUT_AXIS, idx); - strncpy(dest, name, dest_len - 1); - dest[dest_len - 1] = '\0'; - } -#endif #if defined(IMU) else if (idx <= MIXSRC_TILT_Y) { idx -= MIXSRC_TILT_X; diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 40ba379c9c1..1f60d8768f1 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -171,6 +171,8 @@ void evalFunctionSwitches() } } } +#else +uint8_t getFSLogicalState(uint8_t) { return false; } #endif // FUNCTION_SWITCHES div_t switchInfo(int switchPosition) @@ -196,15 +198,12 @@ int switchLookupIdx(char c) int switchLookupIdx(const char* name, size_t len) { - if (len < 2 || name[0] != 'S') return -1; - - uint8_t idx = 1; // Sx - if (len > 2) idx = 2; // SWx + if (len < 2 || (name[0] != 'S' && name[0] != 'F')) return -1; auto max_switches = switchGetMaxSwitches() + switchGetMaxFctSwitches(); for (int i = 0; i < max_switches; i++) { - const char *sw_name = switchGetName(i); - if (sw_name[idx] == name[idx]) return i; + const char *sw_name = switchGetCanonicalName(i); + if (strncmp(sw_name, name, len) == 0) return i; } return -1; @@ -244,9 +243,6 @@ bool switchHasCustomName(uint8_t idx) const char* switchGetCanonicalName(uint8_t idx) { - if (idx >= switchGetMaxSwitches() + switchGetMaxFctSwitches()) - return nullptr; - return switchGetName(idx); } @@ -314,8 +310,8 @@ void getSwitchesPosition(bool startup) switchesPos = newPos; - auto max_pots = adcGetMaxInputs(ADC_INPUT_POT); - auto offset = adcGetInputOffset(ADC_INPUT_POT); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); for (int i = 0; i < max_pots; i++) { if (IS_POT_MULTIPOS(i)) { @@ -345,6 +341,30 @@ void getSwitchesPosition(bool startup) } } +uint8_t getSwitchCount() +{ + int count = 0; + for (int i = 0; i < switchGetMaxSwitches(); ++i) { + if (SWITCH_EXISTS(i)) { + ++count; + } + } + return count; +} + +uint8_t switchGetMaxRow(uint8_t col) +{ + uint8_t lastrow = 0; + for (int i = 0; i < switchGetMaxSwitches(); ++i) { + if (SWITCH_EXISTS(i)) { + auto switch_display = switchGetDisplayPosition(i); + if (switch_display.col == col) + lastrow = switch_display.row > lastrow ? switch_display.row : lastrow; + } + } + return lastrow; +} + getvalue_t getValueForLogicalSwitch(mixsrc_t i) { getvalue_t result = getValue(i); @@ -567,11 +587,19 @@ bool getSwitch(swsrc_t swtch, uint8_t flags) #endif else if (cs_idx <= SWSRC_LAST_SWITCH) { cs_idx -= SWSRC_FIRST_SWITCH; +#if defined(FUNCTION_SWITCHES) auto max_reg_pos = switchGetMaxSwitches() * 3; - if (cs_idx < max_reg_pos) { - if (flags & GETSWITCH_MIDPOS_DELAY) + if (cs_idx >= max_reg_pos && cs_idx - max_reg_pos < switchGetMaxFctSwitches() * 3) { + cs_idx -= max_reg_pos; + div_t qr = div(cs_idx, 3); + auto value = getFSLogicalState(qr.quot); + result = qr.rem == 0 ? !value : (qr.rem == 2 ? value : false); + } else +#endif + { + if (flags & GETSWITCH_MIDPOS_DELAY) { result = SWITCH_POSITION(cs_idx); - else { + } else { div_t qr = div(cs_idx, 3); if (SWITCH_EXISTS(qr.quot)) { result = switchState(cs_idx); @@ -580,17 +608,6 @@ bool getSwitch(swsrc_t swtch, uint8_t flags) } } } -#if defined(FUNCTION_SWITCHES) - else if (cs_idx - max_reg_pos < switchGetMaxFctSwitches() * 3) { - cs_idx -= max_reg_pos; - div_t qr = div(cs_idx, 3); - auto value = getFSLogicalState(qr.quot); - result = qr.rem == 0 ? !value : (qr.rem == 2 ? value : false); - } -#endif - else { - result = false; - } } else if (cs_idx <= SWSRC_LAST_MULTIPOS_SWITCH) { result = POT_POSITION(cs_idx - SWSRC_FIRST_MULTIPOS_SWITCH); @@ -753,7 +770,7 @@ bool isSwitchWarningRequired(uint16_t &bad_pots) if (g_model.potsWarnMode) { evalFlightModeMixes(e_perout_mode_normal, 0); bad_pots = 0; - for (int i = 0; i < adcGetMaxInputs(ADC_INPUT_POT); i++) { + for (int i = 0; i < adcGetMaxInputs(ADC_INPUT_FLEX); i++) { if (!IS_POT_SLIDER_AVAILABLE(i)) continue; if ((g_model.potsWarnEnabled & (1 << i)) && (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1)) { diff --git a/radio/src/switches.h b/radio/src/switches.h index 4a7f995b28f..029f55af56f 100644 --- a/radio/src/switches.h +++ b/radio/src/switches.h @@ -50,6 +50,10 @@ bool isSwitchWarningRequired(uint16_t &bad_pots); void getSwitchesPosition(bool startup); +uint8_t getSwitchCount(); + +uint8_t switchGetMaxRow(uint8_t col); + extern swarnstate_t switches_states; swsrc_t getMovedSwitch(); diff --git a/radio/src/targets/common/arm/stm32/stm32_switch_driver.cpp b/radio/src/targets/common/arm/stm32/stm32_switch_driver.cpp index 91bede6d466..7b6fcda8957 100644 --- a/radio/src/targets/common/arm/stm32/stm32_switch_driver.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_switch_driver.cpp @@ -22,72 +22,6 @@ #include "stm32_switch_driver.h" #include "hal/adc_driver.h" -bool stm32_switch_get_state(const stm32_switch_t* sw, SwitchHwPos pos) -{ - switch (sw->type) { - case SWITCH_HW_2POS: - switch (pos) { - case SWITCH_HW_UP: - if (sw->flags & SWITCH_HW_INVERTED) - return !LL_GPIO_IsInputPinSet(sw->GPIOx_high, sw->Pin_high); - else - return LL_GPIO_IsInputPinSet(sw->GPIOx_high, sw->Pin_high); - - case SWITCH_HW_DOWN: - if (sw->flags & SWITCH_HW_INVERTED) - return LL_GPIO_IsInputPinSet(sw->GPIOx_high, sw->Pin_high); - else - return !LL_GPIO_IsInputPinSet(sw->GPIOx_high, sw->Pin_high); - - default: - return false; - } - break; - - case SWITCH_HW_3POS: { - auto hi = LL_GPIO_IsInputPinSet(sw->GPIOx_high, sw->Pin_high); - auto lo = LL_GPIO_IsInputPinSet(sw->GPIOx_low, sw->Pin_low); - - switch (pos) { - case SWITCH_HW_UP: - if (sw->flags & SWITCH_HW_INVERTED) - return !hi && lo; - else - return hi && !lo; - - case SWITCH_HW_DOWN: - if (sw->flags & SWITCH_HW_INVERTED) - return hi && !lo; - else - return !hi && lo; - - case SWITCH_HW_MID: - return hi && lo; - - default: - return false; - } - } break; - - case SWITCH_HW_ADC: { - uint16_t value = getAnalogValue(sw->Pin_high); - switch (pos) { - case SWITCH_HW_UP: - return value < 1024; - case SWITCH_HW_DOWN: - return value > 3 * 1024; - case SWITCH_HW_MID: - return (value >= 1024) && (value <= 3 * 1024); - } - } break; - - default: - break; - } - - return false; -} - SwitchHwPos stm32_switch_get_position(const stm32_switch_t* sw) { bool inv = sw->flags & SWITCH_HW_INVERTED; diff --git a/radio/src/targets/common/arm/stm32/stm32_switch_driver.h b/radio/src/targets/common/arm/stm32/stm32_switch_driver.h index 4d4e43921f3..11d67630ef2 100644 --- a/radio/src/targets/common/arm/stm32/stm32_switch_driver.h +++ b/radio/src/targets/common/arm/stm32/stm32_switch_driver.h @@ -37,18 +37,5 @@ struct stm32_switch_t uint8_t flags; }; -#define SWITCH_HW_DEF_3POS(x, flags) \ - { \ - SWITCHES_GPIO_REG_##x##_H, SWITCHES_GPIO_PIN_##x##_H, \ - SWITCHES_GPIO_REG_##x##_L, SWITCHES_GPIO_PIN_##x##_L, \ - SWITCH_HW_3POS, (flags) \ - } - -#define SWITCH_HW_DEF_2POS(x, flags) \ - { \ - SWITCHES_GPIO_REG_##x, SWITCHES_GPIO_PIN_##x, \ - nullptr, 0, SWITCH_HW_2POS, (flags) \ - } - SwitchHwPos stm32_switch_get_position(const stm32_switch_t* sw); bool stm32_switch_get_state(const stm32_switch_t* sw, SwitchHwPos pos); diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 4a38d59c881..537fb5d31cf 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -110,6 +110,7 @@ if (PCB STREQUAL X10) endif() set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS") set(FLYSKY_GIMBAL ON) + set(FLEXSW "2" CACHE STRING "Max flex inputs usable as switches") elseif (PCBREV STREQUAL T18) set(FLAVOUR t18) add_definitions(-DRADIO_T18) diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 5cb3cc8696e..3c13292347f 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -51,7 +51,7 @@ QVector OpenTxSimulator::tracebackDevices; uint16_t simu_get_analog(uint8_t idx) { // 6POS simu mechanism use a different scale, so needs specific offset - if (IS_POT_MULTIPOS(idx - adcGetInputOffset(ADC_INPUT_POT))) { + if (IS_POT_MULTIPOS(idx - adcGetInputOffset(ADC_INPUT_FLEX))) { // Use radio calibration data to determine conversion factor StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[idx]; int range6POS = 2048; // Default if calibration is not valid @@ -256,11 +256,11 @@ void OpenTxSimulator::setInputValue(int type, uint8_t index, int16_t value) setAnalogValue(index, value); break; case INPUT_SRC_KNOB : - setAnalogValue(index + adcGetInputOffset(ADC_INPUT_POT), value); + setAnalogValue(index + adcGetInputOffset(ADC_INPUT_FLEX), value); break; case INPUT_SRC_SLIDER : // TODO redo this when Companion refactored to use radio json adc files - //setAnalogValue(index + adcGetInputOffset(ADC_INPUT_POT), value); + //setAnalogValue(index + adcGetInputOffset(ADC_INPUT_FLEX), value); static const int slideroffset = adcGetInputIdx("SL1", 3); //qDebug() << "SL1:" << slideroffset; if (slideroffset >= 0) diff --git a/radio/src/targets/simu/switch_driver.cpp b/radio/src/targets/simu/switch_driver.cpp index 92251a05ab3..fd7617697c5 100644 --- a/radio/src/targets/simu/switch_driver.cpp +++ b/radio/src/targets/simu/switch_driver.cpp @@ -33,97 +33,65 @@ struct hw_switch_def { #include "simu_switches.inc" -int8_t switchesStates[n_total_switches] = { -1 }; +int8_t switchesStates[MAX_SWITCHES] = { -1 }; void simuSetSwitch(uint8_t swtch, int8_t state) { - assert(swtch < n_total_switches); + assert(swtch < switchGetMaxSwitches() + switchGetMaxFctSwitches()); switchesStates[swtch] = state; } -swconfig_t switchGetDefaultConfig() -{ - return _switch_default_config; -} - -switch_display_pos_t switchGetDisplayPosition(uint8_t idx) -{ - if (idx >= DIM(_switch_display)) - return {0, 0}; - - return _switch_display[idx]; -} +void boardInitSwitches() {} -uint8_t switchGetMaxSwitches() +static uint8_t get_switch_index(uint8_t cat, uint8_t idx) { - return n_switches; + switch(cat) { + case SWITCH_PHYSICAL: + assert(idx < n_switches); + return idx; + + case SWITCH_FUNCTION: + assert(idx < n_fct_switches); + return idx + n_switches; + + default: + assert(0); + return 0; + } } -uint8_t getSwitchCount() +SwitchHwPos boardSwitchGetPosition(uint8_t cat, uint8_t idx) { - int count = 0; - for (int i = 0; i < switchGetMaxSwitches(); ++i) { - if (SWITCH_EXISTS(i)) { - ++count; - } - } - return count; -} + idx = get_switch_index(cat, idx); -uint8_t switchGetMaxRow(uint8_t col) -{ - uint8_t lastrow = 0; - for (int i = 0; i < switchGetMaxSwitches(); ++i) { - if (SWITCH_EXISTS(i)) { - auto switch_display = switchGetDisplayPosition(i); - if (switch_display.col == col) - lastrow = switch_display.row > lastrow ? switch_display.row : lastrow; - } - } - return lastrow; + if (switchesStates[idx] < 0) + return SWITCH_HW_UP; + else if (switchesStates[idx] == 0) + return SWITCH_HW_MID; + else + return SWITCH_HW_DOWN; } -uint8_t switchGetMaxFctSwitches() +const char* boardSwitchGetName(uint8_t cat, uint8_t idx) { - return n_fct_switches; + idx = get_switch_index(cat, idx); + return _switch_defs[idx].name; } -const char* switchGetName(uint8_t idx) +SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx) { - assert(idx < n_total_switches); - return _hw_switch_defs[idx].name; + idx = get_switch_index(cat, idx); + return _switch_defs[idx].type; } -SwitchHwType switchGetHwType(uint8_t idx) -{ - assert(idx < n_total_switches); - return _hw_switch_defs[idx].type; -} +uint8_t boardGetMaxSwitches() { return n_switches; } +uint8_t boardGetMaxFctSwitches() { return n_fct_switches; } -uint32_t switchState(uint8_t pos) -{ - assert(pos < n_total_switches * 3); - - div_t qr = div(pos, 3); - int state = switchesStates[qr.quot]; - switch (qr.rem) { - case SWITCH_HW_UP: - return state < 0; - case SWITCH_HW_DOWN: - return state > 0; - default: - return state == 0; - } -} +swconfig_t boardSwitchGetDefaultConfig() { return _switch_default_config; } -SwitchHwPos switchGetPosition(uint8_t idx) +switch_display_pos_t switchGetDisplayPosition(uint8_t idx) { - assert(idx < n_total_switches); + if (idx >= DIM(_switch_display)) return {0, 0}; - if (switchesStates[idx] < 0) - return SWITCH_HW_UP; - else if (switchesStates[idx] == 0) - return SWITCH_HW_MID; - else - return SWITCH_HW_DOWN; + return _switch_display[idx]; } diff --git a/radio/src/tests/functions.cpp b/radio/src/tests/functions.cpp index 603c7e64bad..25549b5b2d4 100644 --- a/radio/src/tests/functions.cpp +++ b/radio/src/tests/functions.cpp @@ -44,13 +44,17 @@ TEST_F(SpecialFunctionsTest, FlightReset) g_model.customFn[0].all.val = FUNC_RESET_FLIGHT; g_model.customFn[0].active = true; + mainRequestFlags = 0; simuSetSwitch(0, 0); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH)); + evalFunctions(g_model.customFn, modelFunctionsContext); EXPECT_EQ((bool)(mainRequestFlags & (1 << REQUEST_FLIGHT_RESET)), false); // now trigger SA0 simuSetSwitch(0, -1); + EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH)); // flightReset() should be called evalFunctions(g_model.customFn, modelFunctionsContext); diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index 8e864db347a..6f73a4e87bb 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -19,7 +19,13 @@ * GNU General Public License for more details. */ +#include "dataconstants.h" +#include "gtest.h" #include "gtests.h" +#include "myeeprom.h" + +#include "hal/adc_driver.h" +#include "hal/switch_driver.h" void setLogicalSwitch(int index, uint16_t _func, int16_t _v1, int16_t _v2, int16_t _v3 = 0, uint8_t _delay = 0, uint8_t _duration = 0, int8_t _andsw = 0) { @@ -137,7 +143,7 @@ TEST(evalLogicalSwitches, playFile) #endif #define SWSRC_SA2 (SWSRC_FIRST_SWITCH + 2) -#define SWSRC_SF2 (SWSRC_FIRST_SWITCH + 5 * 3 + 2) +#define SWSRC_SD2 (SWSRC_FIRST_SWITCH + 3 * 3 + 2) TEST(getSwitch, edgeInstant) { @@ -145,29 +151,29 @@ TEST(getSwitch, edgeInstant) MODEL_RESET(); MIXER_RESET(); - // LS1 setup: EDGE SFup (0:instant) - // LS2 setup: (EDGE SFup (0:instant)) AND SAup - setLogicalSwitch(0, LS_FUNC_EDGE, SWSRC_SF2, -129, -1); - setLogicalSwitch(1, LS_FUNC_EDGE, SWSRC_SF2, -129, -1, 0, 0, SWSRC_SA2); - - simuSetSwitch(0, -1); //SA down - simuSetSwitch(5, 0); //SF down - // EXPECT_EQ(getSwitch(SWSRC_SF2), false); + // LS1 setup: EDGE SDup (0:instant) + // LS2 setup: (EDGE SDup (0:instant)) AND SAup + setLogicalSwitch(0, LS_FUNC_EDGE, SWSRC_SD2, -129, -1); + setLogicalSwitch(1, LS_FUNC_EDGE, SWSRC_SD2, -129, -1, 0, 0, SWSRC_SA2); + + simuSetSwitch(0, -1); //SA down + simuSetSwitch(3, 0); //SD down + // EXPECT_EQ(getSwitch(SWSRC_SD2), false); logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); // now trigger SFup, LS1 should become true - simuSetSwitch(5, 1); //SF up - // EXPECT_EQ(getSwitch(SWSRC_SF2), true); + simuSetSwitch(3, 1); //SD up + // EXPECT_EQ(getSwitch(SWSRC_SD2), true); logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); EXPECT_EQ(getSwitch(SWSRC_SW2), false); // now release SA0 and SW2 should stay true - simuSetSwitch(5, 0); //SF down + simuSetSwitch(3, 0); //SD down logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); @@ -184,23 +190,23 @@ TEST(getSwitch, edgeInstant) // second part with SAup simuSetSwitch(0, 1); //SA up - simuSetSwitch(5, 0); //SF down - // EXPECT_EQ(getSwitch(SWSRC_SF2), false); + simuSetSwitch(3, 0); //SD down + // EXPECT_EQ(getSwitch(SWSRC_SD2), false); logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); // now trigger SFup, LS1 should become true - simuSetSwitch(5, 1); //SF up - // EXPECT_EQ(getSwitch(SWSRC_SF2), true); + simuSetSwitch(3, 1); //SD up + // EXPECT_EQ(getSwitch(SWSRC_SD2), true); logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); EXPECT_EQ(getSwitch(SWSRC_SW2), true); // now release SA0 and SW2 should stay true - simuSetSwitch(5, 0); //SF down + simuSetSwitch(3, 0); //SD down logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); @@ -214,23 +220,23 @@ TEST(getSwitch, edgeInstant) EXPECT_EQ(getSwitch(SWSRC_SW2), false); // now bug #2939 - // SF is kept up and SA is toggled + // SD is kept up and SA is toggled simuSetSwitch(0, -1); //SA down - simuSetSwitch(5, 1); //SF up + simuSetSwitch(3, 1); //SD up logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); EXPECT_EQ(getSwitch(SWSRC_SW2), false); simuSetSwitch(0, 1); //SA up - simuSetSwitch(5, 1); //SF up + simuSetSwitch(3, 1); //SD up logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); simuSetSwitch(0, -1); //SA down - simuSetSwitch(5, 1); //SF up + simuSetSwitch(3, 1); //SD up logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); @@ -240,7 +246,7 @@ TEST(getSwitch, edgeInstant) //logical switches are reset - the switch should fire again simuSetSwitch(0, 1); //SA up - simuSetSwitch(5, 1); //SF up + simuSetSwitch(3, 1); //SD up logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); //switch will not trigger, because SF was already up @@ -265,25 +271,25 @@ TEST(getSwitch, edgeRelease) MODEL_RESET(); MIXER_RESET(); // test for issue #2728 - // LS1 setup: EDGE SFup (0:release) - // LS2 setup: (EDGE SFup (0:release)) AND SAup - setLogicalSwitch(0, LS_FUNC_EDGE, SWSRC_SF2, -129, 0); - setLogicalSwitch(1, LS_FUNC_EDGE, SWSRC_SF2, -129, 0, 0, 0, SWSRC_SA2 ); + // LS1 setup: EDGE SDup (0:release) + // LS2 setup: (EDGE SDup (0:release)) AND SAup + setLogicalSwitch(0, LS_FUNC_EDGE, SWSRC_SD2, -129, 0); + setLogicalSwitch(1, LS_FUNC_EDGE, SWSRC_SD2, -129, 0, 0, 0, SWSRC_SA2 ); simuSetSwitch(0, -1); //SA down - simuSetSwitch(5, 0); //SF down + simuSetSwitch(3, 0); //SD down logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); - simuSetSwitch(5, 1); //SF up + simuSetSwitch(3, 1); //SD up logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); - simuSetSwitch(5, 0); //SF down + simuSetSwitch(3, 0); //SD down logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); @@ -292,19 +298,19 @@ TEST(getSwitch, edgeRelease) // second part with SAup simuSetSwitch(0, 1); //SA up - simuSetSwitch(5, 0); //SF down + simuSetSwitch(3, 0); //SD down logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); - simuSetSwitch(5, 1); //SF up + simuSetSwitch(3, 1); //SD up logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), false); EXPECT_EQ(getSwitch(SWSRC_SW2), false); - simuSetSwitch(5, 0); //SF down + simuSetSwitch(3, 0); //SD down logicalSwitchesTimerTick(); evalLogicalSwitches(); EXPECT_EQ(getSwitch(SWSRC_SW1), true); @@ -318,3 +324,97 @@ TEST(getSwitch, edgeRelease) EXPECT_EQ(getSwitch(SWSRC_SW2), false); } + +uint8_t boardGetMaxSwitches(); + +TEST(FlexSwitches, switchGetPosition) +{ + if (adcGetMaxInputs(ADC_INPUT_FLEX) == 0) return; + if (MAX_FLEX_SWITCHES == 0) return; + switchInit(); + + auto sw_idx = boardGetMaxSwitches(); + auto sw_name = switchGetName(sw_idx); + EXPECT_STREQ("FL1", sw_name); + EXPECT_FALSE(switchIsFlexValid(sw_idx)); + + // Configure 1st FLEX input as switch + g_eeGeneral.potsConfig = FLEX_SWITCH; + switchConfigFlex(sw_idx, 0); + EXPECT_TRUE(switchIsFlexValid(sw_idx)); + + setAnalogValue(0, 0); + EXPECT_EQ(SWITCH_HW_UP, switchGetPosition(sw_idx)); + + setAnalogValue(0, ADC_MAX_VALUE / 2); + EXPECT_EQ(SWITCH_HW_MID, switchGetPosition(sw_idx)); + + setAnalogValue(0, ADC_MAX_VALUE); + EXPECT_EQ(SWITCH_HW_DOWN, switchGetPosition(sw_idx)); +} + +TEST(FlexSwitches, getValue) +{ + if (adcGetMaxInputs(ADC_INPUT_FLEX) == 0) return; + if (MAX_FLEX_SWITCHES == 0) return; + switchInit(); + + // Configure 1st FLEX input as switch + g_eeGeneral.potsConfig = FLEX_SWITCH; + auto sw_idx = boardGetMaxSwitches(); + switchConfigFlex(sw_idx, 0); + + g_eeGeneral.switchConfig = (swconfig_t)SWITCH_3POS << (sw_idx * SW_CFG_BITS); + EXPECT_EQ(SWITCH_3POS, SWITCH_CONFIG(sw_idx)); + + setAnalogValue(0, 0); + EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + setAnalogValue(0, ADC_MAX_VALUE / 2); + EXPECT_EQ(0, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + setAnalogValue(0, ADC_MAX_VALUE); + EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + g_eeGeneral.switchConfig = (swconfig_t)SWITCH_2POS << (sw_idx * SW_CFG_BITS); + EXPECT_EQ(SWITCH_2POS, SWITCH_CONFIG(sw_idx)); + + setAnalogValue(0, 0); + EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + setAnalogValue(0, ADC_MAX_VALUE / 2); + EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + setAnalogValue(0, ADC_MAX_VALUE); + EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); +} + +TEST(FlexSwitches, getSwitch) +{ + if (adcGetMaxInputs(ADC_INPUT_FLEX) == 0) return; + if (MAX_FLEX_SWITCHES == 0) return; + switchInit(); + + // Configure 1st FLEX input as switch + g_eeGeneral.potsConfig = FLEX_SWITCH; + auto sw_idx = boardGetMaxSwitches(); + switchConfigFlex(sw_idx, 0); + + g_eeGeneral.switchConfig = (swconfig_t)SWITCH_3POS << (sw_idx * SW_CFG_BITS); + EXPECT_EQ(SWITCH_3POS, SWITCH_CONFIG(sw_idx)); + + setAnalogValue(0, 0); + EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); + + setAnalogValue(0, ADC_MAX_VALUE / 2); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); + EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); + + setAnalogValue(0, ADC_MAX_VALUE); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); + EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); + EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); +} diff --git a/radio/src/translations/cn.h b/radio/src/translations/cn.h index d40b774a1b6..d675bb167af 100644 --- a/radio/src/translations/cn.h +++ b/radio/src/translations/cn.h @@ -51,7 +51,7 @@ #define TR_AUX_SERIAL_MODES "调试","回传镜像","回传输入","SBUS教练","LUA脚本","CLI","GPS","Debug","SpaceMouse","外置发射" #define TR_SWTYPES "无","回弹","2段","3段" -#define TR_POTTYPES "无","有中点旋钮","多段旋钮","无中点旋钮","侧滑块" +#define TR_POTTYPES "无","无中点旋钮","有中点旋钮","侧滑块","多段旋钮","Axis X","Axis Y","Switch" #define TR_VPERSISTENT "禁用","随飞行记录复位","随手动复位" #define TR_COUNTRY_CODES "美国","日本","欧洲" #define TR_USBMODES "询问","游戏柄","U盘","串行" diff --git a/radio/src/translations/cz.h b/radio/src/translations/cz.h index 19b2dde56ed..76e41ed4d23 100644 --- a/radio/src/translations/cz.h +++ b/radio/src/translations/cz.h @@ -54,7 +54,7 @@ #define TR_TRNCHN "CH1","CH2","CH3","CH4" #define TR_AUX_SERIAL_MODES "VYP","Telemetrie zrcadlení","Telemetrie vstup","SBUS Trenér","LUA","CLI","GPS","Debug","SpaceMouse","Externí modul" #define TR_SWTYPES "Žádný","Bez aretace","2-polohový","3-polohový" -#define TR_POTTYPES "Žádný",TR("Pot s aret.","Pot s aretací"),TR("Vícepol př.","Vícepol. přep."),TR("Pot","Potenciometr"),"Slider" +#define TR_POTTYPES "Žádný",TR("Pot","Potenciometr"),TR("Pot s aret.","Pot s aretací"),"Slider",TR("Vícepol př.","Vícepol. přep."),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "Ne","V rámci letu","Reset ručně" #define TR_COUNTRY_CODES TR("US","Amerika"),TR("JP","Japonsko"),TR("EU","Evropa") #define TR_USBMODES TR("Zeptat","Zeptat se"),TR("Joyst","Joystick"),TR("SDkarta","Úložiště"),"Serial" diff --git a/radio/src/translations/da.h b/radio/src/translations/da.h index cbdf6ef4498..6611d2702d0 100644 --- a/radio/src/translations/da.h +++ b/radio/src/translations/da.h @@ -57,7 +57,7 @@ #define TR_SWTYPES "Ingen","Skift","2POS","3POS" #endif -#define TR_POTTYPES "Ingen",TR("Drejek./klik","Drejekontakt med klik"),TR("Multipos","Multipos kontakt"),TR("Drejek.", "Drejekontakt"),"Skyder" +#define TR_POTTYPES "Ingen",TR("Drejek.", "Drejekontakt"),TR("Drejek./klik","Drejekontakt med klik"),"Skyder",TR("Multipos","Multipos kontakt"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "FRA","Flyv","Manuel nulstil" #define TR_COUNTRY_CODES TR("US","Amerika"),TR("JP","Japan"),TR("EU","Europa") #define TR_USBMODES "Spørg",TR("Joyst","Joystik"),TR("Lager","USB lager"),TR("Data", "USB data") diff --git a/radio/src/translations/de.h b/radio/src/translations/de.h index bfd2ed9e3f2..819bf3576fe 100644 --- a/radio/src/translations/de.h +++ b/radio/src/translations/de.h @@ -54,7 +54,7 @@ #define TR_TRNCHN "CH1","CH2","CH3","CH4" #define TR_AUX_SERIAL_MODES "AUS","Telem weiterl.","Telemetrie In","SBUS Eingang","LUA","CLI","GPS","Debug","SpaceMouse","Externes Modul" #define TR_SWTYPES "Kein","Taster","2POS","3POS" -#define TR_POTTYPES "Kein",TR("Poti m.Ras","Poti mit Raste"),TR("Stufens.","Stufen-Schalter"),TR("Pot","Poti ohne Raste"), "Schieber" +#define TR_POTTYPES "Kein",TR("Pot","Poti ohne Raste"),TR("Poti m.Ras","Poti mit Raste"),"Schieber",TR("Stufens.","Stufen-Schalter"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "AUS","Flugzeit","Manuell Rück" #define TR_COUNTRY_CODES TR("US","Amerika"),TR("JP","Japan"),TR("EU","Europa") #define TR_USBMODES "Fragen",TR("Joyst","Joystick"),TR("SDCard","Speicher"),TR("Serial","Seriell") diff --git a/radio/src/translations/en.h b/radio/src/translations/en.h index 3baaf3dee15..ff93958aec5 100644 --- a/radio/src/translations/en.h +++ b/radio/src/translations/en.h @@ -50,7 +50,7 @@ #define TR_AUX_SERIAL_MODES "OFF","Telem Mirror","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse","External module" #define TR_SWTYPES "None","Toggle","2POS","3POS" -#define TR_POTTYPES "None",TR("Pot w. det","Pot with detent"),TR("Multipos","Multipos Switch"),"Pot", "Slider" +#define TR_POTTYPES "None","Pot",TR("Pot w. det","Pot with detent"),"Slider",TR("Multipos","Multipos Switch"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "OFF","Flight","Manual Reset" #define TR_COUNTRY_CODES TR("US","America"),TR("JP","Japan"),TR("EU","Europe") #define TR_USBMODES "Ask",TR("Joyst","Joystick"),TR("SDCard","Storage"),"Serial" diff --git a/radio/src/translations/es.h b/radio/src/translations/es.h index 4773c34529c..56791c383fb 100644 --- a/radio/src/translations/es.h +++ b/radio/src/translations/es.h @@ -52,7 +52,7 @@ #define TR_AUX_SERIAL_MODES "UIT","Telem Mirror","Telemetría","Entrenador SBUS","LUA","CLI","GPS","Debug","SpaceMouse","Módulo externo" #define TR_SWTYPES "Nada","Palanca","2POS","3POS" -#define TR_POTTYPES "Nada",TR("Pot con fij","Pot con fijador"),TR("Multipos","Switch multipos"),"Pot","Slider" +#define TR_POTTYPES "Nada","Pot",TR("Pot con fij","Pot con fijador"),"Slider",TR("Multipos","Switch multipos"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "OFF","Vuelo","Reset manual" #define TR_COUNTRY_CODES TR("US","América"),TR("JP","Japón"),TR("EU", "Europa") #define TR_USBMODES "Pregunta","Joystick","SDCard","Serie" diff --git a/radio/src/translations/fi.h b/radio/src/translations/fi.h index 1c602ae224a..541e949f997 100644 --- a/radio/src/translations/fi.h +++ b/radio/src/translations/fi.h @@ -54,7 +54,7 @@ #define TR_AUX_SERIAL_MODES "POIS","S-Port Pelik","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse","External module" #define TR_SWTYPES "None","Toggle","2POS","3POS" -#define TR_POTTYPES "None", TR("Pot w. det","Pot with detent"),TR("Multipos","Monias. Kytkin"),TR("Pot","Potikka"),"Slider" +#define TR_POTTYPES "None",TR("Pot","Potikka"),TR("Pot w. det","Pot with detent"),"Slider",TR("Multipos","Monias. Kytkin"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "OFF","Flight","Manual Reset" #define TR_COUNTRY_CODES TR("US","Amerikk"),TR("JP","Japani"),TR("EU","Euroopp") #define TR_USBMODES "Kysy",TR("Joyst","Joystick"),TR("SDCard","Storage"),"Serial" diff --git a/radio/src/translations/fr.h b/radio/src/translations/fr.h index 7d529ac97f1..981da2d2b92 100644 --- a/radio/src/translations/fr.h +++ b/radio/src/translations/fr.h @@ -54,7 +54,7 @@ #define TR_AUX_SERIAL_MODES "OFF","Recopie Télém.","Télémétrie In","Écolage SBUS","LUA","CLI","GPS","Débug","SpaceMouse","Module externe" #define TR_SWTYPES "Rien","Monostable","2-POS","3-POS" -#define TR_POTTYPES "Rien",TR("Pots av. ctr","Pots avec centre"),TR("Multipos.","Inter multi-pos""Potentiomètre"),TR("Pots","Potentiomètre"),"Curseurs" +#define TR_POTTYPES "Rien",TR("Pots","Potentiomètre"),TR("Pots av. ctr","Pots avec centre"),"Curseurs",TR("Multipos.","Inter multi-pos""Potentiomètre"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "OFF","Vol","Reset Manuel" #define TR_COUNTRY_CODES TR("US","USA"),TR("JP","Japon"),TR("Europe","EU") diff --git a/radio/src/translations/he.h b/radio/src/translations/he.h index 2798b72f948..a6552ede52a 100644 --- a/radio/src/translations/he.h +++ b/radio/src/translations/he.h @@ -53,7 +53,7 @@ #define TR_AUX_SERIAL_MODES "OFF","Telem Mirror","Telemetry In","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse","External module" #define TR_SWTYPES "None","Toggle","2POS","3POS" -#define TR_POTTYPES "None",TR("Pot w. det","Pot with detent"),TR("Multipos","Multipos Switch"),"Pot" +#define TR_POTTYPES "None","Pot",TR("Pot w. det","Pot with detent"),"Slider",TR("Multipos","Multipos Switch"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "OFF","Flight","Manual Reset" #define TR_COUNTRY_CODES TR("US","America"),TR("JP","Japan"),TR("EU","Europe") #define TR_USBMODES "הצג לי אופציות",TR("Joyst","חיבור משחק קבוע"),TR("SDCard","העברת נתונים קבוע"),"חיבור סיריילי קבוע" diff --git a/radio/src/translations/it.h b/radio/src/translations/it.h index 4e8dec6550c..1f91ac12bfb 100644 --- a/radio/src/translations/it.h +++ b/radio/src/translations/it.h @@ -55,7 +55,7 @@ #define TR_AUX_SERIAL_MODES "OFF","Replica Telem","Telemetria In","SBUS Trainer","LUA","CLI","GPS","Debug","SpaceMouse","Modulo esterno" #define TR_SWTYPES "Disab.","Toggle","2POS","3POS" -#define TR_POTTYPES "Disab.",TR("Pot c. fer","Pot. con centro"),TR("Multipos","Inter. Multipos"),TR("Pot","Potenziometro"),"Slider" +#define TR_POTTYPES "Disab.",TR("Pot","Potenziometro"),TR("Pot c. fer","Pot. con centro"),"Slider",TR("Multipos","Inter. Multipos"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "NO","Volo","Reset Manuale" #define TR_COUNTRY_CODES TR("US","America"),TR("JP","Japan"),TR("EU","Europa") #define TR_USBMODES TR("Chied","Chiedi"),TR("Joyst","Joystick"),TR("SDCard","Storage"),TR("Serial","Seriale") diff --git a/radio/src/translations/jp.h b/radio/src/translations/jp.h index 25cf4f640ed..ab3f2934357 100644 --- a/radio/src/translations/jp.h +++ b/radio/src/translations/jp.h @@ -50,7 +50,7 @@ #define TR_AUX_SERIAL_MODES "OFF","テレメトリーミラー","テレメトリーIN","SBUSトレーナー","LUAスクリプト","CLI","GPS","デバッグ","外部モジュール" #define TR_SWTYPES "なし","トグル","2POS","3POS" -#define TR_POTTYPES "なし",TR("Pot w. det","ダイヤル(ノッチ有)"),TR("Multipos","マルチPOSスイッチ"),"ダイヤル","スライダー" +#define TR_POTTYPES "なし","ダイヤル",TR("Pot w. det","ダイヤル(ノッチ有)"),"スライダー",TR("Multipos","マルチPOSスイッチ"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "無効","飛行時","手動リセット" #define TR_COUNTRY_CODES TR("US","アメリカ"),TR("JP","日本"),TR("EU","ヨーロッパ") #define TR_USBMODES "確認",TR("Joyst","JoyStick"),TR("SDカード","ストレージ"),"シリアル" diff --git a/radio/src/translations/nl.h b/radio/src/translations/nl.h index edb5b287609..9a8d7d66bcc 100644 --- a/radio/src/translations/nl.h +++ b/radio/src/translations/nl.h @@ -53,7 +53,7 @@ #define TR_AUX_SERIAL_MODES "UIT","Telem Mirror","Telemetry In","SBUS Leerling","LUA","CLI","GPS","Debug","SpaceMouse","External module" #define TR_SWTYPES "Geen","Wissel","2POS","3POS" -#define TR_POTTYPES "Geen",TR("Pot w. det","Pot met Klik"),TR("Multipos","Standenschakelaar"),TR("Pot", "Pot zonder Klik"),"Schuif" +#define TR_POTTYPES "Geen",TR("Pot", "Pot zonder Klik"),TR("Pot w. det","Pot met Klik"),"Schuif",TR("Multipos","Standenschakelaar"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "UIT","Vliegtijd","Handmatige Reset" #define TR_COUNTRY_CODES TR("US","Amerika"),TR("JP","Japan"),TR("EU","Europa") #define TR_USBMODES "Ask",TR("Joyst","Joystick"),TR("SDCard","Storage"),"Serial" diff --git a/radio/src/translations/pl.h b/radio/src/translations/pl.h index 7537a00dd27..28c1cce7479 100644 --- a/radio/src/translations/pl.h +++ b/radio/src/translations/pl.h @@ -52,7 +52,7 @@ #define TR_TRNCHN "KN1","KN2","KN3","KN4" #define TR_AUX_SERIAL_MODES "Wyłącz","S-Port Kopia","Telemetria","Trener SBUS","LUA","CLI","GPS","Debug","SpaceMouse","Moduł zewnętrzny" #define TR_SWTYPES "Brak","Chwil.","2POZ","3POZ" -#define TR_POTTYPES "Brak",TR("Pot w. det","Poten z zapadką"),TR("Multipos","Przeł.Wielopoz."),TR("Pot","Potencjometr"),"Suwak" +#define TR_POTTYPES "Brak",TR("Pot","Potencjometr"),TR("Pot w. det","Poten z zapadką"),"Suwak",TR("Multipos","Przeł.Wielopoz."),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "Wyłącz","Lot","Ręczny Reset" #define TR_COUNTRY_CODES TR("US","Ameryka"),TR("JP","Japonia"),TR("EU", "Europa") #define TR_USBMODES "Ask",TR("Joyst","Joystick"),TR("SDCard","Storage"),"Serial" diff --git a/radio/src/translations/pt.h b/radio/src/translations/pt.h index f44e706e7c1..bd214b189a4 100644 --- a/radio/src/translations/pt.h +++ b/radio/src/translations/pt.h @@ -53,7 +53,7 @@ #define TR_TRNCHN "CH1","CH2","CH3","CH4" #define TR_AUX_SERIAL_MODES "OFF","Espelhar Telem","Entr Telem","Trainer SBUS","LUA","CLI","GPS","Debug","SpaceMouse","External module" #define TR_SWTYPES "Nenhum","Tatil","2POS","3POS" -#define TR_POTTYPES "Nenhum",TR("Pot c. det","Pot com detentor"),TR("Multipos","Chave Multipos"),"Pot","Slider" +#define TR_POTTYPES "Nenhum","Pot",TR("Pot c. det","Pot com detentor"),"Slider",TR("Multipos","Chave Multipos"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "OFF","Voo","Reset Manual" #define TR_COUNTRY_CODES TR("US","America"),TR("JP","Japao"),TR("EU","Europa") #define TR_USBMODES "Pergunta",TR("Joyst","Joystick"),TR("SDCard","Storage"),"Serial" diff --git a/radio/src/translations/se.h b/radio/src/translations/se.h index 4ef3e32e327..511a90df77e 100644 --- a/radio/src/translations/se.h +++ b/radio/src/translations/se.h @@ -61,7 +61,7 @@ #define TR_SWTYPES "Ingen","Flipp","2 pos","3 pos" #endif -#define TR_POTTYPES "Ingen",TR("Vred m. mitt","Vred med mittläge"),TR("Multipos","Flerlägesväljare"),"Vred","Reglage" +#define TR_POTTYPES "Ingen","Vred",TR("Vred m. mitt","Vred med mittläge"),"Reglage",TR("Multipos","Flerlägesväljare"),"Axis X","Axis Y","Switch" #define TR_VPERSISTENT "Av","Flygning","Nolla själv" #define TR_COUNTRY_CODES TR("US","Amerika"),TR("JP","Japan"),TR("EU","Europa") #define TR_USBMODES "Fråga","Joystick",TR("SD-kort","SD-kortlagring"),"Seriell" diff --git a/radio/src/translations/tw.h b/radio/src/translations/tw.h index 45f5523f53a..80990b14f23 100644 --- a/radio/src/translations/tw.h +++ b/radio/src/translations/tw.h @@ -51,7 +51,7 @@ #define TR_AUX_SERIAL_MODES "禁用","回傳鏡像","回傳輸入","SBUS教練","LUA腳本","CLI","GPS","調試","SpaceMouse","外置發射" #define TR_SWTYPES "無","回彈","2段","3段" -#define TR_POTTYPES "無","有中點旋鈕","多段旋鈕","無中點旋鈕","側滑塊" +#define TR_POTTYPES "無","無中點旋鈕","有中點旋鈕","側滑塊","多段旋鈕" #define TR_VPERSISTENT "禁用","隨飛行記錄重啟","隨手動重啟" #define TR_COUNTRY_CODES "美國","日本","歐洲" #define TR_USBMODES "詢問","遊戲柄","U盤","串行" diff --git a/radio/util/hw_defs/generator.py b/radio/util/hw_defs/generator.py index 53c7f12a69a..4129fa79915 100644 --- a/radio/util/hw_defs/generator.py +++ b/radio/util/hw_defs/generator.py @@ -43,6 +43,22 @@ "KEY_BIND", ] +# def eprint(*args, **kwargs): +# from sys import stderr +# print(*args, file=stderr, **kwargs) + +def is_ext_input(input): + + if input.get('type') != 'FLEX': + return False + + name = input.get('name') + if name and name.startswith('EXT'): + return True + + return False + + def generate_from_template(json_filename, template_filename, target): with open(json_filename) as json_file: @@ -70,6 +86,8 @@ def generate_from_template(json_filename, template_filename, target): trim_blocks=True ) + env.tests['ext_input'] = is_ext_input + template_str = template_file.read() template = env.from_string(template_str) diff --git a/radio/util/hw_defs/hal_adc.py b/radio/util/hw_defs/hal_adc.py index 4cd52b853f7..e6018804f6e 100644 --- a/radio/util/hw_defs/hal_adc.py +++ b/radio/util/hw_defs/hal_adc.py @@ -12,7 +12,7 @@ def eprint(*args, **kwargs): class ADCInput: TYPE_STICK = 'STICK' - TYPE_POT = 'POT' + TYPE_FLEX = 'FLEX' TYPE_SWITCH = 'SWITCH' # TYPE_BATT = 'BATT' @@ -60,25 +60,25 @@ class ADCInputParser: }, { 'range': range(1, MAX_POTS + 1), - 'type': ADCInput.TYPE_POT, + 'type': ADCInput.TYPE_FLEX, 'suffix': 'POT{}', 'name': 'P{}', }, { 'range': range(1, MAX_SLIDERS + 1), - 'type': ADCInput.TYPE_POT, + 'type': ADCInput.TYPE_FLEX, 'suffix': 'SLIDER{}', 'name': 'SL{}', }, { 'range': range(1, MAX_EXTS + 1), - 'type': ADCInput.TYPE_POT, + 'type': ADCInput.TYPE_FLEX, 'suffix': 'EXT{}', 'name': 'EXT{}', }, { 'range': range(1, 2 + 1), - 'type': 'AXIS', + 'type': ADCInput.TYPE_FLEX, 'suffix': 'MOUSE{}', 'name': MouseName(), }, @@ -232,10 +232,10 @@ def _add_input(self, adc_input): d = self.dirs[idx] if d < 0: adc_input.inverted = True - if adc_input.type == 'POT': + if adc_input.type == 'FLEX': input_labels = self.labels[adc_input.name] - adc_input.label = input_labels['label'] - adc_input.short_label = input_labels['short_label'] + adc_input.label = input_labels.get('label') + adc_input.short_label = input_labels.get('short_label') cfg = pot_cfg_by_target(self.target,adc_input.name) if cfg: adc_input.default = cfg.get('default') diff --git a/radio/util/hw_defs/hal_adc_inputs.jinja b/radio/util/hw_defs/hal_adc_inputs.jinja index d2deddc7b00..cd947b3b890 100644 --- a/radio/util/hw_defs/hal_adc_inputs.jinja +++ b/radio/util/hw_defs/hal_adc_inputs.jinja @@ -12,25 +12,16 @@ static const etx_hal_adc_input_t _main_inputs[] = { {% endfor %} }; -{% set pot_offset = n_mains %} -{% set pot_inputs = adc_inputs.inputs | selectattr('type', '==', 'POT') | list %} -{% set n_pots = pot_inputs | count %} -static const etx_hal_adc_input_t _pot_inputs[] = { - {% for input in pot_inputs %} +{% set flex_offset = n_mains %} +{% set flex_inputs = adc_inputs.inputs | selectattr('type', '==', 'FLEX') | list %} +{% set n_flex = flex_inputs | count %} +static etx_hal_adc_input_t _flex_inputs[] = { + {% for input in flex_inputs %} { "{{ input.name }}", "{{ input.label }}", "{{ input.short_label }}" }, {% endfor %} }; -{% set axis_offset = pot_offset + n_pots %} -{% set axis_inputs = adc_inputs.inputs | selectattr('type', '==', 'AXIS') | list %} -{% set n_axis = axis_inputs | count %} -static const etx_hal_adc_input_t _axis_inputs[] = { - {% for input in axis_inputs %} - { "{{ input.name }}", "{{ input.label }}", nullptr }, - {% endfor %} -}; - -{% set vbat_offset = axis_offset + n_axis %} +{% set vbat_offset = flex_offset + n_flex %} {% set vbat_inputs = adc_inputs.inputs | selectattr('type', '==', 'VBAT') | list %} {% set n_vbat = vbat_inputs | count %} static const etx_hal_adc_input_t _vbat_inputs[] = { @@ -51,17 +42,16 @@ static const etx_hal_adc_input_t _rtc_bat_inputs[] = { {% set n_inputs = rtc_bat_offset + n_rtc_bat %} static const etx_hal_adc_inputs_t _hal_inputs[] = { { {{ n_mains }}, 0, _main_inputs }, - { {{ n_pots }}, {{ pot_offset }}, _pot_inputs }, - { {{ n_axis }}, {{ axis_offset }}, _axis_inputs }, + { {{ n_flex }}, {{ flex_offset }}, _flex_inputs }, { {{ n_vbat }}, {{ vbat_offset }}, _vbat_inputs }, { {{ n_rtc_bat }}, {{ rtc_bat_offset }}, _rtc_bat_inputs }, { {{ n_inputs }}, 0, nullptr }, }; constexpr potconfig_t _pot_default_config = (0) -{% for pot in pot_inputs %} - {% if pot.default %} - | (POT_{{ pot.default }} << ({{ loop.index0 }} * POT_CFG_BITS)) +{% for flex in flex_inputs %} + {% if flex.default %} + | ((potconfig_t)FLEX_{{ flex.default }} << ({{ loop.index0 }} * POT_CFG_BITS)) {% endif %} {% endfor %} ; diff --git a/radio/util/hw_defs/legacy_names.py b/radio/util/hw_defs/legacy_names.py index 61b052ae197..70e47544382 100644 --- a/radio/util/hw_defs/legacy_names.py +++ b/radio/util/hw_defs/legacy_names.py @@ -148,11 +148,15 @@ "JSx": { "yaml": "MOUSE1", "lua": "jsx", + "label": "JSx", + "short_label": "X", "description": "Joystick X" }, "JSy": { "yaml": "MOUSE2", "lua": "jsy", + "label": "JSy", + "short_label": "Y", "description": "Joystick Y" } } diff --git a/radio/util/hw_defs/pot_config.py b/radio/util/hw_defs/pot_config.py index a9e905200fb..459ac16e34e 100644 --- a/radio/util/hw_defs/pot_config.py +++ b/radio/util/hw_defs/pot_config.py @@ -2,9 +2,9 @@ POT_CONFIG = { "boxer": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"}, - "P3": {"default": "MULTIPOS_SWITCH"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + "P3": {"default": "MULTIPOS"} }, "el18": { "P1": { "default": "WITHOUT_DETENT"}, @@ -15,128 +15,130 @@ "P2": { "default": "WITHOUT_DETENT"} }, "tpro": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"} }, "tprov2": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"} }, "t20": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"}, - "SL3": {"default": "SLIDER_WITH_DETENT"}, - "SL4": {"default": "SLIDER_WITH_DETENT"}, + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"}, + "SL3": {"default": "SLIDER"}, + "SL4": {"default": "SLIDER"}, }, "t12": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "WITHOUT_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "POT"} }, "tx12": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"} }, "tx12mk2": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"} }, "t16": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "MULTIPOS_SWITCH"}, - "P3": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "MULTIPOS"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "t18": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "MULTIPOS_SWITCH"}, - "P3": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "MULTIPOS"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "tx16s": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "MULTIPOS_SWITCH"}, - "P3": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "MULTIPOS"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "x7": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "WITH_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "POT_CENTER"} }, "x7access": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "WITH_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "POT_CENTER"} }, "x9d": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "x9dp": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "x9dp2019": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "x9e": { - "P1": {"default": "WITH_DETENT"}, - "P2": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"}, - "SL3": {"default": "SLIDER_WITH_DETENT"}, - "SL4": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"}, + "SL3": {"default": "SLIDER"}, + "SL4": {"default": "SLIDER"} }, "x10": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "MULTIPOS_SWITCH"}, - "P3": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "MULTIPOS"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "x10express": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "MULTIPOS_SWITCH"}, - "P3": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "MULTIPOS"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"} }, "x12s": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "MULTIPOS_SWITCH"}, - "P3": {"default": "WITH_DETENT"}, - "SL1": {"default": "SLIDER_WITH_DETENT"}, - "SL2": {"default": "SLIDER_WITH_DETENT"}, - "SL3": {"default": "SLIDER_WITH_DETENT"}, - "SL4": {"default": "SLIDER_WITH_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "MULTIPOS"}, + "P3": {"default": "POT_CENTER"}, + "SL1": {"default": "SLIDER"}, + "SL2": {"default": "SLIDER"}, + "SL3": {"default": "SLIDER"}, + "SL4": {"default": "SLIDER"}, + "JSx": {"default": "AXIS_X"}, + "JSy": {"default": "AXIS_Y"} }, "xlite": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "WITHOUT_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "POT"} }, "xlites": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "WITHOUT_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "POT"} }, "x9lite": { - "P1": {"default": "WITH_DETENT"}, + "P1": {"default": "POT_CENTER"}, }, "x9lites": { - "P1": {"default": "WITH_DETENT"}, + "P1": {"default": "POT_CENTER"}, }, "zorro": { - "P1": {"default": "WITHOUT_DETENT"}, - "P2": {"default": "WITHOUT_DETENT"} + "P1": {"default": "POT"}, + "P2": {"default": "POT"} }, "pocket": { "P1": { "default": "WITHOUT_DETENT" } diff --git a/radio/util/hw_defs/simu_switches.jinja b/radio/util/hw_defs/simu_switches.jinja index d8d7fa28bdd..cb03bcbf771 100644 --- a/radio/util/hw_defs/simu_switches.jinja +++ b/radio/util/hw_defs/simu_switches.jinja @@ -1,7 +1,7 @@ {% set regular_switches = switches | selectattr('type','!=','FSWITCH') | list %} {% set function_switches = switches | selectattr('type','==','FSWITCH') | list %} -const hw_switch_def _hw_switch_defs[] = { +const hw_switch_def _switch_defs[] = { {% for switch in regular_switches %} { "{{ switch.name }}", SWITCH_HW_{{ switch.type }} }, {% endfor %} diff --git a/radio/util/hw_defs/stm32_switches.jinja b/radio/util/hw_defs/stm32_switches.jinja index 2adf187a7bc..0eab64c4ac1 100644 --- a/radio/util/hw_defs/stm32_switches.jinja +++ b/radio/util/hw_defs/stm32_switches.jinja @@ -41,6 +41,13 @@ static const stm32_switch_t _switch_defs[] = { {% endfor %} }; +static const stm32_switch_t* const _switch_offsets[] = { + _switch_defs, +{% if function_switches %} + _switch_defs + {{ regular_switches | count }}, +{% endif %} +}; + static inline void _init_switches() { LL_GPIO_InitTypeDef pinInit; @@ -56,7 +63,6 @@ static inline void _init_switches() constexpr uint8_t n_switches = {{ regular_switches | count }}; constexpr uint8_t n_fct_switches = {{ function_switches | count }}; -constexpr uint8_t n_total_switches = {{ switches | count }}; constexpr swconfig_t _switch_default_config = (swconfig_t)0 {% for sw in regular_switches %} From 1dbb4383f3e15ce6be149c5def89683c662f628d Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 5 Aug 2023 10:52:33 +0200 Subject: [PATCH 02/35] feat: add some checks around flex swicthes for colorlcd --- radio/src/gui/colorlcd/hw_inputs.cpp | 4 +++- radio/src/gui/gui_common.cpp | 29 ++++++++++++++++++++++++++++ radio/src/gui/gui_common.h | 2 ++ radio/src/hal/switch_driver.cpp | 5 +++++ radio/src/hal/switch_driver.h | 3 ++- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index 6e660d20c8e..cac12be145a 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -116,6 +116,8 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) potsChanged = true; SET_DIRTY(); }); + pot->setAvailableHandler( + [=](int val) { return isPotTypeAvailable(val); }); } } @@ -182,7 +184,7 @@ HWSwitches::HWSwitches(Window* parent) : FormWindow(parent, rect_t{}) [=]() -> int { return switchGetFlexConfig(i); }, [=](int newValue) { switchConfigFlex(i, newValue); }); channel->setAvailableHandler( - [=](int val) { return POT_CONFIG(val) == FLEX_SWITCH; }); + [=](int val) { return isFlexSwitchAvailable(i,val); }); channel->setTextHandler([=](int val) -> std::string { return adcGetInputLabel(ADC_INPUT_FLEX, val); }); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index ba26d2a11d2..f960ac6328e 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -1197,3 +1197,32 @@ uint8_t expandableSection(coord_t y, const char* title, uint8_t value, uint8_t a return value; } #endif + +bool isPotTypeAvailable(uint8_t type) +{ + if (type == FLEX_SWITCH) { + if (MAX_FLEX_SWITCHES == 0) + return false; + + auto availableFlexSwitch = MAX_FLEX_SWITCHES; + for (uint8_t i = 0; i < adcGetMaxInputs(ADC_INPUT_FLEX); i++) { + if (POT_CONFIG(i) == FLEX_SWITCH) availableFlexSwitch--; + if (availableFlexSwitch == 0) return false; + } + } + + return true; +} + +uint8_t boardGetMaxSwitches(); +bool isFlexSwitchAvailable(uint8_t swtch, uint8_t val) +{ + if (POT_CONFIG(val) != FLEX_SWITCH) + return false; + + for (uint8_t i = 0; i < MAX_FLEX_SWITCHES; i++) { + if (switchGetFlexChannel(i) == val && i != (swtch - boardGetMaxSwitches())) + return false; + } + return true; +} \ No newline at end of file diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 8bfd49e7910..f2f27b55987 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -99,6 +99,8 @@ bool isInternalModuleSupported(int moduleType); bool isRfProtocolAvailable(int protocol); bool isTrainerModeAvailable(int mode); bool isAssignableFunctionAvailable(int function, CustomFunctionData * functions); +bool isPotTypeAvailable(uint8_t type); +bool isFlexSwitchAvailable(uint8_t swtch, uint8_t val); bool isSensorUnit(int sensor, uint8_t unit); bool isCellsSensor(int sensor); diff --git a/radio/src/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp index ef3a233ee75..d99308fa4f1 100644 --- a/radio/src/hal/switch_driver.cpp +++ b/radio/src/hal/switch_driver.cpp @@ -175,6 +175,11 @@ void switchConfigFlex_raw(uint8_t idx, int8_t channel) } } +uint8_t switchGetFlexChannel(uint8_t idx) +{ + return _flex_switches[idx]; +} + void switchConfigFlex(uint8_t idx, int8_t channel) { auto max_switches = boardGetMaxSwitches(); diff --git a/radio/src/hal/switch_driver.h b/radio/src/hal/switch_driver.h index ea107ef91e3..5ad0f5a11da 100644 --- a/radio/src/hal/switch_driver.h +++ b/radio/src/hal/switch_driver.h @@ -74,13 +74,14 @@ int8_t switchGetFlexConfig(uint8_t idx); bool switchIsFlex(uint8_t idx); bool switchIsFlexValid(uint8_t idx); +uint8_t switchGetFlexChannel(uint8_t idx); + // "Raw" variants indexing only flex switches (used for storage) void switchConfigFlex_raw(uint8_t idx, int8_t channel); int8_t switchGetFlexConfig_raw(uint8_t idx); bool switchIsFlexValid_raw(uint8_t idx); - // The functions bellow support regular as well as customizable switches. // // Regular switches are indexed from `0` to `switchGetMaxSwitches() - 1` From 4f2b6ded5377aa8f1ebec185ce0a3db2a56e64ce Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 5 Aug 2023 10:52:33 +0200 Subject: [PATCH 03/35] flex switches: some color UI improvements --- radio/src/gui/colorlcd/hw_inputs.cpp | 33 ++++++++++++++++++++--- radio/src/gui/gui_common.cpp | 13 --------- radio/src/gui/gui_common.h | 1 - radio/src/hal/switch_driver.cpp | 40 ++++++++++++++++++++++++++++ radio/src/hal/switch_driver.h | 3 ++- 5 files changed, 71 insertions(+), 19 deletions(-) diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index cac12be145a..447d11e6ea4 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -113,6 +113,7 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) [=](int newValue) { g_eeGeneral.potsConfig = bfSet( g_eeGeneral.potsConfig, newValue, POT_CFG_BITS * i, POT_CFG_BITS); + switchFixFlexConfig(); potsChanged = true; SET_DIRTY(); }); @@ -161,6 +162,22 @@ class SwitchDynamicLabel : public StaticText uint8_t lastpos = 0xff; }; +static void flex_channel_changed(lv_event_t* e) +{ + auto target = lv_event_get_target(e); + auto channel = (Choice*)lv_obj_get_user_data(target); + + auto sw_cfg = (Choice*)lv_event_get_user_data(e); + lv_obj_t* sw_cfg_obj = sw_cfg->getLvObj(); + + if (channel->getIntValue() < 0) { + lv_obj_add_flag(sw_cfg_obj, LV_OBJ_FLAG_HIDDEN); + sw_cfg->setValue(0); + } else { + lv_obj_clear_flag(sw_cfg_obj, LV_OBJ_FLAG_HIDDEN); + } +} + HWSwitches::HWSwitches(Window* parent) : FormWindow(parent, rect_t{}) { FlexGridLayout grid(col_three_dsc, row_dsc, 2); @@ -178,19 +195,21 @@ HWSwitches::HWSwitches(Window* parent) : FormWindow(parent, rect_t{}) auto box_obj = box->getLvObj(); lv_obj_set_style_flex_cross_place(box_obj, LV_FLEX_ALIGN_CENTER, 0); + Choice* channel = nullptr; if (switchIsFlex(i)) { - auto channel = new Choice( - box, rect_t{}, 0, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, + channel = new Choice( + box, rect_t{}, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, [=]() -> int { return switchGetFlexConfig(i); }, [=](int newValue) { switchConfigFlex(i, newValue); }); channel->setAvailableHandler( - [=](int val) { return isFlexSwitchAvailable(i,val); }); + [=](int val) { return val < 0 || switchIsFlexInputAvailable(i, val); }); channel->setTextHandler([=](int val) -> std::string { + if (val < 0) return STR_NONE; return adcGetInputLabel(ADC_INPUT_FLEX, val); }); } - new Choice( + auto sw_cfg = new Choice( box, rect_t{}, STR_SWTYPES, SWITCH_NONE, switchGetMaxType(i), [=]() -> int { return SWITCH_CONFIG(i); }, [=](int newValue) { @@ -200,6 +219,12 @@ HWSwitches::HWSwitches(Window* parent) : FormWindow(parent, rect_t{}) ((swconfig_t(newValue) & SW_CFG_MASK) << (SW_CFG_BITS * i)); SET_DIRTY(); }); + + if (channel) { + lv_obj_t* obj = channel->getLvObj(); + lv_obj_add_event_cb(obj, flex_channel_changed, LV_EVENT_VALUE_CHANGED, sw_cfg); + lv_event_send(obj, LV_EVENT_VALUE_CHANGED, NULL); + } } } diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index f960ac6328e..02cfaade18c 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -1213,16 +1213,3 @@ bool isPotTypeAvailable(uint8_t type) return true; } - -uint8_t boardGetMaxSwitches(); -bool isFlexSwitchAvailable(uint8_t swtch, uint8_t val) -{ - if (POT_CONFIG(val) != FLEX_SWITCH) - return false; - - for (uint8_t i = 0; i < MAX_FLEX_SWITCHES; i++) { - if (switchGetFlexChannel(i) == val && i != (swtch - boardGetMaxSwitches())) - return false; - } - return true; -} \ No newline at end of file diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index f2f27b55987..b8729b3cfcd 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -100,7 +100,6 @@ bool isRfProtocolAvailable(int protocol); bool isTrainerModeAvailable(int mode); bool isAssignableFunctionAvailable(int function, CustomFunctionData * functions); bool isPotTypeAvailable(uint8_t type); -bool isFlexSwitchAvailable(uint8_t swtch, uint8_t val); bool isSensorUnit(int sensor, uint8_t unit); bool isCellsSensor(int sensor); diff --git a/radio/src/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp index d99308fa4f1..9e8849c2e50 100644 --- a/radio/src/hal/switch_driver.cpp +++ b/radio/src/hal/switch_driver.cpp @@ -216,3 +216,43 @@ bool switchIsFlexValid(uint8_t idx) idx -= max_switches; return switchIsFlexValid_raw(idx); } + +static bool is_flex_input_available(uint8_t flex_idx, uint8_t channel) +{ + for (uint8_t i = 0; i < MAX_FLEX_SWITCHES; i++) { + if (_flex_switches[i] == channel && flex_idx != i) + return false; + } + + return true; +} + +bool switchIsFlexInputAvailable(uint8_t idx, uint8_t channel) +{ + if (MAX_FLEX_SWITCHES == 0) return false; + if (POT_CONFIG(channel) != FLEX_SWITCH) return false; + + auto phy_switches = boardGetMaxSwitches(); + if (idx < phy_switches) return false; + + return is_flex_input_available(idx - phy_switches, channel); +} + +static void invalidate_flex_config(uint8_t flex_idx) +{ + auto sw_idx = flex_idx + boardGetMaxSwitches(); + swconfig_t mask = (swconfig_t)SWITCH_CONFIG_MASK(sw_idx); + g_eeGeneral.switchConfig &= ~mask; + + _flex_switches[flex_idx] = _INVALID_ADC_CH; +} + +void switchFixFlexConfig() +{ + for (uint8_t i = 0; i < MAX_FLEX_SWITCHES; i++) { + auto channel = _flex_switches[i]; + if (channel != _INVALID_ADC_CH && POT_CONFIG(channel) != FLEX_SWITCH) { + invalidate_flex_config(i); + } + } +} diff --git a/radio/src/hal/switch_driver.h b/radio/src/hal/switch_driver.h index 5ad0f5a11da..389e96a5177 100644 --- a/radio/src/hal/switch_driver.h +++ b/radio/src/hal/switch_driver.h @@ -74,8 +74,9 @@ int8_t switchGetFlexConfig(uint8_t idx); bool switchIsFlex(uint8_t idx); bool switchIsFlexValid(uint8_t idx); -uint8_t switchGetFlexChannel(uint8_t idx); +bool switchIsFlexInputAvailable(uint8_t idx, uint8_t channel); +void switchFixFlexConfig(); // "Raw" variants indexing only flex switches (used for storage) void switchConfigFlex_raw(uint8_t idx, int8_t channel); From 89eeec6145a9e75247e010aee6492d8e8a4a5319 Mon Sep 17 00:00:00 2001 From: 3djc Date: Sat, 5 Aug 2023 16:02:47 +0200 Subject: [PATCH 04/35] feat: add BW UI --- radio/src/gui/128x64/widgets.cpp | 1 + .../src/gui/common/stdlcd/radio_hardware.cpp | 72 ++++++++++++++----- radio/src/gui/gui_common.cpp | 18 +++++ radio/src/gui/gui_common.h | 1 + 4 files changed, 76 insertions(+), 16 deletions(-) diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp index 7259d17f747..5ff5a54845a 100644 --- a/radio/src/gui/128x64/widgets.cpp +++ b/radio/src/gui/128x64/widgets.cpp @@ -20,6 +20,7 @@ */ #include "opentx.h" +#include "hal/adc_driver.h" // For surface radio void drawWheel(coord_t centrex, int16_t tval) diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 48ecdf4cc5d..da323ff1b9c 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -28,6 +28,8 @@ #include "analogs.h" #include "switches.h" +uint8_t boardGetMaxSwitches(); + #if defined(BLUETOOTH) #include "bluetooth_driver.h" #endif @@ -152,7 +154,7 @@ static void _init_menu_tab_array(uint8_t* tab, size_t len) auto max_switches = switchGetMaxSwitches(); for (int i = ITEM_RADIO_HARDWARE_SWITCH; i <= ITEM_RADIO_HARDWARE_SWITCH_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_SWITCH; - tab[i] = idx < max_switches ? 1 : HIDDEN_ROW; + tab[i] = (idx < max_switches && idx < max_switches + MAX_FLEX_SWITCHES) ? 2 : idx < max_switches ? 1 : HIDDEN_ROW; } tab[ITEM_RADIO_HARDWARE_BATTERY_CALIB] = 0; @@ -502,6 +504,7 @@ void menuRadioHardware(event_t event) potType = editChoice(HW_SETTINGS_COLUMN2, y, "", STR_POTTYPES, potType, FLEX_NONE, FLEX_SWITCH, menuHorizontalPosition == 1 ? attr : 0, event); + if (checkIncDec_Ret) switchFixFlexConfig(); g_eeGeneral.potsConfig &= ~mask; g_eeGeneral.potsConfig |= (potType << shift); @@ -514,24 +517,61 @@ void menuRadioHardware(event_t event) lcdDrawText(INDENT_WIDTH, y, STR_CHAR_SWITCH, flags); lcdDrawText(lcdNextPos, y, switchGetName(index), flags); - flags = menuHorizontalPosition == 0 ? attr : 0; - if (switchHasCustomName(index) || - (attr && s_editMode > 0 && menuHorizontalPosition == 0)) { - editName(HW_SETTINGS_COLUMN1, y, (char*)switchGetCustomName(index), - LEN_SWITCH_NAME, event, flags, 0, old_editMode); - } else { - lcdDrawMMM(HW_SETTINGS_COLUMN1, y, flags); + if (switchIsFlex(index)) { + uint8_t swtch = index - boardGetMaxSwitches(); + + // flexSwitch source + flags = menuHorizontalPosition == 0 ? attr : 0; + auto source = switchGetFlexConfig_raw(swtch); + lcdDrawText(HW_SETTINGS_COLUMN1, y, (source < 0) ? STR_NONE : adcGetInputLabel(ADC_INPUT_FLEX, source), flags); + if (flags & (~RIGHT)) source = checkIncDec(event, source, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL, isFlexSwicthSourceValid); + switchConfigFlex_raw(swtch, source); + + //Name + flags = menuHorizontalPosition == 1 ? attr : 0; + if (switchHasCustomName(index) || + (attr && s_editMode > 0 && menuHorizontalPosition == 1)) { + editName(HW_SETTINGS_COLUMN2, y, + (char*)switchGetCustomName(index), LEN_SWITCH_NAME, + event, flags, 0, old_editMode); + } else { + lcdDrawMMM(HW_SETTINGS_COLUMN2, y, flags); + } + + // Switch type + flags = menuHorizontalPosition == 2 ? attr : 0; + config = editChoice(HW_SETTINGS_COLUMN2 + 25, y, "", STR_SWTYPES, config, + SWITCH_NONE, switchGetMaxType(index), flags, event); + + if (attr && checkIncDec_Ret) { + swconfig_t mask = SWITCH_CONFIG_MASK(index); + g_eeGeneral.switchConfig = + (g_eeGeneral.switchConfig & ~mask) | + ((swconfig_t(config) & SW_CFG_MASK) << (SW_CFG_BITS * index)); + } } + else { + flags = menuHorizontalPosition == 0 ? attr : 0; + if (switchHasCustomName(index) || + (attr && s_editMode > 0 && menuHorizontalPosition == 0)) { + editName(HW_SETTINGS_COLUMN1, y, + (char*)switchGetCustomName(index), LEN_SWITCH_NAME, + event, flags, 0, old_editMode); + } else { + lcdDrawMMM(HW_SETTINGS_COLUMN1, y, flags); + } - flags = menuHorizontalPosition == 1 ? attr : 0; - config = editChoice(HW_SETTINGS_COLUMN2, y, "", STR_SWTYPES, config, - SWITCH_NONE, switchGetMaxType(index), flags, event); + flags = menuHorizontalPosition == 1 ? attr : 0; + config = + editChoice(HW_SETTINGS_COLUMN2, y, "", STR_SWTYPES, config, + SWITCH_NONE, switchGetMaxType(index), flags, event); - if (attr && checkIncDec_Ret) { - swconfig_t mask = SWITCH_CONFIG_MASK(index); - g_eeGeneral.switchConfig = - (g_eeGeneral.switchConfig & ~mask) | - ((swconfig_t(config) & SW_CFG_MASK) << (SW_CFG_BITS * index)); + if (attr && checkIncDec_Ret) { + swconfig_t mask = SWITCH_CONFIG_MASK(index); + g_eeGeneral.switchConfig = + (g_eeGeneral.switchConfig & ~mask) | + ((swconfig_t(config) & SW_CFG_MASK) << (SW_CFG_BITS * index)); + } } } else if (k <= ITEM_RADIO_HARDWARE_SERIAL_PORT_END) { auto port_nr = k - ITEM_RADIO_HARDWARE_SERIAL_PORT; diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 02cfaade18c..2655e85cf05 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -1213,3 +1213,21 @@ bool isPotTypeAvailable(uint8_t type) return true; } + +bool isFlexSwicthSourceValid(int source) +{ + if (MAX_FLEX_SWITCHES == 0) return false; + + // Allow NONE + if (source < 0) return true; + + // already assigned ? + for (int i=0; i < MAX_FLEX_SWITCHES;i++) { + if (source == switchGetFlexConfig_raw(i)) + return false; + } + + if (POT_CONFIG(source) != FLEX_SWITCH) return false; + + return true; +} \ No newline at end of file diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index b8729b3cfcd..ead08c9d937 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -100,6 +100,7 @@ bool isRfProtocolAvailable(int protocol); bool isTrainerModeAvailable(int mode); bool isAssignableFunctionAvailable(int function, CustomFunctionData * functions); bool isPotTypeAvailable(uint8_t type); +bool isFlexSwicthSourceValid(int source); bool isSensorUnit(int sensor, uint8_t unit); bool isCellsSensor(int sensor); From d77c73482dcf7fe4cff636d8b7b40f04764cc3c7 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Sat, 5 Aug 2023 20:06:43 +0200 Subject: [PATCH 05/35] Cleanup --- radio/src/gui/128x64/widgets.cpp | 1 - radio/src/gui/common/stdlcd/radio_hardware.cpp | 8 ++------ radio/src/hal/switch_driver.cpp | 10 +++------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp index 5ff5a54845a..7259d17f747 100644 --- a/radio/src/gui/128x64/widgets.cpp +++ b/radio/src/gui/128x64/widgets.cpp @@ -20,7 +20,6 @@ */ #include "opentx.h" -#include "hal/adc_driver.h" // For surface radio void drawWheel(coord_t centrex, int16_t tval) diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index da323ff1b9c..b32639ffa88 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -28,8 +28,6 @@ #include "analogs.h" #include "switches.h" -uint8_t boardGetMaxSwitches(); - #if defined(BLUETOOTH) #include "bluetooth_driver.h" #endif @@ -518,14 +516,12 @@ void menuRadioHardware(event_t event) lcdDrawText(lcdNextPos, y, switchGetName(index), flags); if (switchIsFlex(index)) { - uint8_t swtch = index - boardGetMaxSwitches(); - // flexSwitch source flags = menuHorizontalPosition == 0 ? attr : 0; - auto source = switchGetFlexConfig_raw(swtch); + auto source = switchGetFlexConfig(index); lcdDrawText(HW_SETTINGS_COLUMN1, y, (source < 0) ? STR_NONE : adcGetInputLabel(ADC_INPUT_FLEX, source), flags); if (flags & (~RIGHT)) source = checkIncDec(event, source, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL, isFlexSwicthSourceValid); - switchConfigFlex_raw(swtch, source); + switchConfigFlex(index, source); //Name flags = menuHorizontalPosition == 1 ? attr : 0; diff --git a/radio/src/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp index 9e8849c2e50..ec86cd9b7d2 100644 --- a/radio/src/hal/switch_driver.cpp +++ b/radio/src/hal/switch_driver.cpp @@ -43,10 +43,6 @@ swconfig_t boardSwitchGetDefaultConfig(); constexpr uint8_t _INVALID_ADC_CH = 0xFF; -#define XSTR(x) STR(x) -#define STR(x) #x -#pragma message "MAX_FLEX_SWITCHES: " XSTR(MAX_FLEX_SWITCHES) - static uint8_t _flex_switches[MAX_FLEX_SWITCHES]; void switchInit() @@ -219,8 +215,8 @@ bool switchIsFlexValid(uint8_t idx) static bool is_flex_input_available(uint8_t flex_idx, uint8_t channel) { - for (uint8_t i = 0; i < MAX_FLEX_SWITCHES; i++) { - if (_flex_switches[i] == channel && flex_idx != i) + for (int i = 0; i < MAX_FLEX_SWITCHES; i++) { + if (_flex_switches[i] == channel && (int)flex_idx != i) return false; } @@ -249,7 +245,7 @@ static void invalidate_flex_config(uint8_t flex_idx) void switchFixFlexConfig() { - for (uint8_t i = 0; i < MAX_FLEX_SWITCHES; i++) { + for (int i = 0; i < MAX_FLEX_SWITCHES; i++) { auto channel = _flex_switches[i]; if (channel != _INVALID_ADC_CH && POT_CONFIG(channel) != FLEX_SWITCH) { invalidate_flex_config(i); From b669aae39375264ba87b8005709426648c37d0a4 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Sun, 6 Aug 2023 16:06:59 +0200 Subject: [PATCH 06/35] fix: flex switch channel offset --- radio/src/hal/switch_driver.cpp | 3 ++- radio/src/tests/switches.cpp | 27 +++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/radio/src/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp index ec86cd9b7d2..3ede2931a8b 100644 --- a/radio/src/hal/switch_driver.cpp +++ b/radio/src/hal/switch_driver.cpp @@ -84,7 +84,8 @@ SwitchHwPos switchGetPosition(uint8_t sw_idx) SwitchHwPos ret = SWITCH_HW_UP; if (channel != _INVALID_ADC_CH) { - uint16_t value = getAnalogValue(channel); + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + uint16_t value = getAnalogValue(channel + offset); if (value > 3 * 1024) { ret = SWITCH_HW_DOWN; } else if (value >= 1024) { diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index 6f73a4e87bb..58e9bb7cebb 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -343,13 +343,14 @@ TEST(FlexSwitches, switchGetPosition) switchConfigFlex(sw_idx, 0); EXPECT_TRUE(switchIsFlexValid(sw_idx)); - setAnalogValue(0, 0); + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + setAnalogValue(offset, 0); EXPECT_EQ(SWITCH_HW_UP, switchGetPosition(sw_idx)); - setAnalogValue(0, ADC_MAX_VALUE / 2); + setAnalogValue(offset, ADC_MAX_VALUE / 2); EXPECT_EQ(SWITCH_HW_MID, switchGetPosition(sw_idx)); - setAnalogValue(0, ADC_MAX_VALUE); + setAnalogValue(offset, ADC_MAX_VALUE); EXPECT_EQ(SWITCH_HW_DOWN, switchGetPosition(sw_idx)); } @@ -367,25 +368,26 @@ TEST(FlexSwitches, getValue) g_eeGeneral.switchConfig = (swconfig_t)SWITCH_3POS << (sw_idx * SW_CFG_BITS); EXPECT_EQ(SWITCH_3POS, SWITCH_CONFIG(sw_idx)); - setAnalogValue(0, 0); + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + setAnalogValue(offset, 0); EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(0, ADC_MAX_VALUE / 2); + setAnalogValue(offset, ADC_MAX_VALUE / 2); EXPECT_EQ(0, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(0, ADC_MAX_VALUE); + setAnalogValue(offset, ADC_MAX_VALUE); EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); g_eeGeneral.switchConfig = (swconfig_t)SWITCH_2POS << (sw_idx * SW_CFG_BITS); EXPECT_EQ(SWITCH_2POS, SWITCH_CONFIG(sw_idx)); - setAnalogValue(0, 0); + setAnalogValue(offset, 0); EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(0, ADC_MAX_VALUE / 2); + setAnalogValue(offset, ADC_MAX_VALUE / 2); EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(0, ADC_MAX_VALUE); + setAnalogValue(offset, ADC_MAX_VALUE); EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); } @@ -403,17 +405,18 @@ TEST(FlexSwitches, getSwitch) g_eeGeneral.switchConfig = (swconfig_t)SWITCH_3POS << (sw_idx * SW_CFG_BITS); EXPECT_EQ(SWITCH_3POS, SWITCH_CONFIG(sw_idx)); - setAnalogValue(0, 0); + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + setAnalogValue(offset, 0); EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); - setAnalogValue(0, ADC_MAX_VALUE / 2); + setAnalogValue(offset, ADC_MAX_VALUE / 2); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); - setAnalogValue(0, ADC_MAX_VALUE); + setAnalogValue(offset, ADC_MAX_VALUE); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); From f018585f2e621e3f8684c8d0c48a497db5eab83e Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 7 Aug 2023 10:23:53 +0200 Subject: [PATCH 07/35] Draft UI for POT inversion (NOT working, need YAML fixed) --- radio/src/gui/colorlcd/hw_inputs.cpp | 35 +++++++++---------- .../src/gui/common/stdlcd/radio_hardware.cpp | 20 ++++++----- radio/src/gui/gui_common.cpp | 20 +++++++++++ radio/src/gui/gui_common.h | 4 +++ radio/src/myeeprom.h | 4 ++- radio/src/opentx.h | 3 +- 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index 447d11e6ea4..f188f81a6d0 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -42,6 +42,9 @@ static const lv_coord_t col_two_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), static const lv_coord_t col_three_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t col_four_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(2),LV_GRID_FR(3), + LV_GRID_TEMPLATE_LAST}; + static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; HWSticks::HWSticks(Window* parent) : FormWindow(parent, rect_t{}) @@ -71,7 +74,7 @@ HWSticks::HWSticks(Window* parent) : FormWindow(parent, rect_t{}) HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) { - FlexGridLayout grid(col_three_dsc, row_dsc, 2); + FlexGridLayout grid(col_four_dsc, row_dsc, 2); setFlexLayout(); potsChanged = false; @@ -96,29 +99,25 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) new StaticText(line, rect_t{}, adcGetInputLabel(ADC_INPUT_FLEX, i), 0, COLOR_THEME_PRIMARY1); - auto box = new FormWindow(line, rect_t{}); - box->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(4)); - - auto box_obj = box->getLvObj(); - lv_obj_set_style_flex_cross_place(box_obj, LV_FLEX_ALIGN_CENTER, 0); - - new HWInputEdit(box, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, i), + new HWInputEdit(line, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, i), LEN_ANA_NAME); - new Choice( + auto pot = new Choice( line, rect_t{}, STR_POTTYPES, FLEX_NONE, FLEX_SWITCH, - [=]() -> int { - return bfGet(g_eeGeneral.potsConfig, POT_CFG_BITS * i, - POT_CFG_BITS); - }, + [=]() -> int { return getPotType(i); }, [=](int newValue) { - g_eeGeneral.potsConfig = bfSet( - g_eeGeneral.potsConfig, newValue, POT_CFG_BITS * i, POT_CFG_BITS); - switchFixFlexConfig(); + setPotType(i, newValue); + switchFixFlexConfig(); potsChanged = true; SET_DIRTY(); }); - pot->setAvailableHandler( - [=](int val) { return isPotTypeAvailable(val); }); + pot->setAvailableHandler([=](int val) { return isPotTypeAvailable(val); }); + + new ToggleSwitch( + line, rect_t{}, [=]() -> uint8_t { return (uint8_t)getPotInversion(i); }, + [=](int8_t newValue) { + setPotInversion(i, newValue); + SET_DIRTY(); + }); } } diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index b32639ffa88..2e7f7480613 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -146,7 +146,7 @@ static void _init_menu_tab_array(uint8_t* tab, size_t len) auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (int i = ITEM_RADIO_HARDWARE_POT; i <= ITEM_RADIO_HARDWARE_POT_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_POT; - tab[i] = idx < max_pots ? 1 : HIDDEN_ROW; + tab[i] = idx < max_pots ? 2 : HIDDEN_ROW; } auto max_switches = switchGetMaxSwitches(); @@ -479,8 +479,6 @@ void menuRadioHardware(event_t event) } else if (k <= ITEM_RADIO_HARDWARE_POT_END) { // Pots & sliders int idx = k - ITEM_RADIO_HARDWARE_POT; - uint8_t shift = (POT_CFG_BITS * idx); - potconfig_t mask = POT_CONFIG_MASK(idx); // draw hw name LcdFlags flags = menuHorizontalPosition < 0 ? attr : 0; @@ -498,15 +496,21 @@ void menuRadioHardware(event_t event) } // pot config - uint8_t potType = (g_eeGeneral.potsConfig & mask) >> shift; + uint8_t potType = getPotType(idx); potType = editChoice(HW_SETTINGS_COLUMN2, y, "", STR_POTTYPES, potType, FLEX_NONE, FLEX_SWITCH, menuHorizontalPosition == 1 ? attr : 0, event); if (checkIncDec_Ret) switchFixFlexConfig(); - g_eeGeneral.potsConfig &= ~mask; - g_eeGeneral.potsConfig |= (potType << shift); - - } else if (k <= ITEM_RADIO_HARDWARE_SWITCH_END) { + setPotType(idx, potType); + + // ADC inversion + flags = menuHorizontalPosition == 2 ? attr : 0; + bool potinversion = getPotInversion(idx); + lcdDrawChar(LCD_W - 8, y, potinversion ? 127 : 126, flags); + if (flags & (~RIGHT)) potinversion = checkIncDec(event, potinversion, 0, 1, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL); + setPotInversion(idx, potinversion); + } + else if (k <= ITEM_RADIO_HARDWARE_SWITCH_END) { // Switches int index = k - ITEM_RADIO_HARDWARE_SWITCH; int config = SWITCH_CONFIG(index); diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 2655e85cf05..a4632dd7e73 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -1230,4 +1230,24 @@ bool isFlexSwicthSourceValid(int source) if (POT_CONFIG(source) != FLEX_SWITCH) return false; return true; +} + +bool getPotInversion(int index) +{ + return bfGet(g_eeGeneral.potsConfig, (POT_CFG_BITS * index) + POT_CFG_TYPE_BITS, POT_CFG_INV_BITS); +} + +void setPotInversion(int index, bool value) +{ + g_eeGeneral.potsConfig = bfSet(g_eeGeneral.potsConfig, value, (POT_CFG_BITS * index) + POT_CFG_TYPE_BITS, POT_CFG_INV_BITS); +} + +uint8_t getPotType(int index) +{ + return bfGet(g_eeGeneral.potsConfig, POT_CFG_BITS * index, POT_CFG_TYPE_BITS); +} + +void setPotType(int index, int value) +{ + g_eeGeneral.potsConfig = bfSet(g_eeGeneral.potsConfig, value, (POT_CFG_BITS * index), POT_CFG_TYPE_BITS); } \ No newline at end of file diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index ead08c9d937..8d837b32dda 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -101,6 +101,10 @@ bool isTrainerModeAvailable(int mode); bool isAssignableFunctionAvailable(int function, CustomFunctionData * functions); bool isPotTypeAvailable(uint8_t type); bool isFlexSwicthSourceValid(int source); +bool getPotInversion(int index); +void setPotInversion(int index, bool value); +uint8_t getPotType(int index); +void setPotType(int index, int value); bool isSensorUnit(int sensor, uint8_t unit); bool isCellsSensor(int sensor); diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index f68d61e0e56..d029bef0223 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -86,7 +86,9 @@ #define MODEL_GVAR_MAX(idx) (CFN_GVAR_CST_MAX - g_model.gvars[idx].max) // pots config -#define POT_CFG_BITS 4 // 4 bits per pot +#define POT_CFG_TYPE_BITS 3 +#define POT_CFG_INV_BITS 1 +#define POT_CFG_BITS POT_CFG_TYPE_BITS + POT_CFG_INV_BITS // 4 bits per pot #define POT_CFG_MASK ((1 << POT_CFG_BITS) - 1) #define POT_CONFIG_POS(x) (POT_CFG_BITS * (x)) #define POT_CONFIG_MASK(x) (POT_CFG_MASK << POT_CONFIG_POS(x)) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index eeb0ea6f303..26fabfadae4 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -256,8 +256,7 @@ enum RotaryEncoderMode { void memswap(void * a, void * b, uint8_t size); // TODO: move these config check macros somewhere else -#define POT_CONFIG(x) \ - ((g_eeGeneral.potsConfig >> POT_CONFIG_POS(x)) & POT_CFG_MASK) +#define POT_CONFIG(x) (getPotType(x)) #define IS_POT_MULTIPOS(x) (POT_CONFIG(x) == FLEX_MULTIPOS) From 2a608bf3a4573d991c3241b42ae464ddf9d5a19d Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 7 Aug 2023 11:32:16 +0200 Subject: [PATCH 08/35] FIx --- radio/src/myeeprom.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index d029bef0223..813b3e10d8f 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -88,7 +88,7 @@ // pots config #define POT_CFG_TYPE_BITS 3 #define POT_CFG_INV_BITS 1 -#define POT_CFG_BITS POT_CFG_TYPE_BITS + POT_CFG_INV_BITS // 4 bits per pot +#define POT_CFG_BITS (POT_CFG_TYPE_BITS + POT_CFG_INV_BITS) #define POT_CFG_MASK ((1 << POT_CFG_BITS) - 1) #define POT_CONFIG_POS(x) (POT_CFG_BITS * (x)) #define POT_CONFIG_MASK(x) (POT_CFG_MASK << POT_CONFIG_POS(x)) From 6dd1eccc8981956a295741c01806ea24a0ab5c46 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 08:05:35 +0200 Subject: [PATCH 09/35] Tweak color UI --- radio/src/gui/colorlcd/hw_inputs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index f188f81a6d0..5e72289a7f3 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -42,8 +42,8 @@ static const lv_coord_t col_two_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), static const lv_coord_t col_three_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; -static const lv_coord_t col_four_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(2),LV_GRID_FR(3), - LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t col_four_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(5), + LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; From c49df8dd6e0f5f3e88e404dadb2964629704ef58 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 08:05:50 +0200 Subject: [PATCH 10/35] Persist pot inversion storage --- radio/src/storage/yaml/yaml_datastructs_funcs.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index cf033bdf814..351f31ab282 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -22,6 +22,7 @@ #include "opentx.h" #include "opentx_constants.h" #include "yaml_bits.h" +#include "yaml_node.h" #include "yaml_tree_walker.h" #include "pulses/multi.h" @@ -859,9 +860,10 @@ static const struct YamlIdStr enum_PotConfig[] = { }; static const struct YamlNode struct_potConfig[] = { - YAML_IDX_CUST( "pot", pot_read, pot_write ), - YAML_ENUM( "type", POT_CFG_BITS, enum_PotConfig), - YAML_CUSTOM( "name", pot_name_read, pot_name_write), + YAML_IDX_CUST("pot", pot_read, pot_write ), + YAML_ENUM("type", POT_CFG_TYPE_BITS, enum_PotConfig), + YAML_UNSIGNED("inv", POT_CFG_INV_BITS), + YAML_CUSTOM("name", pot_name_read, pot_name_write), YAML_END }; From f9b2080e8db5a95ce411eee7f343365a7ef2ceac Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 10:09:50 +0200 Subject: [PATCH 11/35] Diag analogs: display all flex inputs --- radio/src/gui/colorlcd/radio_diaganas.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/radio_diaganas.cpp b/radio/src/gui/colorlcd/radio_diaganas.cpp index 89dc34976af..903c32c8161 100644 --- a/radio/src/gui/colorlcd/radio_diaganas.cpp +++ b/radio/src/gui/colorlcd/radio_diaganas.cpp @@ -70,11 +70,14 @@ class AnaViewWindow: public FormWindow { { char s[10]; + auto pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); auto max_inputs = adcGetMaxInputs(ADC_INPUT_MAIN) + adcGetMaxInputs(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_inputs; i++) { - if (i > adcGetMaxInputs(ADC_INPUT_MAIN) && !IS_POT_AVAILABLE(i - adcGetMaxInputs(ADC_INPUT_MAIN))) continue; + if (i >= pot_offset && (POT_CONFIG(i - pot_offset) == FLEX_NONE)) + continue; + #if LCD_W > LCD_H if ((i & 1) == 0) line = newLine(grid); From c2226fc3062a0f475bb1631561336f5020ee254c Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 10:12:02 +0200 Subject: [PATCH 12/35] Apply ADC filter setting only on main controls --- radio/src/hal/adc_driver.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 7b00e10618b..774b60708fc 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -310,6 +310,7 @@ uint16_t getBatteryVoltage() void getADC() { + uint8_t max_mains = adcGetMaxInputs(ADC_INPUT_MAIN); uint8_t max_analogs = adcGetMaxInputs(ADC_INPUT_ALL); uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); @@ -376,13 +377,16 @@ void getADC() // Combine ADC jitter filter setting form radio and model. // Model can override (on or off) or use setting from radio setup. // Model setting is active when 1, radio setting is active when 0 - uint8_t useJitterFilter = 0; - if (g_model.jitterFilter == OVERRIDE_GLOBAL) { - // Use radio setting - which is inverted - useJitterFilter = !g_eeGeneral.noJitterFilter; - } else { - // Enable if value is "On", disable if "Off" - useJitterFilter = (g_model.jitterFilter == OVERRIDE_ON)?1:0; + // Please note: these settings only apply to main controls. + bool useJitterFilter = true; + if (x < max_mains) { + if (g_model.jitterFilter == OVERRIDE_GLOBAL) { + // Use radio setting - which is inverted + useJitterFilter = !g_eeGeneral.noJitterFilter; + } else { + // Enable if value is "On", disable if "Off" + useJitterFilter = (g_model.jitterFilter == OVERRIDE_ON); + } } if (useJitterFilter && diff < (10*ANALOG_MULTIPLIER)) { From 9ad1e075840bf205ac88a8edf0a2e52938a15968 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 10:14:18 +0200 Subject: [PATCH 13/35] Implement configurable inversion on flex inputs This might have some influence on calibration and might require re-calibrating after configuring the software inversion. --- radio/src/hal/adc_driver.cpp | 8 +++++++- radio/src/hal/switch_driver.cpp | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 774b60708fc..ccae1cd569a 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -313,6 +313,7 @@ void getADC() uint8_t max_mains = adcGetMaxInputs(ADC_INPUT_MAIN); uint8_t max_analogs = adcGetMaxInputs(ADC_INPUT_ALL); uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); + uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); #if defined(JITTER_MEASURE) if (JITTER_MEASURE_ACTIVE() && jitterResetTime < get_tmr10ms()) { @@ -335,7 +336,12 @@ void getADC() // for (uint8_t x = 0; x < max_analogs; x++) { - uint32_t v = getAnalogValue(x) >> (1 - ANALOG_SCALE); + auto raw = getAnalogValue(x); + if (x >= pot_offset && x < pot_offset + max_pots) { + if (getPotInversion(x - pot_offset)) raw = ADC_INVERT_VALUE(raw); + } + + uint32_t v = raw >> (1 - ANALOG_SCALE); // Jitter filter: // * pass trough any big change directly diff --git a/radio/src/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp index 3ede2931a8b..3c7f1d698a8 100644 --- a/radio/src/hal/switch_driver.cpp +++ b/radio/src/hal/switch_driver.cpp @@ -85,10 +85,10 @@ SwitchHwPos switchGetPosition(uint8_t sw_idx) if (channel != _INVALID_ADC_CH) { auto offset = adcGetInputOffset(ADC_INPUT_FLEX); - uint16_t value = getAnalogValue(channel + offset); - if (value > 3 * 1024) { + uint16_t value = anaIn(channel + offset); + if (value > 3 * 512) { ret = SWITCH_HW_DOWN; - } else if (value >= 1024) { + } else if (value >= 512) { ret = SWITCH_HW_MID; } } From c4dcf4e5f3968dd937324818497dba48bed174d0 Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 8 Aug 2023 11:05:41 +0200 Subject: [PATCH 14/35] fix: do not display FLEX switch on mainView until switchGetDisplayPosition() handles those --- radio/src/boards/generic_stm32/switches.cpp | 1 + radio/src/gui/128x64/view_main.cpp | 6 +++--- radio/src/gui/212x64/view_main.cpp | 4 ++-- radio/src/hal/switch_driver.h | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/radio/src/boards/generic_stm32/switches.cpp b/radio/src/boards/generic_stm32/switches.cpp index 6946757cc6c..bf7bc3525db 100644 --- a/radio/src/boards/generic_stm32/switches.cpp +++ b/radio/src/boards/generic_stm32/switches.cpp @@ -59,6 +59,7 @@ swconfig_t boardSwitchGetDefaultConfig() { return _switch_default_config; } switch_display_pos_t switchGetDisplayPosition(uint8_t idx) { + // TODO: find a solution for FLEX switches so they can be displayed on main view if (idx >= DIM(_switch_display)) return {0, 0}; return _switch_display[idx]; diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index fc343ec0366..c4c6cadac99 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -567,14 +567,14 @@ void menuMainView(event_t event) uint8_t configured_switches = 0; for (uint8_t i = 0; i < switches; i++) { - if (SWITCH_EXISTS(i)) { + if (SWITCH_EXISTS(i) && !switchIsFlex(i)) { configured_switches ++; } } if (configured_switches < 9) { for (int i = 0; i < switches; ++i) { - if (SWITCH_EXISTS(i)) { + if (SWITCH_EXISTS(i) && !switchIsFlex(i)) { auto switch_display = switchGetDisplayPosition(i); if (switch_display.row >= 3) { drawSmallSwitch(switch_display.col == 0 ? 28 : 16 * FW + 1, @@ -594,7 +594,7 @@ void menuMainView(event_t event) } else { for (int i = 0; i < switches; ++i) { - if (SWITCH_EXISTS(i)) { + if (SWITCH_EXISTS(i) && !switchIsFlex(i)) { auto switch_display = switchGetDisplayPosition(i); coord_t x = (switch_display.col == 0 ? 8 : 96) + switch_display.row * 5; drawSmallSwitch(x, 5 * FH + 1, 4, i); diff --git a/radio/src/gui/212x64/view_main.cpp b/radio/src/gui/212x64/view_main.cpp index 3a9a5a54026..c3c951ce966 100644 --- a/radio/src/gui/212x64/view_main.cpp +++ b/radio/src/gui/212x64/view_main.cpp @@ -534,7 +534,7 @@ void menuMainView(event_t event) uint8_t switches = switchGetMaxSwitches(); if (getSwitchCount() > 16) { // beware, there is a desired col/row swap in this special mode for (int i = 0; i < switches; ++i) { - if (SWITCH_EXISTS(i)) { + if (SWITCH_EXISTS(i) && !switchIsFlex(i)) { auto switch_display = switchGetDisplayPosition(i); if (g_model.view == VIEW_INPUTS) { coord_t x = 50 + (switch_display.row % 5) * 4 + @@ -552,7 +552,7 @@ void menuMainView(event_t event) else { coord_t shiftright = switchGetMaxRow(1) < 4 ? 20 : 0; for (int i = 0; i < switches; ++i) { - if (SWITCH_EXISTS(i)) { + if (SWITCH_EXISTS(i) && !switchIsFlex(i)) { auto switch_display = switchGetDisplayPosition(i); if (g_model.view == VIEW_INPUTS) { coord_t x = (switch_display.col == 0 ? 50 : 125) + diff --git a/radio/src/hal/switch_driver.h b/radio/src/hal/switch_driver.h index 389e96a5177..d2a3e157901 100644 --- a/radio/src/hal/switch_driver.h +++ b/radio/src/hal/switch_driver.h @@ -49,7 +49,7 @@ void switchInit(); // returns the factory configuration for all switches swconfig_t switchGetDefaultConfig(); -// returns the maximum number of regular switches supported in hardware +// returns the maximum number of regular switches supported in hardware (customizable switches NOT included) uint8_t switchGetMaxSwitches(); // returns the number of configured switches From e5b59c461b5ed82a9e58725cda26f7e9d0fb39bd Mon Sep 17 00:00:00 2001 From: 3djc Date: Tue, 8 Aug 2023 11:44:57 +0200 Subject: [PATCH 15/35] fix: diag keys screen layout --- radio/src/gui/colorlcd/radio_diagkeys.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/radio_diagkeys.cpp b/radio/src/gui/colorlcd/radio_diagkeys.cpp index d92d475ff11..426fbba87c4 100644 --- a/radio/src/gui/colorlcd/radio_diagkeys.cpp +++ b/radio/src/gui/colorlcd/radio_diagkeys.cpp @@ -101,9 +101,9 @@ class RadioKeyDiagsWindow : public Window coord_t y = 1; for (uint8_t i = 0; i < keysGetMaxKeys(); i++) { auto k = get_ith_key(i); - y += FH; dc->drawText(KEY_COLUMN, y, keysGetLabel(k), COLOR_THEME_PRIMARY1); displayKeyState(dc, 70, y, k); + y += FH; } #if defined(ROTARY_ENCODER_NAVIGATION) y += FH; @@ -122,12 +122,13 @@ class RadioKeyDiagsWindow : public Window } #endif // SWITCHES + y = 1; for (uint8_t i = 0; i < switchGetMaxSwitches(); i++) { if (SWITCH_EXISTS(i)) { - coord_t y = 1 + FH * i; getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i); getvalue_t sw = ((val < 0) ? 3 * i + 1 : ((val == 0) ? 3 * i + 2 : 3 * i + 3)); drawSwitch(dc, SWITCHES_COLUMN, y, sw, COLOR_THEME_PRIMARY1); + y +=FH; } } From 1906cc5a578fae0a86753b3ddd4fed2ab8597578 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 12:46:24 +0200 Subject: [PATCH 16/35] refactor: apply ADC calibration before everything else --- radio/src/hal/adc_driver.cpp | 231 ++++++++++++++++++++--------------- radio/src/mixer.cpp | 20 +-- 2 files changed, 137 insertions(+), 114 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index ccae1cd569a..8fc2c7c65c9 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -129,9 +129,9 @@ void adcCalibSetMinMax() for (uint8_t i = 0; i < max_input; i++) { auto& calib = reusableBuffer.calib.inputs[i]; + int16_t vt = getAnalogValue(i) >> 1; if (i < pot_offset || !IS_POT_MULTIPOS(i - pot_offset)) { - int16_t vt = anaIn(i); calib.input.loVal = min(vt, calib.input.loVal); calib.input.hiVal = max(vt, calib.input.hiVal); @@ -147,9 +147,6 @@ void adcCalibSetMinMax() auto& xpot = calib.xpot; int count = xpot.stepsCount; if (count <= XPOTS_MULTIPOS_COUNT) { - // use raw analog value for multipos calibraton, - // anaIn() already has multipos decoded value - int16_t vt = getAnalogValue(i) >> 1; if (xpot.lastCount == 0 || vt < xpot.lastPosition - XPOT_DELTA || vt > xpot.lastPosition + XPOT_DELTA) { xpot.lastPosition = vt; @@ -252,8 +249,8 @@ uint16_t* getAnalogValues() // used by diaganas uint32_t s_anaFilt[MAX_ANALOG_INPUTS]; -#define ANALOG_MULTIPLIER (1< 32) #error "JITTER_FILTER_STRENGTH and ANALOG_SCALE are too big, their summ should be <= 5 !!!" #endif @@ -308,12 +305,121 @@ uint16_t getBatteryVoltage() #endif } +static uint32_t apply_low_pass_filter(uint32_t v, uint32_t v_prev, + bool is_main_input) +{ + // Jitter filter: + // * pass trough any big change directly + // * for small change use Modified moving average (MMA) filter + // + // Explanation: + // + // Normal MMA filter has this formula: + // = ((ALPHA-1)* + )/ALPHA + // + // If calculation is done this way with integer arithmetics, then any small + // change in input signal is lost. One way to combat that, is to rearrange the + // formula somewhat, to store a more precise (larger) number between + // iterations. The basic idea is to store undivided value between iterations. + // Therefore an new variable is used. The new formula becomes: + // = - /ALPHA + + // = /ALPHA (use only when out is needed) + // + // The above formula with a maximum allowed ALPHA value (we are limited by + // the 16 bit s_anaFilt[]) was tested on the radio. The resulting signal still + // had some jitter (a value of 1 was observed). The jitter might be bigger on + // other radios. + // + // So another idea is to use larger input values for filtering. So instead of + // using input in a range from 0 to 2047, we use twice larger number (temp[x] + // is divided less) + // + // This also means that ALPHA must be lowered (remember 16 bit limit), but + // test results have proved that this kind of filtering gives better results. + // So the recommended values for filter are: + // JITTER_FILTER_STRENGTH 4 + // ANALOG_SCALE 1 + // + uint32_t previous = v_prev / JITTER_ALPHA; + uint32_t diff = (v > previous) ? (v - previous) : (previous - v); + + // Combine ADC jitter filter setting form radio and model. + // Model can override (on or off) or use setting from radio setup. + // Model setting is active when 1, radio setting is active when 0 + // Please note: these settings only apply to main controls. + bool useJitterFilter = true; + if (is_main_input) { + if (g_model.jitterFilter == OVERRIDE_GLOBAL) { + // Use radio setting - which is inverted + useJitterFilter = !g_eeGeneral.noJitterFilter; + } else { + // Enable if value is "On", disable if "Off" + useJitterFilter = (g_model.jitterFilter == OVERRIDE_ON); + } + } + + uint32_t out; + if (useJitterFilter && diff < (10 * ANALOG_MULTIPLIER)) { + // apply jitter filter + out = (v_prev - previous) + v; + } else { + // use unfiltered value + out = v * JITTER_ALPHA; + } + + return out; + // #if defined(JITTER_MEASURE) + // if (JITTER_MEASURE_ACTIVE()) { + // avgJitter[x].measure(ANA_FILT(x)); + // } + // #endif +} + +static uint32_t apply_calibration(const CalibData* calib, uint32_t v) +{ + // Simu uses normed inputs +#if !defined(SIMU) + // Apply calibration relative to mid-point + int32_t s = v - 2 * calib->mid; + s = s * (int32_t)RESX / + (max((int16_t)100, (s > 0 ? calib->spanPos : calib->spanNeg))); + + // Limit values to supported range + if (s < -RESX) s = -RESX; + if (s > RESX) s = RESX; + + // Translate back in range + v = s + RESX; +#endif + + return v; +} + +static uint32_t apply_multipos(const StepsCalibData* calib, uint32_t v) +{ + constexpr uint32_t ALPHA_MULT = JITTER_ALPHA * ANALOG_MULTIPLIER; + constexpr uint32_t ANAFILT_MAX = 2 * RESX * ALPHA_MULT; + + // TODO: consider adding another low pass filter to eliminate multipos + // switching glitches + uint8_t vShifted = (v / ALPHA_MULT) >> 4; + + for (uint32_t i = 0; i < calib->count; i++) { + if (vShifted < calib->steps[i]) { + return (i * (ANAFILT_MAX + ALPHA_MULT)) / calib->count; + } + } + + return ANAFILT_MAX; +} + void getADC() { - uint8_t max_mains = adcGetMaxInputs(ADC_INPUT_MAIN); - uint8_t max_analogs = adcGetMaxInputs(ADC_INPUT_ALL); - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); - uint8_t max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); + auto max_analogs = adcGetMaxInputs(ADC_INPUT_ALL); + auto max_mains = adcGetMaxInputs(ADC_INPUT_MAIN); + auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); + auto pot_offset = adcGetInputOffset(ADC_INPUT_FLEX); + auto max_calib_analogs = adcGetMaxCalibratedInputs(); #if defined(JITTER_MEASURE) if (JITTER_MEASURE_ACTIVE() && jitterResetTime < get_tmr10ms()) { @@ -322,105 +428,38 @@ void getADC() rawJitter[x].reset(); avgJitter[x].reset(); } - jitterResetTime = get_tmr10ms() + 100; //every second + jitterResetTime = get_tmr10ms() + 100; // every second } #endif DEBUG_TIMER_START(debugTimerAdcRead); - if (!adcRead()) - TRACE("adcRead failed"); + if (!adcRead()) TRACE("adcRead failed"); DEBUG_TIMER_STOP(debugTimerAdcRead); - // TODO: jitter filter should probably still be applied - // to VBAT and RTC_BAT, no matter what is configured - // for (uint8_t x = 0; x < max_analogs; x++) { + // TODO ??? ANALOG_SCALE == 1 + uint32_t v = getAnalogValue(x) >> (1 - ANALOG_SCALE); - auto raw = getAnalogValue(x); - if (x >= pot_offset && x < pot_offset + max_pots) { - if (getPotInversion(x - pot_offset)) raw = ADC_INVERT_VALUE(raw); - } - - uint32_t v = raw >> (1 - ANALOG_SCALE); - - // Jitter filter: - // * pass trough any big change directly - // * for small change use Modified moving average (MMA) filter - // - // Explanation: - // - // Normal MMA filter has this formula: - // = ((ALPHA-1)* + )/ALPHA - // - // If calculation is done this way with integer arithmetics, then any small change in - // input signal is lost. One way to combat that, is to rearrange the formula somewhat, - // to store a more precise (larger) number between iterations. The basic idea is to - // store undivided value between iterations. Therefore an new variable is - // used. The new formula becomes: - // = - /ALPHA + - // = /ALPHA (use only when out is needed) - // - // The above formula with a maximum allowed ALPHA value (we are limited by - // the 16 bit s_anaFilt[]) was tested on the radio. The resulting signal still had - // some jitter (a value of 1 was observed). The jitter might be bigger on other - // radios. - // - // So another idea is to use larger input values for filtering. So instead of using - // input in a range from 0 to 2047, we use twice larger number (temp[x] is divided less) - // - // This also means that ALPHA must be lowered (remember 16 bit limit), but test results - // have proved that this kind of filtering gives better results. So the recommended values - // for filter are: - // JITTER_FILTER_STRENGTH 4 - // ANALOG_SCALE 1 - // - // Variables mapping: - // * = v - // * = s_anaFilt[x] - uint32_t previous = s_anaFilt[x] / JITTER_ALPHA; - uint32_t diff = (v > previous) ? (v - previous) : (previous - v); - - // Combine ADC jitter filter setting form radio and model. - // Model can override (on or off) or use setting from radio setup. - // Model setting is active when 1, radio setting is active when 0 - // Please note: these settings only apply to main controls. - bool useJitterFilter = true; - if (x < max_mains) { - if (g_model.jitterFilter == OVERRIDE_GLOBAL) { - // Use radio setting - which is inverted - useJitterFilter = !g_eeGeneral.noJitterFilter; - } else { - // Enable if value is "On", disable if "Off" - useJitterFilter = (g_model.jitterFilter == OVERRIDE_ON); - } - } + bool is_flex_input = (x >= pot_offset) && (x < pot_offset + max_pots); + bool is_multipos = is_flex_input && IS_POT_MULTIPOS(x - pot_offset); - if (useJitterFilter && diff < (10*ANALOG_MULTIPLIER)) { - // apply jitter filter - s_anaFilt[x] = (s_anaFilt[x] - previous) + v; - } - else { - // use unfiltered value - s_anaFilt[x] = v * JITTER_ALPHA; + // 1st: apply calibration + if (x < max_calib_analogs && !is_multipos) { + v = apply_calibration(&g_eeGeneral.calib[x], v); } -#if defined(JITTER_MEASURE) - if (JITTER_MEASURE_ACTIVE()) { - avgJitter[x].measure(ANA_FILT(x)); + // 2nd: apply inversion + if (is_flex_input && getPotInversion(x - pot_offset)) { + v = 2 * RESX - v; } -#endif - #define ANAFILT_MAX (2 * RESX * JITTER_ALPHA * ANALOG_MULTIPLIER) - StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[x]; - if (IS_POT_MULTIPOS(x - pot_offset) && IS_MULTIPOS_CALIBRATED(calib)) { - // TODO: consider adding another low pass filter to eliminate multipos switching glitches - uint8_t vShifted = ANA_FILT(x) >> 4; - s_anaFilt[x] = ANAFILT_MAX; - for (uint32_t i = 0; i < calib->count; i++) { - if (vShifted < calib->steps[i]) { - s_anaFilt[x] = (i * (ANAFILT_MAX + JITTER_ALPHA * ANALOG_MULTIPLIER)) / calib->count; - break; - } + // 3rd: apply filtering + s_anaFilt[x] = apply_low_pass_filter(v, s_anaFilt[x], x < max_mains); + + if (is_multipos) { + const auto* calib = (const StepsCalibData*)&g_eeGeneral.calib[x]; + if (IS_MULTIPOS_CALIBRATED(calib)) { + s_anaFilt[x] = apply_multipos(calib, s_anaFilt[x]); } } } diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index cafe117d1f8..0212bb0d51c 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -506,27 +506,11 @@ void evalInputs(uint8_t mode) auto pots_offset = adcGetInputOffset(ADC_INPUT_FLEX); for (uint8_t i = 0; i < max_calib_analogs; i++) { - // normalization [0..2048] -> [-1024..1024] int16_t v = anaIn(i); uint8_t ch = (i < pots_offset ? inputMappingConvertMode(i) : i); - if (i >= pots_offset && IS_POT_MULTIPOS(i - pots_offset)) { - v -= RESX; - } - else { -#if defined(SIMU) - // Simu uses normed inputs - v -= RESX; -#else - CalibData * calib = &g_eeGeneral.calib[i]; - v -= calib->mid; - v = v * (int32_t) RESX / (max((int16_t) 100, (v > 0 ? calib->spanPos : calib->spanNeg))); -#endif - } - - // Limit values to supported range - if (v < -RESX) v = -RESX; - if (v > RESX) v = RESX; + // [0..2048] -> [-1024..1024] + v -= RESX; #if defined(STICK_DEAD_ZONE) // dead zone invented by FlySky in my opinion it should goes into ADC From 9f7699208155c9c3fa02bdffe23b423495dd5299 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 18:16:01 +0200 Subject: [PATCH 17/35] fix: value scoping while applying calibration --- radio/src/hal/adc_driver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 8fc2c7c65c9..3ed73b03315 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -385,11 +385,11 @@ static uint32_t apply_calibration(const CalibData* calib, uint32_t v) (max((int16_t)100, (s > 0 ? calib->spanPos : calib->spanNeg))); // Limit values to supported range - if (s < -RESX) s = -RESX; - if (s > RESX) s = RESX; + if (s < -2 * RESX) s = - 2 * RESX; + if (s > 2 * RESX) s = 2 * RESX; // Translate back in range - v = s + RESX; + v = s + 2 * RESX; #endif return v; From a25f62dffa16cf2a0042af815b92297c71dd2334 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Tue, 8 Aug 2023 18:25:56 +0200 Subject: [PATCH 18/35] fix: NV14 diag keys --- radio/src/gui/colorlcd/radio_diagkeys.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/radio/src/gui/colorlcd/radio_diagkeys.cpp b/radio/src/gui/colorlcd/radio_diagkeys.cpp index 426fbba87c4..1522d054f62 100644 --- a/radio/src/gui/colorlcd/radio_diagkeys.cpp +++ b/radio/src/gui/colorlcd/radio_diagkeys.cpp @@ -96,7 +96,6 @@ class RadioKeyDiagsWindow : public Window dc->drawText(TRIM_MINUS_COLUMN, 1, "-", COLOR_THEME_PRIMARY1); dc->drawText(TRIM_PLUS_COLUMN, 1, "+", COLOR_THEME_PRIMARY1); -#if !defined(PCBNV14) // KEYS coord_t y = 1; for (uint8_t i = 0; i < keysGetMaxKeys(); i++) { @@ -109,17 +108,6 @@ class RadioKeyDiagsWindow : public Window y += FH; dc->drawText(KEY_COLUMN, y, STR_ROTARY_ENCODER, COLOR_THEME_PRIMARY1); dc->drawNumber(70, y, rotaryEncoderGetValue(), COLOR_THEME_PRIMARY1); -#endif -#else // defined(PCBNV14) - // KEYS - { - coord_t y = 1; - dc->drawText(KEY_COLUMN, y, keysGetLabel(KEY_ENTER), COLOR_THEME_PRIMARY1); - displayKeyState(dc, 70, y, KEY_ENTER); - y += FH; - dc->drawText(KEY_COLUMN, y, keysGetLabel(KEY_EXIT), COLOR_THEME_PRIMARY1); - displayKeyState(dc, 70, y, KEY_EXIT); - } #endif // SWITCHES y = 1; From b3f0a1881f2c009a59eacb7e51987eec265a3f63 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Wed, 9 Aug 2023 07:06:53 +0200 Subject: [PATCH 19/35] Add default calibration --- radio/src/storage/sdcard_yaml.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/radio/src/storage/sdcard_yaml.cpp b/radio/src/storage/sdcard_yaml.cpp index f7413e121de..f47b9dfbada 100644 --- a/radio/src/storage/sdcard_yaml.cpp +++ b/radio/src/storage/sdcard_yaml.cpp @@ -19,6 +19,8 @@ * GNU General Public License for more details. */ +#include "hal/adc_driver.h" +#include "myeeprom.h" #include "opentx.h" #include "opentx_helpers.h" #include "storage.h" @@ -185,6 +187,13 @@ const char * loadRadioSettings() g_eeGeneral.internalModule = DEFAULT_INTERNAL_MODULE; #endif + for (int i = 0; i < adcGetMaxCalibratedInputs(); i++) { + CalibData* calib = &g_eeGeneral.calib[i]; + calib->mid = 1023; + calib->spanNeg = 1024 - (1024 / STICK_TOLERANCE); + calib->spanPos = 1024 - (1024 / STICK_TOLERANCE); + } + const char* error = loadRadioSettingsYaml(true); if (!error) { g_eeGeneral.chkSum = evalChkSum(); From d6b09ab1776e4541842bfa842b8651e62d9ae575 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Wed, 9 Aug 2023 07:49:35 +0200 Subject: [PATCH 20/35] Fix inversion and some cleanup --- radio/src/hal/adc_driver.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 3ed73b03315..1cac0237976 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -22,10 +22,8 @@ #include "adc_driver.h" #include "board.h" -// IS_POT_SLIDER_AVAILABLE() #include "opentx.h" - const etx_hal_adc_driver_t* _hal_adc_driver = nullptr; const etx_hal_adc_inputs_t* _hal_adc_inputs = nullptr; @@ -368,11 +366,6 @@ static uint32_t apply_low_pass_filter(uint32_t v, uint32_t v_prev, } return out; - // #if defined(JITTER_MEASURE) - // if (JITTER_MEASURE_ACTIVE()) { - // avgJitter[x].measure(ANA_FILT(x)); - // } - // #endif } static uint32_t apply_calibration(const CalibData* calib, uint32_t v) @@ -384,12 +377,17 @@ static uint32_t apply_calibration(const CalibData* calib, uint32_t v) s = s * (int32_t)RESX / (max((int16_t)100, (s > 0 ? calib->spanPos : calib->spanNeg))); + // Translate back in range + s += 2 * RESX; + // Limit values to supported range - if (s < -2 * RESX) s = - 2 * RESX; - if (s > 2 * RESX) s = 2 * RESX; + if (s < 0) { + s = 0; + } else if (s > 4 * RESX) { + s = 4 * RESX; + } - // Translate back in range - v = s + 2 * RESX; + v = s; #endif return v; @@ -437,20 +435,20 @@ void getADC() DEBUG_TIMER_STOP(debugTimerAdcRead); for (uint8_t x = 0; x < max_analogs; x++) { - // TODO ??? ANALOG_SCALE == 1 - uint32_t v = getAnalogValue(x) >> (1 - ANALOG_SCALE); bool is_flex_input = (x >= pot_offset) && (x < pot_offset + max_pots); bool is_multipos = is_flex_input && IS_POT_MULTIPOS(x - pot_offset); // 1st: apply calibration + uint32_t v = getAnalogValue(x); + if (x < max_calib_analogs && !is_multipos) { v = apply_calibration(&g_eeGeneral.calib[x], v); } // 2nd: apply inversion if (is_flex_input && getPotInversion(x - pot_offset)) { - v = 2 * RESX - v; + v = 4 * RESX - v; } // 3rd: apply filtering @@ -462,6 +460,12 @@ void getADC() s_anaFilt[x] = apply_multipos(calib, s_anaFilt[x]); } } + +#if defined(JITTER_MEASURE) + if (JITTER_MEASURE_ACTIVE()) { + avgJitter[x].measure(ANA_FILT(x)); + } +#endif } } From 8b9989a8a98a38057fa8084fbe1e9729e8403789 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Wed, 9 Aug 2023 09:50:53 +0200 Subject: [PATCH 21/35] fix: compute mid value for all inputs without a defined center --- radio/src/hal/adc_driver.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 1cac0237976..60f65bae838 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -133,13 +133,16 @@ void adcCalibSetMinMax() calib.input.loVal = min(vt, calib.input.loVal); calib.input.hiVal = max(vt, calib.input.hiVal); - if (i >= pot_offset && IS_POT_WITHOUT_DETENT(i - pot_offset)) { - calib.input.midVal = (calib.input.hiVal + calib.input.loVal) / 2; + if (i >= pot_offset) { + auto pot_cfg = POT_CONFIG(i - pot_offset); + if (pot_cfg == FLEX_POT || pot_cfg == FLEX_SWITCH || pot_cfg == FLEX_NONE) { + calib.input.midVal = (calib.input.hiVal + calib.input.loVal) / 2; + } } // in case we enough input movement, store the result if (abs(calib.input.loVal - calib.input.hiVal) > 50) { - writeAnalogCalib(i, calib.input.loVal, calib.input.midVal, calib.input.hiVal); + writeAnalogCalib(i, calib.input.loVal, calib.input.midVal, calib.input.hiVal); } } else { auto& xpot = calib.xpot; From 7e5f9f084f2ce634d627c1ee309a9b7e68d8a475 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Wed, 9 Aug 2023 10:16:49 +0200 Subject: [PATCH 22/35] fix: use default calibration on brand new config as well --- radio/src/hal/adc_driver.cpp | 10 ++++++++++ radio/src/hal/adc_driver.h | 3 +++ radio/src/opentx.cpp | 10 ++++++++-- radio/src/storage/sdcard_yaml.cpp | 7 +------ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 60f65bae838..d3aeecca414 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -69,6 +69,16 @@ bool adcRead() return true; } +void adcCalibDefaults() +{ + for (int i = 0; i < adcGetMaxCalibratedInputs(); i++) { + CalibData* calib = &g_eeGeneral.calib[i]; + calib->mid = 1023; + calib->spanNeg = 1024 - (1024 / STICK_TOLERANCE); + calib->spanPos = 1024 - (1024 / STICK_TOLERANCE); + } +} + void adcCalibSetMidPoint() { uint8_t max_inputs = adcGetMaxCalibratedInputs(); diff --git a/radio/src/hal/adc_driver.h b/radio/src/hal/adc_driver.h index 86e76ca9ae5..863d38ba4d3 100644 --- a/radio/src/hal/adc_driver.h +++ b/radio/src/hal/adc_driver.h @@ -91,6 +91,9 @@ uint16_t* getAnalogValues(); // Run calibration steps: +// Set default values before loading radio settings +void adcCalibDefaults(); + // Set mid-points and reset min/max in temporary buffer void adcCalibSetMidPoint(); diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 73e099d9f37..1e030a6ca3e 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -277,6 +277,8 @@ void generalDefault() g_eeGeneral.internalModule = DEFAULT_INTERNAL_MODULE; #endif + adcCalibDefaults(); + g_eeGeneral.potsConfig = adcGetDefaultPotsConfig(); g_eeGeneral.switchConfig = switchGetDefaultConfig(); @@ -359,9 +361,13 @@ void generalDefault() uint16_t evalChkSum() { uint16_t sum = 0; - const int16_t * calibValues = (const int16_t *) &g_eeGeneral.calib[0]; - for (int i=0; i<12; i++) + auto main_calib_words = adcGetMaxInputs(ADC_INPUT_MAIN) + * sizeof(CalibData) / 2; + + const int16_t * calibValues = (const int16_t *)&g_eeGeneral.calib[0]; + for (int i = 0; i < main_calib_words; i++) { sum += calibValues[i]; + } return sum; } diff --git a/radio/src/storage/sdcard_yaml.cpp b/radio/src/storage/sdcard_yaml.cpp index f47b9dfbada..85c186295c1 100644 --- a/radio/src/storage/sdcard_yaml.cpp +++ b/radio/src/storage/sdcard_yaml.cpp @@ -187,12 +187,7 @@ const char * loadRadioSettings() g_eeGeneral.internalModule = DEFAULT_INTERNAL_MODULE; #endif - for (int i = 0; i < adcGetMaxCalibratedInputs(); i++) { - CalibData* calib = &g_eeGeneral.calib[i]; - calib->mid = 1023; - calib->spanNeg = 1024 - (1024 / STICK_TOLERANCE); - calib->spanPos = 1024 - (1024 / STICK_TOLERANCE); - } + adcCalibDefaults(); const char* error = loadRadioSettingsYaml(true); if (!error) { From 9b11070404779029f42e54008158d5035b2e7cca Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Wed, 9 Aug 2023 10:27:20 +0200 Subject: [PATCH 23/35] fix: flex switch unit tests --- radio/src/tests/switches.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index 58e9bb7cebb..f4d63183df7 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -344,13 +344,13 @@ TEST(FlexSwitches, switchGetPosition) EXPECT_TRUE(switchIsFlexValid(sw_idx)); auto offset = adcGetInputOffset(ADC_INPUT_FLEX); - setAnalogValue(offset, 0); + anaSetFiltered(offset, -1024); EXPECT_EQ(SWITCH_HW_UP, switchGetPosition(sw_idx)); - setAnalogValue(offset, ADC_MAX_VALUE / 2); + anaSetFiltered(offset, 0); EXPECT_EQ(SWITCH_HW_MID, switchGetPosition(sw_idx)); - setAnalogValue(offset, ADC_MAX_VALUE); + anaSetFiltered(offset, +1024); EXPECT_EQ(SWITCH_HW_DOWN, switchGetPosition(sw_idx)); } @@ -369,25 +369,25 @@ TEST(FlexSwitches, getValue) EXPECT_EQ(SWITCH_3POS, SWITCH_CONFIG(sw_idx)); auto offset = adcGetInputOffset(ADC_INPUT_FLEX); - setAnalogValue(offset, 0); + anaSetFiltered(offset, -1024); EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(offset, ADC_MAX_VALUE / 2); + anaSetFiltered(offset, 0); EXPECT_EQ(0, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(offset, ADC_MAX_VALUE); + anaSetFiltered(offset, +1024); EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); g_eeGeneral.switchConfig = (swconfig_t)SWITCH_2POS << (sw_idx * SW_CFG_BITS); EXPECT_EQ(SWITCH_2POS, SWITCH_CONFIG(sw_idx)); - setAnalogValue(offset, 0); + anaSetFiltered(offset, -1024); EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(offset, ADC_MAX_VALUE / 2); + anaSetFiltered(offset, 0); EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); - setAnalogValue(offset, ADC_MAX_VALUE); + anaSetFiltered(offset, +1024); EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); } @@ -406,17 +406,17 @@ TEST(FlexSwitches, getSwitch) EXPECT_EQ(SWITCH_3POS, SWITCH_CONFIG(sw_idx)); auto offset = adcGetInputOffset(ADC_INPUT_FLEX); - setAnalogValue(offset, 0); + anaSetFiltered(offset, -1024); EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); - setAnalogValue(offset, ADC_MAX_VALUE / 2); + anaSetFiltered(offset, 0); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); - setAnalogValue(offset, ADC_MAX_VALUE); + anaSetFiltered(offset, +1024); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3)); EXPECT_EQ(false, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 1)); EXPECT_EQ(true, getSwitch(SWSRC_FIRST_SWITCH + sw_idx * 3 + 2)); From 050a72d0705eb886f4a5b5c185545cf7e2469f89 Mon Sep 17 00:00:00 2001 From: 3djc Date: Wed, 9 Aug 2023 16:18:22 +0200 Subject: [PATCH 24/35] fix: legacy import --- radio/util/hw_defs/yaml_inputs.jinja | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/radio/util/hw_defs/yaml_inputs.jinja b/radio/util/hw_defs/yaml_inputs.jinja index ef3535c61a0..f36f24bd25d 100644 --- a/radio/util/hw_defs/yaml_inputs.jinja +++ b/radio/util/hw_defs/yaml_inputs.jinja @@ -4,8 +4,7 @@ // {% set main_inputs = adc_inputs.inputs | selectattr('type', '==', 'STICK') | list %} -{% set pot_inputs = adc_inputs.inputs | selectattr('type', '==', 'POT') | list %} -{% set axis_inputs = adc_inputs.inputs | selectattr('type', '==', 'AXIS') | list %} +{% set flex_inputs = adc_inputs.inputs | selectattr('type', '==', 'FLEX') | list %} struct legacy_input_t { const char* legacy; @@ -17,12 +16,8 @@ static const legacy_input_t _legacy_inputs[] = { {% set li = legacy_inputs[input.name] %} { "{{ li.yaml }}", MIXSRC_FIRST_STICK + {{ loop.index0 }} }, {% endfor %} - {% for input in pot_inputs %} + {% for input in flex_inputs %} {% set li = legacy_inputs[input.name] %} { "{{ li.yaml }}", MIXSRC_FIRST_POT + {{ loop.index0 }} }, {% endfor %} - {% for input in axis_inputs %} - {% set li = legacy_inputs[input.name] %} - { "{{ li.yaml }}", MIXSRC_FIRST_AXIS + {{ loop.index0 }} }, - {% endfor %} }; From 8fe6a0e70ce6a1f89ef22d2388fff37fb7cb3ff2 Mon Sep 17 00:00:00 2001 From: 3djc Date: Thu, 10 Aug 2023 08:26:04 +0200 Subject: [PATCH 25/35] fix: typo (thx @elecpower) --- radio/src/gui/common/stdlcd/radio_hardware.cpp | 2 +- radio/src/gui/gui_common.cpp | 2 +- radio/src/gui/gui_common.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 2e7f7480613..78eac767910 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -524,7 +524,7 @@ void menuRadioHardware(event_t event) flags = menuHorizontalPosition == 0 ? attr : 0; auto source = switchGetFlexConfig(index); lcdDrawText(HW_SETTINGS_COLUMN1, y, (source < 0) ? STR_NONE : adcGetInputLabel(ADC_INPUT_FLEX, source), flags); - if (flags & (~RIGHT)) source = checkIncDec(event, source, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL, isFlexSwicthSourceValid); + if (flags & (~RIGHT)) source = checkIncDec(event, source, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL, isFlexSwitchSourceValid); switchConfigFlex(index, source); //Name diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index a4632dd7e73..a76a72080ee 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -1214,7 +1214,7 @@ bool isPotTypeAvailable(uint8_t type) return true; } -bool isFlexSwicthSourceValid(int source) +bool isFlexSwitchSourceValid(int source) { if (MAX_FLEX_SWITCHES == 0) return false; diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 8d837b32dda..e213b4eb00e 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -100,7 +100,7 @@ bool isRfProtocolAvailable(int protocol); bool isTrainerModeAvailable(int mode); bool isAssignableFunctionAvailable(int function, CustomFunctionData * functions); bool isPotTypeAvailable(uint8_t type); -bool isFlexSwicthSourceValid(int source); +bool isFlexSwitchSourceValid(int source); bool getPotInversion(int index); void setPotInversion(int index, bool value); uint8_t getPotType(int index); From b43a880a469981fe343b99d76c1f385c056b4a68 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Sun, 3 Sep 2023 10:45:56 +0200 Subject: [PATCH 26/35] Fix POCKET pot definition --- radio/util/hw_defs/pot_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/util/hw_defs/pot_config.py b/radio/util/hw_defs/pot_config.py index 459ac16e34e..bcd32ae4f0f 100644 --- a/radio/util/hw_defs/pot_config.py +++ b/radio/util/hw_defs/pot_config.py @@ -141,7 +141,7 @@ "P2": {"default": "POT"} }, "pocket": { - "P1": { "default": "WITHOUT_DETENT" } + "P1": {"default": "POT"} }, } From e15674832bb0517ebc5d07ff28d6fa9a9580fc93 Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Fri, 29 Sep 2023 08:59:10 +0200 Subject: [PATCH 27/35] Fix model data size checks --- radio/src/datastructs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index f35d37e2ae9..f87d84b7df6 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -147,14 +147,14 @@ static inline void check_struct() CHKSIZE(ModelData, 6706); #elif defined(PCBHORUS) #if defined(PCBX10) - CHKSIZE(RadioData, 848); + CHKSIZE(RadioData, 836); CHKSIZE(ModelData, 15607); #else - CHKSIZE(RadioData, 848); + CHKSIZE(RadioData, 836); CHKSIZE(ModelData, 15607); #endif #elif defined(PCBNV14) - CHKSIZE(RadioData, 848); + CHKSIZE(RadioData, 836); CHKSIZE(ModelData, 15463); #endif From cd0559601797c7b7fde37b96f5d282101ea904ac Mon Sep 17 00:00:00 2001 From: raphaelcoeffic Date: Fri, 29 Sep 2023 09:15:27 +0200 Subject: [PATCH 28/35] Fix NV14 / EL18 --- radio/src/gui/colorlcd/radio_diagkeys.cpp | 4 +--- radio/util/hw_defs/pot_config.py | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/radio/src/gui/colorlcd/radio_diagkeys.cpp b/radio/src/gui/colorlcd/radio_diagkeys.cpp index 1522d054f62..a12c102e85c 100644 --- a/radio/src/gui/colorlcd/radio_diagkeys.cpp +++ b/radio/src/gui/colorlcd/radio_diagkeys.cpp @@ -27,7 +27,6 @@ static const uint8_t _trimMap[MAX_TRIMS * 2] = {6, 7, 4, 5, 2, 3, 0, 1, 8, 9, 10, 11}; -#if !defined(PCBNV14) static EnumKeys get_ith_key(uint8_t i) { auto supported_keys = keysGetSupported(); @@ -41,7 +40,6 @@ static EnumKeys get_ith_key(uint8_t i) // we assume: i < keysGetMaxKeys() return (EnumKeys)0; } -#endif class RadioKeyDiagsWindow : public Window { @@ -104,7 +102,7 @@ class RadioKeyDiagsWindow : public Window displayKeyState(dc, 70, y, k); y += FH; } -#if defined(ROTARY_ENCODER_NAVIGATION) +#if defined(ROTARY_ENCODER_NAVIGATION) && !defined(USE_HATS_AS_KEYS) y += FH; dc->drawText(KEY_COLUMN, y, STR_ROTARY_ENCODER, COLOR_THEME_PRIMARY1); dc->drawNumber(70, y, rotaryEncoderGetValue(), COLOR_THEME_PRIMARY1); diff --git a/radio/util/hw_defs/pot_config.py b/radio/util/hw_defs/pot_config.py index bcd32ae4f0f..d5088e747f1 100644 --- a/radio/util/hw_defs/pot_config.py +++ b/radio/util/hw_defs/pot_config.py @@ -7,12 +7,12 @@ "P3": {"default": "MULTIPOS"} }, "el18": { - "P1": { "default": "WITHOUT_DETENT"}, - "P2": { "default": "WITHOUT_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"} }, "nv14": { - "P1": { "default": "WITHOUT_DETENT"}, - "P2": { "default": "WITHOUT_DETENT"} + "P1": {"default": "POT_CENTER"}, + "P2": {"default": "POT_CENTER"} }, "tpro": { "P1": {"default": "POT_CENTER"}, From e48a9a94622e8ee2101a0c237ec98a8ca0af607a Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Fri, 27 Oct 2023 16:17:51 +1000 Subject: [PATCH 29/35] fix: Think should now be `ADC_INPUT_FLEX` --- radio/src/gui/gui_common.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index a76a72080ee..741ccb19f87 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -379,7 +379,7 @@ bool isSwitchAvailable(int swtch, SwitchContext context) if (swtch >= SWSRC_FIRST_MULTIPOS_SWITCH && swtch <= SWSRC_LAST_MULTIPOS_SWITCH) { int index = (swtch - SWSRC_FIRST_MULTIPOS_SWITCH) / XPOTS_MULTIPOS_COUNT; - return (index < adcGetMaxInputs(ADC_INPUT_POT)) ? IS_POT_MULTIPOS(index) : false; + return (index < adcGetMaxInputs(ADC_INPUT_FLEX)) ? IS_POT_MULTIPOS(index) : false; } if (swtch >= SWSRC_FIRST_TRIM && swtch <= SWSRC_LAST_TRIM) { From a51f183383a534d00ae78d2c678096e13a14c6ca Mon Sep 17 00:00:00 2001 From: philmoz Date: Mon, 30 Oct 2023 22:05:25 +1100 Subject: [PATCH 30/35] Fix portrait layout. --- radio/src/gui/colorlcd/hw_inputs.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index 5e72289a7f3..8ec168774bc 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -39,11 +39,16 @@ struct HWInputEdit : public RadioTextEdit { static const lv_coord_t col_two_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; -static const lv_coord_t col_three_dsc[] = { - LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t col_three_dsc[] = {LV_GRID_FR(8), LV_GRID_FR(12), LV_GRID_FR(20), + LV_GRID_TEMPLATE_LAST}; -static const lv_coord_t col_four_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(5), +#if LCD_W > LCD_H +static const lv_coord_t pots_col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(5), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; +#else +static const lv_coord_t pots_col_dsc[] = {LV_GRID_FR(24), LV_GRID_FR(50), LV_GRID_FR(16), + LV_GRID_TEMPLATE_LAST}; +#endif static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; @@ -74,7 +79,7 @@ HWSticks::HWSticks(Window* parent) : FormWindow(parent, rect_t{}) HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) { - FlexGridLayout grid(col_four_dsc, row_dsc, 2); + FlexGridLayout grid(pots_col_dsc, row_dsc, 2); setFlexLayout(); potsChanged = false; @@ -99,6 +104,10 @@ HWPots::HWPots(Window* parent) : FormWindow(parent, rect_t{}) new StaticText(line, rect_t{}, adcGetInputLabel(ADC_INPUT_FLEX, i), 0, COLOR_THEME_PRIMARY1); +#if LCD_H > LCD_W + line = newLine(&grid); +#endif + new HWInputEdit(line, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, i), LEN_ANA_NAME); auto pot = new Choice( @@ -190,9 +199,7 @@ HWSwitches::HWSwitches(Window* parent) : FormWindow(parent, rect_t{}) auto box = new FormWindow(line, rect_t{}); box->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(4)); - - auto box_obj = box->getLvObj(); - lv_obj_set_style_flex_cross_place(box_obj, LV_FLEX_ALIGN_CENTER, 0); + box->setWidth(lv_pct(45)); Choice* channel = nullptr; if (switchIsFlex(i)) { @@ -234,7 +241,11 @@ HWInputDialog::HWInputDialog(const char* title) : setCloseWhenClickOutside(true); if (title) content->setTitle(title); new T(&content->form); +#if LCD_W > LCD_H content->setWidth(LCD_W * 0.8); +#else + content->setWidth(LCD_W * 0.95); +#endif content->updateSize(); } From 74708fd2ff8ed0a13aef568fe3e6d312616b52e1 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Mon, 30 Oct 2023 21:34:32 +1000 Subject: [PATCH 31/35] fix: Audio MULTIPOS test --- radio/src/tests/model_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/tests/model_audio.cpp b/radio/src/tests/model_audio.cpp index 3254e092215..31b2a1d3c55 100644 --- a/radio/src/tests/model_audio.cpp +++ b/radio/src/tests/model_audio.cpp @@ -74,7 +74,7 @@ TEST(ModelAudio, switches) EXPECT_FALSE(matchSwitchAudioFile("SX-mid.wav", sw_pos)); EXPECT_FALSE(matchSwitchAudioFile("AS-mid.wav", sw_pos)); - g_eeGeneral.potsConfig = POT_MULTIPOS_SWITCH << (POT_CFG_BITS * 2); + g_eeGeneral.potsConfig = FLEX_MULTIPOS << (POT_CFG_BITS * 2); EXPECT_TRUE(matchSwitchAudioFile("S34.wav", sw_pos)); EXPECT_EQ(MAX_SWITCHES * 3 + 2 * XPOTS_MULTIPOS_COUNT + 3, sw_pos); From 740ee0091663073374b51194d6dea4fbaa307a52 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Mon, 30 Oct 2023 21:50:12 +1000 Subject: [PATCH 32/35] fix: Seems like wrong header name --- radio/src/tests/switches.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index f4d63183df7..12cb3f037fd 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -20,7 +20,6 @@ */ #include "dataconstants.h" -#include "gtest.h" #include "gtests.h" #include "myeeprom.h" From 3eef459c595502d5e14bda13ff01a65a85a9069b Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Tue, 31 Oct 2023 09:17:22 +1000 Subject: [PATCH 33/35] fix: portrait still had a couple pixels of scroll --- radio/src/gui/colorlcd/hw_inputs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index 8ec168774bc..813a23d8d17 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -46,7 +46,7 @@ static const lv_coord_t col_three_dsc[] = {LV_GRID_FR(8), LV_GRID_FR(12), LV_GRI static const lv_coord_t pots_col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(2), LV_GRID_FR(5), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; #else -static const lv_coord_t pots_col_dsc[] = {LV_GRID_FR(24), LV_GRID_FR(50), LV_GRID_FR(16), +static const lv_coord_t pots_col_dsc[] = {LV_GRID_FR(22), LV_GRID_FR(48), LV_GRID_FR(16), LV_GRID_TEMPLATE_LAST}; #endif From 5dab732d6f9828ed8e491027e8d1987492ae2a79 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Wed, 1 Nov 2023 20:54:41 +1000 Subject: [PATCH 34/35] fix: alignment issue (thanks @raphaelcoeffic) --- radio/src/opentx.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 1e030a6ca3e..7aba20149e9 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -361,11 +361,11 @@ void generalDefault() uint16_t evalChkSum() { uint16_t sum = 0; - auto main_calib_words = adcGetMaxInputs(ADC_INPUT_MAIN) - * sizeof(CalibData) / 2; + auto main_calib_bytes = adcGetMaxInputs(ADC_INPUT_MAIN) + * sizeof(CalibData); - const int16_t * calibValues = (const int16_t *)&g_eeGeneral.calib[0]; - for (int i = 0; i < main_calib_words; i++) { + const uint8_t * calibValues = (const uint8_t *)&g_eeGeneral.calib[0]; + for (unsigned i = 0; i < main_calib_bytes; i++) { sum += calibValues[i]; } return sum; From bf394f3e6df65dc5da3344b3cf1ad74984cefd39 Mon Sep 17 00:00:00 2001 From: Peter Feerick Date: Thu, 2 Nov 2023 09:28:34 +1000 Subject: [PATCH 35/35] chore: Formatting --- radio/src/opentx.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 7aba20149e9..35f992eb274 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -361,10 +361,9 @@ void generalDefault() uint16_t evalChkSum() { uint16_t sum = 0; - auto main_calib_bytes = adcGetMaxInputs(ADC_INPUT_MAIN) - * sizeof(CalibData); + auto main_calib_bytes = adcGetMaxInputs(ADC_INPUT_MAIN) * sizeof(CalibData); - const uint8_t * calibValues = (const uint8_t *)&g_eeGeneral.calib[0]; + const uint8_t *calibValues = (const uint8_t *)&g_eeGeneral.calib[0]; for (unsigned i = 0; i < main_calib_bytes; i++) { sum += calibValues[i]; }