diff --git a/radio/src/boards/generic_stm32/switches.cpp b/radio/src/boards/generic_stm32/switches.cpp index 5c72fb0dd..bf7bc3525 100644 --- a/radio/src/boards/generic_stm32/switches.cpp +++ b/radio/src/boards/generic_stm32/switches.cpp @@ -32,80 +32,35 @@ #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]); } +const char* boardSwitchGetName(uint8_t cat, uint8_t idx) +{ + return _switch_offsets[cat][idx].name; +} + +SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx) +{ + return _switch_offsets[cat][idx].type; +} + +uint8_t boardGetMaxSwitches() { return n_switches; } +uint8_t boardGetMaxFctSwitches() { return n_fct_switches; } + +swconfig_t boardSwitchGetDefaultConfig() { return _switch_default_config; } + switch_display_pos_t switchGetDisplayPosition(uint8_t idx) { - if (idx >= DIM(_switch_display)) - return {0, 0}; + // 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]; } - -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) -{ - 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; -} - -uint8_t switchGetMaxFctSwitches() -{ - return n_fct_switches; -} - -// 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); -} - -SwitchHwPos switchGetPosition(uint8_t idx) -{ - if (idx >= n_total_switches) return SWITCH_HW_UP; - return stm32_switch_get_position(&_switch_defs[idx]); -} - -const char* switchGetName(uint8_t idx) -{ - if (idx >= n_total_switches) return ""; - return _switch_defs[idx].name; -} - -SwitchHwType switchGetHwType(uint8_t idx) -{ - if (idx >= n_total_switches) return SWITCH_HW_2POS; - return _switch_defs[idx].type; -} diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index 24bddd66f..60af23702 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.h b/radio/src/datastructs.h index f35d37e2a..f87d84b7d 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 diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index 9660466fb..0582c28a4 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 ddcb6714e..fdc8ff04c 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 8250bb595..c4c6cadac 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++) { @@ -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/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp index 624d3cf3b..5d2ceceac 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 33fb1241f..e3676ba39 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 6b78c4222..c3c951ce9 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++) { @@ -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/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index 2bc899213..813a23d8d 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -39,8 +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}; + +#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(22), LV_GRID_FR(48), LV_GRID_FR(16), + LV_GRID_TEMPLATE_LAST}; +#endif static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; @@ -71,7 +79,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(pots_col_dsc, row_dsc, 2); setFlexLayout(); potsChanged = false; @@ -83,7 +91,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,29 +101,32 @@ 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{}); - box->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(4)); +#if LCD_H > LCD_W + line = newLine(&grid); +#endif - 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(line, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, i), LEN_ANA_NAME); - new Choice( - box, rect_t{}, STR_POTTYPES, POT_NONE, POT_SLIDER_WITH_DETENT, - [=]() -> int { - return bfGet(g_eeGeneral.potsConfig, POT_CFG_BITS * i, - POT_CFG_BITS); - }, + auto pot = new Choice( + line, rect_t{}, STR_POTTYPES, FLEX_NONE, FLEX_SWITCH, + [=]() -> int { return getPotType(i); }, [=](int newValue) { - g_eeGeneral.potsConfig = bfSet( - g_eeGeneral.potsConfig, newValue, POT_CFG_BITS * i, POT_CFG_BITS); + setPotType(i, newValue); + switchFixFlexConfig(); potsChanged = true; SET_DIRTY(); }); + 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(); + }); } } @@ -130,7 +141,7 @@ class SwitchDynamicLabel : public StaticText std::string label() { - std::string str(switchGetName(index)); + std::string str(switchGetCanonicalName(index)); return str + getSwitchPositionSymbol(lastpos); } @@ -159,18 +170,53 @@ 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); 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); - new Choice( - line, rect_t{}, STR_SWTYPES, SWITCH_NONE, switchGetMaxType(i), + + auto box = new FormWindow(line, rect_t{}); + box->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(4)); + box->setWidth(lv_pct(45)); + + Choice* channel = nullptr; + if (switchIsFlex(i)) { + 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 val < 0 || switchIsFlexInputAvailable(i, val); }); + channel->setTextHandler([=](int val) -> std::string { + if (val < 0) return STR_NONE; + return adcGetInputLabel(ADC_INPUT_FLEX, val); + }); + } + + auto sw_cfg = new Choice( + 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); @@ -179,6 +225,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); + } } } @@ -189,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(); } diff --git a/radio/src/gui/colorlcd/layouts/sliders.cpp b/radio/src/gui/colorlcd/layouts/sliders.cpp index 08519a93b..799540de6 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 12b946f75..b3353dfee 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 9e93cc0d4..903c32c81 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_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; + if (i >= pot_offset && (POT_CONFIG(i - pot_offset) == FLEX_NONE)) + continue; + #if LCD_W > LCD_H if ((i & 1) == 0) line = newLine(grid); @@ -316,7 +319,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 +328,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 +422,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 +440,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/radio_diagkeys.cpp b/radio/src/gui/colorlcd/radio_diagkeys.cpp index d92d475ff..a12c102e8 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 { @@ -96,38 +94,27 @@ 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++) { 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) +#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); -#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; 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; } } diff --git a/radio/src/gui/colorlcd/view_main_decoration.cpp b/radio/src/gui/colorlcd/view_main_decoration.cpp index e7862d418..efe1d1511 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 c085e9c6a..78eac7679 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -143,16 +143,16 @@ 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; + tab[i] = idx < max_pots ? 2 : HIDDEN_ROW; } 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; @@ -479,33 +479,38 @@ 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; 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); } // pot config - uint8_t potType = (g_eeGeneral.potsConfig & mask) >> shift; + uint8_t potType = getPotType(idx); 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); + if (checkIncDec_Ret) switchFixFlexConfig(); + setPotType(idx, potType); - } else if (k <= ITEM_RADIO_HARDWARE_SWITCH_END) { + // 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); @@ -514,24 +519,59 @@ 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)) { + // flexSwitch source + 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, isFlexSwitchSourceValid); + switchConfigFlex(index, 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 5f784b6a4..741ccb19f 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; @@ -391,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) { @@ -1209,3 +1197,57 @@ 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; +} + +bool isFlexSwitchSourceValid(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; +} + +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 8bfd49e79..e213b4eb0 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -99,6 +99,12 @@ bool isInternalModuleSupported(int moduleType); bool isRfProtocolAvailable(int protocol); bool isTrainerModeAvailable(int mode); bool isAssignableFunctionAvailable(int function, CustomFunctionData * functions); +bool isPotTypeAvailable(uint8_t type); +bool isFlexSwitchSourceValid(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/hal/CMakeLists.txt b/radio/src/hal/CMakeLists.txt index ac7c8a232..856bbc976 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 5dd4dc030..d3aeecca4 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; @@ -71,10 +69,20 @@ 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(); - 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,32 +132,32 @@ 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++) { 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); - 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; 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; @@ -192,8 +200,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)) { @@ -252,8 +260,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,10 +316,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; +} + +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))); + + // Translate back in range + s += 2 * RESX; + + // Limit values to supported range + if (s < 0) { + s = 0; + } else if (s > 4 * RESX) { + s = 4 * RESX; + } + + v = s; +#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_analogs = adcGetMaxInputs(ADC_INPUT_ALL); - uint8_t pot_offset = adcGetInputOffset(ADC_INPUT_POT); + 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()) { @@ -320,78 +439,39 @@ 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++) { - 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); - // 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); + // 1st: apply calibration + uint32_t v = getAnalogValue(x); - // 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; + if (x < max_calib_analogs && !is_multipos) { + v = apply_calibration(&g_eeGeneral.calib[x], v); } - if (useJitterFilter && diff < (10*ANALOG_MULTIPLIER)) { - // apply jitter filter - s_anaFilt[x] = (s_anaFilt[x] - previous) + v; + // 2nd: apply inversion + if (is_flex_input && getPotInversion(x - pot_offset)) { + v = 4 * RESX - v; } - else { - // use unfiltered value - s_anaFilt[x] = v * JITTER_ALPHA; + + // 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]); + } } #if defined(JITTER_MEASURE) @@ -399,20 +479,6 @@ void getADC() avgJitter[x].measure(ANA_FILT(x)); } #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; - } - } - } } } @@ -436,7 +502,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 +533,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 bf414da3f..863d38ba4 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, @@ -92,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/hal/switch_driver.cpp b/radio/src/hal/switch_driver.cpp new file mode 100644 index 000000000..3c7f1d698 --- /dev/null +++ b/radio/src/hal/switch_driver.cpp @@ -0,0 +1,255 @@ +/* + * 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; + +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) { + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + uint16_t value = anaIn(channel + offset); + if (value > 3 * 512) { + ret = SWITCH_HW_DOWN; + } else if (value >= 512) { + 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; + } +} + +uint8_t switchGetFlexChannel(uint8_t idx) +{ + return _flex_switches[idx]; +} + +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); +} + +static bool is_flex_input_available(uint8_t flex_idx, uint8_t channel) +{ + for (int i = 0; i < MAX_FLEX_SWITCHES; i++) { + if (_flex_switches[i] == channel && (int)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 (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); + } + } +} diff --git a/radio/src/hal/switch_driver.h b/radio/src/hal/switch_driver.h index 149d01b38..d2a3e1579 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 @@ -44,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 @@ -63,6 +68,21 @@ 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); +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); +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 7d8c67d6c..703fc8f1b 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 83cec454c..d25971a36 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 3e1791967..0212bb0d5 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,24 +341,13 @@ 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 (i >= adcGetMaxInputs(ADC_INPUT_FLEX)) { if (valid != nullptr) *valid = false; return 0; } - return calibratedAnalogs[i + adcGetInputOffset(ADC_INPUT_POT)]; + return calibratedAnalogs[i + adcGetInputOffset(ADC_INPUT_FLEX)]; } -#if MAX_AXIS > 0 - else if (i <= MIXSRC_LAST_AXIS) { - i -= MIXSRC_FIRST_AXIS; - if (i >= adcGetMaxInputs(ADC_INPUT_AXIS)) { - if (valid != nullptr) *valid = false; - return 0; - } - return calibratedAnalogs[i + adcGetInputOffset(ADC_INPUT_AXIS)]; - } -#endif - #if defined(IMU) else if (i == MIXSRC_TILT_X) { return gyro.scaledX(); @@ -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,30 +503,14 @@ 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] 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 diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index f68d61e0e..813b3e10d 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) #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.cpp b/radio/src/opentx.cpp index cb1f5d390..35f992eb2 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,12 @@ 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_bytes = adcGetMaxInputs(ADC_INPUT_MAIN) * sizeof(CalibData); + + 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; } @@ -403,18 +408,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 +1400,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 411bdda13..26fabfada 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -256,15 +256,21 @@ 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) == 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 45d40b882..3529c4c49 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 feb3cd060..6421a5cd6 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/sdcard_yaml.cpp b/radio/src/storage/sdcard_yaml.cpp index f7413e121..85c186295 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,8 @@ const char * loadRadioSettings() g_eeGeneral.internalModule = DEFAULT_INTERNAL_MODULE; #endif + adcCalibDefaults(); + const char* error = loadRadioSettingsYaml(true); if (!error) { g_eeGeneral.chkSum = evalChkSum(); diff --git a/radio/src/storage/yaml/yaml_datastructs_128x64.cpp b/radio/src/storage/yaml/yaml_datastructs_128x64.cpp index a2986cd6f..0b3281986 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 433904097..351f31ab2 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -20,7 +20,9 @@ */ #include "opentx.h" +#include "opentx_constants.h" #include "yaml_bits.h" +#include "yaml_node.h" #include "yaml_tree_walker.h" #include "pulses/multi.h" @@ -254,14 +256,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 +315,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 +674,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 +696,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 +760,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,35 +831,39 @@ 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 } }; 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 }; @@ -840,7 +889,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 ac83379bd..b5e9ebcf8 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 b6b9d9be9..bf5b1c38b 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 45bb5ba33..bdf710240 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 e6a3f6010..d6fef2dce 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 e6a3f6010..d6fef2dce 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 07fecdc2c..d820b7d29 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 d23ce959b..a5691efe4 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 9958d7a53..4df8ea04f 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 31a3fe3c7..0d5aea189 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 2e5cb1952..51d56d66f 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 40ba379c9..1f60d8768 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 4a7f995b2..029f55af5 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 91bede6d4..7b6fcda89 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 4d4e43921..11d67630e 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 4a38d59c8..537fb5d31 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 5cb3cc869..3c1329234 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 92251a05a..fd7617697 100644 --- a/radio/src/targets/simu/switch_driver.cpp +++ b/radio/src/targets/simu/switch_driver.cpp @@ -33,92 +33,36 @@ 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() +void boardInitSwitches() {} + +static uint8_t get_switch_index(uint8_t cat, uint8_t idx) { - return _switch_default_config; + 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; + } } -switch_display_pos_t switchGetDisplayPosition(uint8_t idx) +SwitchHwPos boardSwitchGetPosition(uint8_t cat, 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) -{ - 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; -} - -uint8_t switchGetMaxFctSwitches() -{ - return n_fct_switches; -} - -const char* switchGetName(uint8_t idx) -{ - assert(idx < n_total_switches); - return _hw_switch_defs[idx].name; -} - -SwitchHwType switchGetHwType(uint8_t idx) -{ - assert(idx < n_total_switches); - return _hw_switch_defs[idx].type; -} - -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; - } -} - -SwitchHwPos switchGetPosition(uint8_t idx) -{ - assert(idx < n_total_switches); + idx = get_switch_index(cat, idx); if (switchesStates[idx] < 0) return SWITCH_HW_UP; @@ -127,3 +71,27 @@ SwitchHwPos switchGetPosition(uint8_t idx) else return SWITCH_HW_DOWN; } + +const char* boardSwitchGetName(uint8_t cat, uint8_t idx) +{ + idx = get_switch_index(cat, idx); + return _switch_defs[idx].name; +} + +SwitchHwType boardSwitchGetType(uint8_t cat, uint8_t idx) +{ + idx = get_switch_index(cat, idx); + return _switch_defs[idx].type; +} + +uint8_t boardGetMaxSwitches() { return n_switches; } +uint8_t boardGetMaxFctSwitches() { return n_fct_switches; } + +swconfig_t boardSwitchGetDefaultConfig() { return _switch_default_config; } + +switch_display_pos_t switchGetDisplayPosition(uint8_t idx) +{ + if (idx >= DIM(_switch_display)) return {0, 0}; + + return _switch_display[idx]; +} diff --git a/radio/src/tests/functions.cpp b/radio/src/tests/functions.cpp index 603c7e64b..25549b5b2 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/model_audio.cpp b/radio/src/tests/model_audio.cpp index 3254e0922..31b2a1d3c 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); diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index 8e864db34..12cb3f037 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -19,7 +19,12 @@ * GNU General Public License for more details. */ +#include "dataconstants.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 +142,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 +150,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); + // 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(5, 0); //SF down - // EXPECT_EQ(getSwitch(SWSRC_SF2), false); + 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 +189,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 +219,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 +245,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 +270,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 +297,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 +323,100 @@ 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)); + + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + anaSetFiltered(offset, -1024); + EXPECT_EQ(SWITCH_HW_UP, switchGetPosition(sw_idx)); + + anaSetFiltered(offset, 0); + EXPECT_EQ(SWITCH_HW_MID, switchGetPosition(sw_idx)); + + anaSetFiltered(offset, +1024); + 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)); + + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + anaSetFiltered(offset, -1024); + EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + anaSetFiltered(offset, 0); + EXPECT_EQ(0, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + 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)); + + anaSetFiltered(offset, -1024); + EXPECT_EQ(-1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + anaSetFiltered(offset, 0); + EXPECT_EQ(+1024, getValue(MIXSRC_FIRST_SWITCH + sw_idx)); + + anaSetFiltered(offset, +1024); + 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)); + + auto offset = adcGetInputOffset(ADC_INPUT_FLEX); + 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)); + + 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)); + + 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)); +} diff --git a/radio/src/translations/cn.h b/radio/src/translations/cn.h index d40b774a1..d675bb167 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 19b2dde56..76e41ed4d 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 cbdf6ef44..6611d2702 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 bfd2ed9e3..819bf3576 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 3baaf3dee..ff93958ae 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 4773c3452..56791c383 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 1c602ae22..541e949f9 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 7d529ac97..981da2d2b 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 2798b72f9..a6552ede5 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 4e8dec655..1f91ac12b 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 25cf4f640..ab3f29343 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 edb5b2876..9a8d7d66b 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 7537a00dd..28c1cce74 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 f44e706e7..bd214b189 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 4ef3e32e3..511a90df7 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 45f5523f5..80990b14f 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 53c7f12a6..4129fa799 100644 --- a/radio/util/hw_defs/generator.py +++ b/radio/util/hw_defs/generator.py @@ -43,6 +43,22 @@ KEYS_LUT = [ "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 4cd52b853..e6018804f 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 @@ class ADCInputParser: 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 d2deddc7b..cd947b3b8 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 61b052ae1..70e475443 100644 --- a/radio/util/hw_defs/legacy_names.py +++ b/radio/util/hw_defs/legacy_names.py @@ -148,11 +148,15 @@ LEGACY_NAMES = [ "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 a9e905200..d5088e747 100644 --- a/radio/util/hw_defs/pot_config.py +++ b/radio/util/hw_defs/pot_config.py @@ -2,144 +2,146 @@ 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"}, - "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": "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" } + "P1": {"default": "POT"} }, } diff --git a/radio/util/hw_defs/simu_switches.jinja b/radio/util/hw_defs/simu_switches.jinja index d8d7fa28b..cb03bcbf7 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 2adf187a7..0eab64c4a 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 %} diff --git a/radio/util/hw_defs/yaml_inputs.jinja b/radio/util/hw_defs/yaml_inputs.jinja index ef3535c61..f36f24bd2 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 %} };