feat: More flexible ADC inputs (#3870)

Co-authored-by: 3djc <lesitewebdejc@hotmail.com>
Co-authored-by: Peter Feerick <peter.feerick@gmail.com>
Co-authored-by: philmoz <phil.a.mitchell@gmail.com>
This commit is contained in:
Raphael Coeffic
2023-11-02 11:07:53 +10:00
committed by GitHub
co-authored by 3djc Peter Feerick philmoz
parent f5593c44e8
commit b48e07026d
78 changed files with 1291 additions and 773 deletions
+20 -65
View File
@@ -32,80 +32,35 @@
#include <stdlib.h>
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;
}
+7 -9
View File
@@ -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,
+3 -3
View File
@@ -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
+1
View File
@@ -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
+6 -6
View File
@@ -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;
+5 -5
View File
@@ -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);
+5 -5
View File
@@ -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 {
+2 -2
View File
@@ -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;
+4 -4
View File
@@ -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) +
+80 -24
View File
@@ -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<potconfig_t>(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<potconfig_t>(
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<T>::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();
}
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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);
}
+9 -6
View File
@@ -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));
+4 -17
View File
@@ -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;
}
}
@@ -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
+68 -28
View File
@@ -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;
+55 -13
View File
@@ -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<potconfig_t>(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<potconfig_t>(g_eeGeneral.potsConfig, value, (POT_CFG_BITS * index) + POT_CFG_TYPE_BITS, POT_CFG_INV_BITS);
}
uint8_t getPotType(int index)
{
return bfGet<potconfig_t>(g_eeGeneral.potsConfig, POT_CFG_BITS * index, POT_CFG_TYPE_BITS);
}
void setPotType(int index, int value)
{
g_eeGeneral.potsConfig = bfSet<potconfig_t>(g_eeGeneral.potsConfig, value, (POT_CFG_BITS * index), POT_CFG_TYPE_BITS);
}
+6
View File
@@ -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);
+6
View File
@@ -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}
+158 -92
View File
@@ -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<<ANALOG_SCALE)
#define ANA_FILT(chan) (s_anaFilt[chan] / (JITTER_ALPHA * ANALOG_MULTIPLIER))
#define ANALOG_MULTIPLIER (1 << ANALOG_SCALE)
#define ANA_FILT(chan) (s_anaFilt[chan] / (JITTER_ALPHA * ANALOG_MULTIPLIER))
#if (JITTER_ALPHA * ANALOG_MULTIPLIER > 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:
// <out> = ((ALPHA-1)*<out> + <in>)/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 <filtered> is used. The new formula becomes:
// <filtered> = <filtered> - <filtered>/ALPHA + <in>
// <out> = <filtered>/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:
// <out> = ((ALPHA-1)*<out> + <in>)/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 <filtered> is
// used. The new formula becomes:
// <filtered> = <filtered> - <filtered>/ALPHA + <in>
// <out> = <filtered>/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:
// * <in> = v
// * <out> = 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;
+4 -2
View File
@@ -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();
+255
View File
@@ -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);
}
}
}
+21 -1
View File
@@ -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`
+4 -4
View File
@@ -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))
+1
View File
@@ -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);
+35 -51
View File
@@ -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
+3 -1
View File
@@ -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))
+10 -10
View File
@@ -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();
+14 -8
View File
@@ -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)
+9 -6
View File
@@ -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 {
+2 -7
View File
@@ -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;
}
+4
View File
@@ -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();
@@ -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),
@@ -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<YamlTreeWalker*>(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<YamlTreeWalker*>(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<YamlTreeWalker*>(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<YamlTreeWalker*>(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<YamlTreeWalker*>(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') {
@@ -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 ),
@@ -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),
@@ -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),
@@ -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 ),
@@ -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 ),
@@ -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),
@@ -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),
@@ -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),
@@ -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),
+5 -12
View File
@@ -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;
+43 -26
View File
@@ -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)) {
+4
View File
@@ -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();
@@ -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;
@@ -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);
+1
View File
@@ -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)
+3 -3
View File
@@ -51,7 +51,7 @@ QVector<QIODevice *> 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)
+44 -76
View File
@@ -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];
}
+4
View File
@@ -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);
+1 -1
View File
@@ -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);
+133 -31
View File
@@ -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));
}
+1 -1
View File
@@ -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盘","串行"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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","העברת נתונים קבוע"),"חיבור סיריילי קבוע"
+1 -1
View File
@@ -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")
+1 -1
View File
@@ -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カード","ストレージ"),"シリアル"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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盤","串行"
+18
View File
@@ -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)
+8 -8
View File
@@ -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')
+10 -20
View File
@@ -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 %}
;
+4
View File
@@ -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"
}
}
+88 -86
View File
@@ -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"}
},
}
+1 -1
View File
@@ -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 %}
+7 -1
View File
@@ -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 %}
+2 -7
View File
@@ -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 %}
};