simplify model setup screen
This commit is contained in:
committed by
Raphael Coeffic
parent
009018be3a
commit
ace7cfbe9d
@@ -56,6 +56,9 @@ set(GUI_SRC
|
||||
custom_failsafe.cpp
|
||||
module_setup.cpp
|
||||
timer_setup.cpp
|
||||
trims_setup.cpp
|
||||
throttle_params.cpp
|
||||
preflight_checks.cpp
|
||||
model_setup.cpp
|
||||
model_flightmodes.cpp
|
||||
model_inputs.cpp
|
||||
|
||||
@@ -51,8 +51,13 @@ TouchState getLastTochState()
|
||||
extern "C" void keyboardDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data)
|
||||
{
|
||||
// if there is a keyboard event then call checkevents
|
||||
if (isEvent())
|
||||
MainWindow::instance()->checkEvents();
|
||||
if (isEvent()) {
|
||||
event_t evt = getWindowEvent();
|
||||
auto focusWindow = Window::getFocus();
|
||||
if (focusWindow) {
|
||||
focusWindow->onEvent(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_ts_to_indev_data(const TouchState &st, lv_indev_data_t *data)
|
||||
|
||||
@@ -23,30 +23,20 @@
|
||||
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
#include "button_matrix.h"
|
||||
|
||||
#include "storage/modelslist.h"
|
||||
#include "trainer_setup.h"
|
||||
#include "module_setup.h"
|
||||
#include "timer_setup.h"
|
||||
#include "trims_setup.h"
|
||||
#include "throttle_params.h"
|
||||
#include "preflight_checks.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
std::string switchWarninglabel(swsrc_t index)
|
||||
{
|
||||
static const char *switchPositions[] = {
|
||||
" ",
|
||||
STR_CHAR_UP,
|
||||
"-",
|
||||
STR_CHAR_DOWN,
|
||||
};
|
||||
|
||||
return TEXT_AT_INDEX(STR_VSRCRAW,
|
||||
(index + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1)) +
|
||||
std::string(
|
||||
switchPositions[g_model.switchWarningState >> (3 * index) & 0x07]);
|
||||
}
|
||||
|
||||
ModelSetupPage::ModelSetupPage() :
|
||||
PageTab(STR_MENU_MODEL_SETUP, ICON_MODEL_SETUP)
|
||||
{
|
||||
@@ -87,293 +77,133 @@ static void setModelBitmap(std::string newValue)
|
||||
}
|
||||
|
||||
struct ModelBitmapEdit : public FileChoice {
|
||||
ModelBitmapEdit(FormGroup *parent, const rect_t &rect) :
|
||||
ModelBitmapEdit(Window *parent, const rect_t &rect) :
|
||||
FileChoice(parent, rect, BITMAPS_PATH, BITMAPS_EXT,
|
||||
sizeof(g_model.header.bitmap), getModelBitmap, setModelBitmap)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct SubScreenButtonMatrix : public ButtonMatrix {
|
||||
SubScreenButtonMatrix(Window* parent, const rect_t& rect);
|
||||
void onPress(uint8_t btn_id) override;
|
||||
bool isActive(uint8_t btn_id) override;
|
||||
};
|
||||
|
||||
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
void ModelSetupPage::build(FormWindow * window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
window->setFlexLayout();
|
||||
FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
|
||||
|
||||
// Model name
|
||||
new StaticText(window, grid.getLabelSlot(), STR_MODELNAME, 0, COLOR_THEME_PRIMARY1);
|
||||
new ModelNameEdit(window, grid.getFieldSlot());
|
||||
grid.nextLine();
|
||||
auto line = window->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_MODELNAME, 0, COLOR_THEME_PRIMARY1);
|
||||
new ModelNameEdit(line, rect_t{});
|
||||
|
||||
// Bitmap
|
||||
new StaticText(window, grid.getLabelSlot(), STR_BITMAP, 0, COLOR_THEME_PRIMARY1);
|
||||
new ModelBitmapEdit(window, grid.getFieldSlot());
|
||||
grid.nextLine();
|
||||
|
||||
for (uint8_t i = 0; i < TIMERS; i++)
|
||||
new TimerButton(window, grid.getSlot(3, i), i);
|
||||
grid.nextLine();
|
||||
line = window->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_BITMAP, 0, COLOR_THEME_PRIMARY1);
|
||||
// TODO: show bitmap thumbnail instead?
|
||||
new ModelBitmapEdit(line, rect_t{});
|
||||
|
||||
// Extended limits
|
||||
new StaticText(window, grid.getLabelSlot(), STR_ELIMITS, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.extendedLimits));
|
||||
grid.nextLine();
|
||||
|
||||
// Extended trims
|
||||
new StaticText(window, grid.getLabelSlot(), STR_ETRIMS, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(2, 0), GET_SET_DEFAULT(g_model.extendedTrims));
|
||||
new TextButton(window, grid.getFieldSlot(2, 1), STR_RESET_BTN,
|
||||
[]() -> uint8_t {
|
||||
for (auto &flightModeData : g_model.flightModeData) {
|
||||
memclear(&flightModeData, TRIMS_ARRAY_SIZE);
|
||||
}
|
||||
SET_DIRTY();
|
||||
AUDIO_WARNING1();
|
||||
return 0;
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
// Display trims
|
||||
new StaticText(window, grid.getLabelSlot(), STR_DISPLAY_TRIMS, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(window, grid.getFieldSlot(), "\006No\0 ChangeYes", 0, 2, GET_SET_DEFAULT(g_model.displayTrims));
|
||||
grid.nextLine();
|
||||
|
||||
// Trim step
|
||||
new StaticText(window, grid.getLabelSlot(), STR_TRIMINC, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(window, grid.getFieldSlot(), STR_VTRIMINC, -2, 2, GET_SET_DEFAULT(g_model.trimInc));
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle parameters
|
||||
{
|
||||
new Subtitle(window, grid.getLineSlot(), STR_THROTTLE_LABEL, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle reversed
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_THROTTLEREVERSE, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.throttleReversed));
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle source
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_TTRACE, 0, COLOR_THEME_PRIMARY1);
|
||||
auto sc = new SourceChoice(
|
||||
window, grid.getFieldSlot(), 0, MIXSRC_LAST_CH,
|
||||
[=]() { return throttleSource2Source(g_model.thrTraceSrc); },
|
||||
[=](int16_t src) {
|
||||
int16_t val = source2ThrottleSource(src);
|
||||
if (val >= 0) {
|
||||
g_model.thrTraceSrc = val;
|
||||
SET_DIRTY();
|
||||
}
|
||||
}, 0, COLOR_THEME_PRIMARY1);
|
||||
sc->setAvailableHandler(isThrottleSourceAvailable);
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle trim
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_TTRIM, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.thrTrim));
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle trim source
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_TTRIM_SW, 0, COLOR_THEME_PRIMARY1);
|
||||
new SourceChoice(
|
||||
window, grid.getFieldSlot(), MIXSRC_FIRST_TRIM, MIXSRC_LAST_TRIM,
|
||||
[=]() { return g_model.getThrottleStickTrimSource(); },
|
||||
[=](int16_t src) { g_model.setThrottleStickTrimSource(src); }, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
// Preflight parameters
|
||||
{
|
||||
new Subtitle(window, grid.getLineSlot(), STR_PREFLIGHT, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
|
||||
// Display checklist
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_CHECKLIST, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.displayChecklist));
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle warning
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_THROTTLE_WARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_model.disableThrottleWarning));
|
||||
grid.nextLine();
|
||||
|
||||
// Custom Throttle warning
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_CUSTOM_THROTTLE_WARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(g_model.enableCustomThrottleWarning));
|
||||
grid.nextLine();
|
||||
// Custom Throttle warning value
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_CUSTOM_THROTTLE_WARNING_VAL, 0, COLOR_THEME_PRIMARY1);
|
||||
new NumberEdit(window, grid.getFieldSlot(), -100, 100, GET_SET_DEFAULT(g_model.customThrottleWarningPosition));
|
||||
grid.nextLine();
|
||||
|
||||
// Switches warning
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_SWITCHWARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
auto group = new FormGroup(window, grid.getFieldSlot(), FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
GridLayout switchesGrid(group);
|
||||
for (int i = 0, j = 0; i < NUM_SWITCHES; i++) {
|
||||
if (SWITCH_EXISTS(i)) {
|
||||
if (j > 0 && (j % 3) == 0)
|
||||
switchesGrid.nextLine();
|
||||
auto button = new TextButton(group, switchesGrid.getSlot(3, j % 3), switchWarninglabel(i), nullptr,
|
||||
OPAQUE | (bfGet(g_model.switchWarningState, 3 * i, 3) == 0 ? 0 : BUTTON_CHECKED));
|
||||
button->setPressHandler([button, i] {
|
||||
swarnstate_t newstate = bfGet(g_model.switchWarningState, 3 * i, 3);
|
||||
if (newstate == 1 && SWITCH_CONFIG(i) != SWITCH_3POS)
|
||||
newstate = 3;
|
||||
else
|
||||
newstate = (newstate + 1) % 4;
|
||||
g_model.switchWarningState = bfSet(g_model.switchWarningState, newstate, 3 * i, 3);
|
||||
SET_DIRTY();
|
||||
button->setText(switchWarninglabel(i));
|
||||
return newstate > 0;
|
||||
});
|
||||
j++;
|
||||
}
|
||||
}
|
||||
grid.addWindow(group);
|
||||
|
||||
// Pots and sliders warning
|
||||
#if NUM_POTS + NUM_SLIDERS
|
||||
{
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_POTWARNINGSTATE, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(window, grid.getFieldSlot(), {"OFF", "ON", "AUTO"}, 0, 2,
|
||||
GET_SET_DEFAULT(g_model.potsWarnMode));
|
||||
grid.nextLine();
|
||||
|
||||
#if (NUM_POTS)
|
||||
{
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_POTWARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
auto group =
|
||||
new FormGroup(window, grid.getFieldSlot(),
|
||||
FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
GridLayout centerGrid(group);
|
||||
for (int i = POT_FIRST, j = 0, k = 0; i <= POT_LAST; i++, k++) {
|
||||
char s[8];
|
||||
if ((IS_POT(i) || IS_POT_MULTIPOS(i)) && IS_POT_AVAILABLE(i)) {
|
||||
if (j > 0 && ((j % 4) == 0)) centerGrid.nextLine();
|
||||
|
||||
auto button = new TextButton(
|
||||
group, centerGrid.getSlot(4, j % 4),
|
||||
getStringAtIndex(s, STR_VSRCRAW, i + 1), nullptr,
|
||||
OPAQUE | ((g_model.potsWarnEnabled & (1 << k)) ? BUTTON_CHECKED
|
||||
: 0));
|
||||
button->setPressHandler([button, k] {
|
||||
g_model.potsWarnEnabled ^= (1 << k);
|
||||
if ((g_model.potsWarnMode == POTS_WARN_MANUAL) &&
|
||||
(g_model.potsWarnEnabled & (1 << k))) {
|
||||
SAVE_POT_POSITION(k);
|
||||
}
|
||||
button->check(g_model.potsWarnEnabled & (1 << k) ? true : false);
|
||||
SET_DIRTY();
|
||||
return (g_model.potsWarnEnabled & (1 << k) ? 1 : 0);
|
||||
});
|
||||
j++;
|
||||
} else {
|
||||
g_model.potsWarnEnabled &= ~(1 << k);
|
||||
}
|
||||
}
|
||||
grid.addWindow(group);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (NUM_SLIDERS)
|
||||
{
|
||||
new StaticText(window, grid.getLabelSlot(true), STR_SLIDERWARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
auto group =
|
||||
new FormGroup(window, grid.getFieldSlot(),
|
||||
FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
GridLayout centerGrid(group);
|
||||
for (int i = SLIDER_FIRST, j = 0, k = NUM_POTS; i <= SLIDER_LAST; i++, k++) {
|
||||
char s[8];
|
||||
if ((IS_SLIDER(i))) {
|
||||
if (j > 0 && ((j % 4) == 0)) centerGrid.nextLine();
|
||||
|
||||
auto *button = new TextButton(
|
||||
group, centerGrid.getSlot(4, j % 4),
|
||||
getStringAtIndex(s, STR_VSRCRAW, i + 1), nullptr,
|
||||
OPAQUE | ((g_model.potsWarnEnabled & (1 << k)) ? BUTTON_CHECKED
|
||||
: 0));
|
||||
button->setPressHandler([button, k] {
|
||||
g_model.potsWarnEnabled ^= (1 << (k));
|
||||
if ((g_model.potsWarnMode == POTS_WARN_MANUAL) &&
|
||||
(g_model.potsWarnEnabled & (1 << k))) {
|
||||
SAVE_POT_POSITION(k);
|
||||
}
|
||||
button->check(g_model.potsWarnEnabled & (1 << k) ? true : false);
|
||||
SET_DIRTY();
|
||||
return (g_model.potsWarnEnabled & (1 << k) ? 1 : 0);
|
||||
});
|
||||
j++;
|
||||
}
|
||||
}
|
||||
grid.addWindow(group);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
grid.nextLine();
|
||||
|
||||
// Center beeps
|
||||
{
|
||||
new StaticText(window, grid.getLabelSlot(false), STR_BEEPCTR, 0, COLOR_THEME_PRIMARY1);
|
||||
auto group = new FormGroup(window, grid.getFieldSlot(), FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
GridLayout centerGrid(group);
|
||||
for (int i = 0, j = 0; i < NUM_STICKS + NUM_POTS + NUM_SLIDERS; i++) {
|
||||
char s[2];
|
||||
if (i < NUM_STICKS || (IS_POT_SLIDER_AVAILABLE(i) && !IS_POT_MULTIPOS(i))) { // multipos cannot be centered
|
||||
if (j > 0 && (j % 6) == 0)
|
||||
centerGrid.nextLine();
|
||||
|
||||
new TextButton(
|
||||
group, centerGrid.getSlot(6, j % 6),
|
||||
getStringAtIndex(s, STR_RETA123, i),
|
||||
[=]() -> uint8_t {
|
||||
BFBIT_FLIP(g_model.beepANACenter, bfBit<BeepANACenter>(i));
|
||||
SET_DIRTY();
|
||||
return (bfSingleBitGet<BeepANACenter>(g_model.beepANACenter, i) ? 1 : 0);
|
||||
},
|
||||
OPAQUE | (bfSingleBitGet<BeepANACenter>(g_model.beepANACenter, i)
|
||||
? BUTTON_CHECKED
|
||||
: 0));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
grid.addWindow(group);
|
||||
}
|
||||
// TODO: move to "Outputs" screen ?
|
||||
line = window->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_ELIMITS, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.extendedLimits));
|
||||
|
||||
// Global functions
|
||||
new StaticText(window, grid.getLabelSlot(), STR_USE_GLOBAL_FUNCS, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_model.noGlobalFunctions));
|
||||
grid.nextLine();
|
||||
line = window->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_USE_GLOBAL_FUNCS, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(line, rect_t{}, GET_SET_INVERTED(g_model.noGlobalFunctions));
|
||||
|
||||
{
|
||||
// Model ADC jitter filter
|
||||
new StaticText(window, grid.getLabelSlot(), STR_JITTER_FILTER, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(window, grid.getFieldSlot(), STR_ADCFILTERVALUES, 0, 2, GET_SET_DEFAULT(g_model.jitterFilter));
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
// Internal module
|
||||
{
|
||||
new Subtitle(window, grid.getLineSlot(), TR_INTERNALRF, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
grid.addWindow(new ModuleWindow(window, {0, grid.getWindowHeight(), LCD_W, 0}, INTERNAL_MODULE));
|
||||
}
|
||||
|
||||
// External module
|
||||
{
|
||||
new Subtitle(window, grid.getLineSlot(), TR_EXTERNALRF, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
grid.addWindow(new ModuleWindow(window, {0, grid.getWindowHeight(), LCD_W, 0}, EXTERNAL_MODULE));
|
||||
}
|
||||
|
||||
// Trainer
|
||||
{
|
||||
new Subtitle(window, grid.getLineSlot(), STR_TRAINER, 0, COLOR_THEME_PRIMARY1);
|
||||
grid.nextLine();
|
||||
grid.addWindow(new TrainerModuleWindow(window, {0, grid.getWindowHeight(), LCD_W, 0}));
|
||||
}
|
||||
// Model ADC jitter filter
|
||||
line = window->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_JITTER_FILTER, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(line, rect_t{}, STR_ADCFILTERVALUES, 0, 2,
|
||||
GET_SET_DEFAULT(g_model.jitterFilter));
|
||||
|
||||
// Sub-screens
|
||||
new SubScreenButtonMatrix(window, rect_t{});
|
||||
}
|
||||
|
||||
#define MAX_SUBSCREEN_BTNS 9
|
||||
|
||||
SubScreenButtonMatrix::SubScreenButtonMatrix(Window* parent, const rect_t& r) :
|
||||
ButtonMatrix(parent, r)
|
||||
{
|
||||
initBtnMap(3, MAX_SUBSCREEN_BTNS);
|
||||
|
||||
setText(0, STR_INTERNALRF);
|
||||
setText(1, STR_EXTERNALRF);
|
||||
setText(2, STR_TRAINER);
|
||||
|
||||
setText(3, STR_PREFLIGHT);
|
||||
setText(4, STR_TRIMS);
|
||||
setText(5, STR_THROTTLE_LABEL);
|
||||
setText(6, TR_TIMER "1");
|
||||
setText(7, TR_TIMER "2");
|
||||
setText(8, TR_TIMER "3");
|
||||
update();
|
||||
|
||||
lv_btnmatrix_set_btn_width(lvobj, 3, 2);
|
||||
lv_obj_set_width(lvobj, lv_pct(100));
|
||||
lv_obj_set_height(lvobj, (4 * LV_DPI_DEF) / 3);
|
||||
|
||||
lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_all(lvobj, LV_DPI_DEF / 10, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_FOCUSED);
|
||||
lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_EDITED);
|
||||
}
|
||||
|
||||
void SubScreenButtonMatrix::onPress(uint8_t btn_id)
|
||||
{
|
||||
if (btn_id >= MAX_SUBSCREEN_BTNS) return;
|
||||
|
||||
Window* w = nullptr;
|
||||
switch (btn_id) {
|
||||
case 0:
|
||||
w = new ModulePage(INTERNAL_MODULE);
|
||||
break;
|
||||
case 1:
|
||||
w = new ModulePage(EXTERNAL_MODULE);
|
||||
break;
|
||||
case 2:
|
||||
w = new TrainerPage();
|
||||
break;
|
||||
case 3:
|
||||
w = new PreflightChecks();
|
||||
break;
|
||||
case 4:
|
||||
w = new TrimsSetup();
|
||||
break;
|
||||
case 5:
|
||||
w = new ThrottleParams();
|
||||
break;
|
||||
default:
|
||||
w = new TimerWindow((uint8_t)(btn_id - 6));
|
||||
break;
|
||||
}
|
||||
|
||||
if (w) w->setFocus();
|
||||
}
|
||||
|
||||
bool SubScreenButtonMatrix::isActive(uint8_t btn_id)
|
||||
{
|
||||
if (btn_id == 0)
|
||||
return g_model.moduleData[INTERNAL_MODULE].type > 0;
|
||||
|
||||
if (btn_id == 1)
|
||||
return g_model.moduleData[EXTERNAL_MODULE].type > 0;
|
||||
|
||||
if (btn_id == 2)
|
||||
return g_model.trainerData.mode > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@
|
||||
#include "module_setup.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#include "form.h"
|
||||
#include "choice.h"
|
||||
#include "button.h"
|
||||
#include "gridlayout.h"
|
||||
|
||||
#include "mixer_scheduler.h"
|
||||
#include "multi_rfprotos.h"
|
||||
#include "io/multi_protolist.h"
|
||||
@@ -35,6 +40,29 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
class ModuleWindow : public FormGroup
|
||||
{
|
||||
public:
|
||||
ModuleWindow(FormWindow *parent, const rect_t &rect, uint8_t moduleIdx);
|
||||
|
||||
protected:
|
||||
uint8_t moduleIdx;
|
||||
bool hasFailsafe = false;
|
||||
|
||||
Choice *moduleChoice = nullptr;
|
||||
Choice *rfChoice = nullptr;
|
||||
TextButton *bindButton = nullptr;
|
||||
TextButton *rangeButton = nullptr;
|
||||
TextButton *registerButton = nullptr;
|
||||
Choice *failSafeChoice = nullptr;
|
||||
|
||||
void addChannelRange(FormGridLayout &grid);
|
||||
void startRSSIDialog(std::function<void()> closeHandler = nullptr);
|
||||
|
||||
void update();
|
||||
void checkEvents() override;
|
||||
};
|
||||
|
||||
ModuleWindow::ModuleWindow(FormWindow *parent, const rect_t &rect,
|
||||
uint8_t moduleIdx) :
|
||||
FormGroup(parent, rect, FORWARD_SCROLL | NO_FOCUS | FORM_FORWARD_FOCUS),
|
||||
@@ -882,3 +910,16 @@ void ModuleWindow::checkEvents()
|
||||
|
||||
FormGroup::checkEvents();
|
||||
}
|
||||
|
||||
ModulePage::ModulePage(uint8_t moduleIdx) : Page(ICON_MODEL_SETUP)
|
||||
{
|
||||
const char* title = moduleIdx == INTERNAL_MODULE ?
|
||||
STR_INTERNALRF : STR_EXTERNALRF;
|
||||
|
||||
new StaticText(&header,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
title, 0, COLOR_THEME_PRIMARY2);
|
||||
|
||||
new ModuleWindow(&body, {0, 0, width(), 0}, moduleIdx);
|
||||
}
|
||||
|
||||
@@ -21,30 +21,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "form.h"
|
||||
#include "choice.h"
|
||||
#include "button.h"
|
||||
#include "gridlayout.h"
|
||||
#include "page.h"
|
||||
|
||||
class ModuleWindow : public FormGroup
|
||||
{
|
||||
public:
|
||||
ModuleWindow(FormWindow *parent, const rect_t &rect, uint8_t moduleIdx);
|
||||
|
||||
protected:
|
||||
uint8_t moduleIdx;
|
||||
bool hasFailsafe = false;
|
||||
|
||||
Choice *moduleChoice = nullptr;
|
||||
Choice *rfChoice = nullptr;
|
||||
TextButton *bindButton = nullptr;
|
||||
TextButton *rangeButton = nullptr;
|
||||
TextButton *registerButton = nullptr;
|
||||
Choice *failSafeChoice = nullptr;
|
||||
|
||||
void addChannelRange(FormGridLayout &grid);
|
||||
void startRSSIDialog(std::function<void()> closeHandler = nullptr);
|
||||
|
||||
void update();
|
||||
void checkEvents() override;
|
||||
struct ModulePage : public Page {
|
||||
ModulePage(uint8_t moduleIdx);
|
||||
};
|
||||
|
||||
@@ -67,6 +67,11 @@ void Page::deleteLater(bool detach, bool trash)
|
||||
Window::deleteLater(detach, trash);
|
||||
}
|
||||
|
||||
void Page::setFocus(uint8_t flag, Window * from)
|
||||
{
|
||||
body.setFocus(flag, from);
|
||||
}
|
||||
|
||||
void Page::paint(BitmapBuffer * dc)
|
||||
{
|
||||
dc->clear(COLOR_THEME_SECONDARY3);
|
||||
|
||||
@@ -114,6 +114,8 @@ class Page: public Window
|
||||
}
|
||||
#endif
|
||||
|
||||
void setFocus(uint8_t flag = SET_FOCUS_DEFAULT, Window * from = nullptr) override;
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* 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 "preflight_checks.h"
|
||||
#include "button_matrix.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
static void cb_changed(lv_event_t* e)
|
||||
{
|
||||
auto target = lv_event_get_target(e);
|
||||
auto obj = (lv_obj_t*)lv_event_get_user_data(e);
|
||||
|
||||
if (lv_obj_has_state(target, LV_STATE_CHECKED)) {
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void make_conditional(Window* w, CheckBox* cb)
|
||||
{
|
||||
lv_obj_t* w_obj = w->getLvObj();
|
||||
if (!cb->getValue()) { lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN); }
|
||||
|
||||
lv_obj_t* cb_obj = cb->getLvObj();
|
||||
lv_obj_add_event_cb(cb_obj, cb_changed, LV_EVENT_VALUE_CHANGED, w_obj);
|
||||
}
|
||||
|
||||
static void choice_changed(lv_event_t* e)
|
||||
{
|
||||
auto target = lv_event_get_target(e);
|
||||
auto choice = (Choice*)lv_obj_get_user_data(target);
|
||||
auto obj = (lv_obj_t*)lv_event_get_user_data(e);
|
||||
|
||||
if (choice->getIntValue() != 0) {
|
||||
lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void make_conditional(Window* w, Choice* choice)
|
||||
{
|
||||
lv_obj_t* w_obj = w->getLvObj();
|
||||
if (choice->getIntValue() == 0) { lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN); }
|
||||
|
||||
lv_obj_t* choice_obj = choice->getLvObj();
|
||||
lv_obj_add_event_cb(choice_obj, choice_changed, LV_EVENT_VALUE_CHANGED, w_obj);
|
||||
}
|
||||
|
||||
struct SwitchWarnMatrix : public ButtonMatrix {
|
||||
SwitchWarnMatrix(Window* parent, const rect_t& rect);
|
||||
void onPress(uint8_t btn_id);
|
||||
bool isActive(uint8_t btn_id);
|
||||
};
|
||||
|
||||
struct PotWarnMatrix : public ButtonMatrix {
|
||||
PotWarnMatrix(Window* parent, const rect_t& rect);
|
||||
void onPress(uint8_t btn_id);
|
||||
bool isActive(uint8_t btn_id);
|
||||
};
|
||||
|
||||
PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP)
|
||||
{
|
||||
new StaticText(&header,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_PREFLIGHT, 0, COLOR_THEME_PRIMARY2);
|
||||
|
||||
auto form = new FormWindow(&body, rect_t{0, 0, body.width(), body.height()},
|
||||
NO_FOCUS | FORM_FORWARD_FOCUS);
|
||||
form->setFlexLayout();
|
||||
FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
|
||||
|
||||
// Display checklist
|
||||
auto line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_CHECKLIST, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.displayChecklist));
|
||||
|
||||
// Throttle warning
|
||||
line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_THROTTLE_WARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
auto tw = new CheckBox(line, rect_t{}, GET_SET_INVERTED(g_model.disableThrottleWarning));
|
||||
|
||||
// Custom Throttle warning (conditional on previous field)
|
||||
line = form->newLine(&grid);
|
||||
make_conditional(line, tw);
|
||||
|
||||
new StaticText(line, rect_t{}, STR_CUSTOM_THROTTLE_WARNING, 0, COLOR_THEME_PRIMARY1);
|
||||
auto box = new FormGroup::Line(line, lv_obj_create(line->getLvObj()), nullptr, form);
|
||||
lv_obj_set_layout(box->getLvObj(), LV_LAYOUT_FLEX);
|
||||
|
||||
auto cst_tw = new CheckBox(
|
||||
box, rect_t{}, GET_SET_DEFAULT(g_model.enableCustomThrottleWarning));
|
||||
|
||||
// Custom Throttle warning value
|
||||
auto cst_val =
|
||||
new NumberEdit(box, rect_t{}, -100, 100,
|
||||
GET_SET_DEFAULT(g_model.customThrottleWarningPosition));
|
||||
make_conditional(cst_val, cst_tw);
|
||||
|
||||
// Switch warnings (TODO: add display switch?)
|
||||
new SwitchWarnMatrix(form, rect_t{});
|
||||
|
||||
// Pots and sliders warning
|
||||
#if NUM_POTS + NUM_SLIDERS
|
||||
line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_POTWARNINGSTATE, 0, COLOR_THEME_PRIMARY1);
|
||||
auto pots_wm = new Choice(line, rect_t{}, {"OFF", "ON", "AUTO"}, 0, 2,
|
||||
GET_SET_DEFAULT(g_model.potsWarnMode));
|
||||
#if (NUM_POTS)
|
||||
// Pot warnings
|
||||
auto pwm = new PotWarnMatrix(form, rect_t{});
|
||||
make_conditional(pwm, pots_wm);
|
||||
#endif
|
||||
|
||||
// #if (NUM_SLIDERS)
|
||||
// {
|
||||
// new StaticText(window, grid.getLabelSlot(true), STR_SLIDERWARNING, 0,
|
||||
// COLOR_THEME_PRIMARY1);
|
||||
// auto group = new FormGroup(window, grid.getFieldSlot(),
|
||||
// FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
// GridLayout centerGrid(group);
|
||||
// for (int i = SLIDER_FIRST, j = 0, k = NUM_POTS; i <= SLIDER_LAST;
|
||||
// i++, k++) {
|
||||
// char s[8];
|
||||
// if ((IS_SLIDER(i))) {
|
||||
// if (j > 0 && ((j % 4) == 0)) centerGrid.nextLine();
|
||||
|
||||
// auto *button = new TextButton(
|
||||
// group, centerGrid.getSlot(4, j % 4),
|
||||
// getStringAtIndex(s, STR_VSRCRAW, i + 1), nullptr,
|
||||
// OPAQUE |
|
||||
// ((g_model.potsWarnEnabled & (1 << k)) ? BUTTON_CHECKED : 0));
|
||||
// button->setPressHandler([button, k] {
|
||||
// g_model.potsWarnEnabled ^= (1 << (k));
|
||||
// if ((g_model.potsWarnMode == POTS_WARN_MANUAL) &&
|
||||
// (g_model.potsWarnEnabled & (1 << k))) {
|
||||
// SAVE_POT_POSITION(k);
|
||||
// }
|
||||
// button->check(g_model.potsWarnEnabled & (1 << k) ? true : false);
|
||||
// SET_DIRTY();
|
||||
// return (g_model.potsWarnEnabled & (1 << k) ? 1 : 0);
|
||||
// });
|
||||
// j++;
|
||||
// }
|
||||
// }
|
||||
// grid.addWindow(group);
|
||||
// }
|
||||
// #endif
|
||||
// }
|
||||
#endif
|
||||
|
||||
// // Center beeps
|
||||
// {
|
||||
// new StaticText(window, grid.getLabelSlot(false), STR_BEEPCTR, 0,
|
||||
// COLOR_THEME_PRIMARY1);
|
||||
// auto group = new FormGroup(window, grid.getFieldSlot(),
|
||||
// FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST);
|
||||
// GridLayout centerGrid(group);
|
||||
// for (int i = 0, j = 0; i < NUM_STICKS + NUM_POTS + NUM_SLIDERS; i++) {
|
||||
// char s[2];
|
||||
// if (i < NUM_STICKS ||
|
||||
// (IS_POT_SLIDER_AVAILABLE(i) &&
|
||||
// !IS_POT_MULTIPOS(i))) { // multipos cannot be centered
|
||||
// if (j > 0 && (j % 6) == 0) centerGrid.nextLine();
|
||||
|
||||
// new TextButton(
|
||||
// group, centerGrid.getSlot(6, j % 6),
|
||||
// getStringAtIndex(s, STR_RETA123, i),
|
||||
// [=]() -> uint8_t {
|
||||
// BFBIT_FLIP(g_model.beepANACenter, bfBit<BeepANACenter>(i));
|
||||
// SET_DIRTY();
|
||||
// return (bfSingleBitGet<BeepANACenter>(g_model.beepANACenter, i)
|
||||
// ? 1
|
||||
// : 0);
|
||||
// },
|
||||
// OPAQUE | (bfSingleBitGet<BeepANACenter>(g_model.beepANACenter, i)
|
||||
// ? BUTTON_CHECKED
|
||||
// : 0));
|
||||
// j++;
|
||||
// }
|
||||
// }
|
||||
// grid.addWindow(group);
|
||||
// }
|
||||
}
|
||||
|
||||
// // Max 12 switches
|
||||
// #define MAX_SW_WARN 12
|
||||
|
||||
// static const char* sw_warn_map[] = {
|
||||
// "0", "1", "2", "3", "\n",
|
||||
// "4", "5", "6", "7", "\n",
|
||||
// "8", "9", "0", "1", ""
|
||||
// };
|
||||
// static_assert(NUM_SWITCHES <= MAX_SW_WARN, "Max 12 switches supported");
|
||||
|
||||
static std::string switchWarninglabel(swsrc_t index)
|
||||
{
|
||||
auto warn_pos = g_model.switchWarningState >> (3 * index) & 0x07;
|
||||
return TEXT_AT_INDEX(STR_VSRCRAW,
|
||||
(index + MIXSRC_FIRST_SWITCH - MIXSRC_Rud + 1)) +
|
||||
std::string(getSwitchWarnSymbol(warn_pos));
|
||||
}
|
||||
|
||||
SwitchWarnMatrix::SwitchWarnMatrix(Window* parent, const rect_t& r) :
|
||||
ButtonMatrix(parent, r)
|
||||
{
|
||||
// Setup button layout & texts
|
||||
uint8_t btn_cnt = 0;
|
||||
for (uint8_t i = 0; i < NUM_SWITCHES; i++)
|
||||
if (SWITCH_EXISTS(i)) btn_cnt++;
|
||||
|
||||
initBtnMap(4, btn_cnt);
|
||||
|
||||
for (uint8_t i = 0; i < NUM_SWITCHES; i++) {
|
||||
if (SWITCH_EXISTS(i)) {
|
||||
std::string txt = switchWarninglabel(i);
|
||||
setText(i, txt.c_str());
|
||||
}
|
||||
}
|
||||
update();
|
||||
|
||||
lv_obj_set_width(lvobj, LV_DPI_DEF * 2);
|
||||
|
||||
uint8_t rows = ((btn_cnt - 1) / 4) + 1;
|
||||
lv_obj_set_height(lvobj, (rows * LV_DPI_DEF) / 3);
|
||||
|
||||
lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_set_style_pad_all(lvobj, 4, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_left(lvobj, LV_DPI_DEF / 10, LV_PART_MAIN);
|
||||
|
||||
lv_obj_set_style_pad_row(lvobj, 4, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_column(lvobj, 4, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_FOCUSED);
|
||||
lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_EDITED);
|
||||
}
|
||||
|
||||
void SwitchWarnMatrix::onPress(uint8_t btn_id)
|
||||
{
|
||||
if (btn_id >= NUM_SWITCHES) return;
|
||||
|
||||
swarnstate_t newstate = bfGet(g_model.switchWarningState, 3 * btn_id, 3);
|
||||
if (newstate == 1 && SWITCH_CONFIG(btn_id) != SWITCH_3POS)
|
||||
newstate = 3;
|
||||
else
|
||||
newstate = (newstate + 1) % 4;
|
||||
|
||||
g_model.switchWarningState =
|
||||
bfSet(g_model.switchWarningState, newstate, 3 * btn_id, 3);
|
||||
SET_DIRTY();
|
||||
|
||||
// TODO: save state in object
|
||||
std::string txt = switchWarninglabel(btn_id);
|
||||
setText(btn_id, txt.c_str());
|
||||
}
|
||||
|
||||
bool SwitchWarnMatrix::isActive(uint8_t btn_id)
|
||||
{
|
||||
return bfGet(g_model.switchWarningState, 3 * btn_id, 3) != 0;
|
||||
}
|
||||
|
||||
PotWarnMatrix::PotWarnMatrix(Window* parent, const rect_t& r) :
|
||||
ButtonMatrix(parent, r)
|
||||
{
|
||||
// Setup button layout & texts
|
||||
uint8_t btn_cnt = 0;
|
||||
for (uint16_t i = POT_FIRST; i <= POT_LAST; i++) {
|
||||
if ((IS_POT(i) || IS_POT_MULTIPOS(i)) && IS_POT_AVAILABLE(i)) btn_cnt++;
|
||||
}
|
||||
|
||||
initBtnMap(3, btn_cnt);
|
||||
|
||||
uint8_t btn_id = 0;
|
||||
for (uint16_t i = POT_FIRST; i <= POT_LAST; i++) {
|
||||
if ((IS_POT(i) || IS_POT_MULTIPOS(i)) && IS_POT_AVAILABLE(i)) {
|
||||
setText(btn_id, STR_VSRCRAW[btn_id + POT_FIRST + 1]);
|
||||
btn_id++;
|
||||
}
|
||||
}
|
||||
update();
|
||||
|
||||
lv_obj_set_width(lvobj, (LV_DPI_DEF * 3) / 2);
|
||||
|
||||
uint8_t rows = ((btn_cnt - 1) / 4) + 1;
|
||||
lv_obj_set_height(lvobj, (rows * LV_DPI_DEF) / 3);
|
||||
|
||||
lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, LV_PART_MAIN);
|
||||
|
||||
lv_obj_set_style_pad_all(lvobj, 4, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_left(lvobj, LV_DPI_DEF / 10, LV_PART_MAIN);
|
||||
|
||||
lv_obj_set_style_pad_row(lvobj, 4, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_column(lvobj, 4, LV_PART_MAIN);
|
||||
|
||||
lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_FOCUSED);
|
||||
lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_EDITED);
|
||||
}
|
||||
|
||||
void PotWarnMatrix::onPress(uint8_t btn_id)
|
||||
{
|
||||
if (btn_id >= NUM_POTS) return;
|
||||
|
||||
g_model.potsWarnEnabled ^= (1 << btn_id);
|
||||
if ((g_model.potsWarnMode == POTS_WARN_MANUAL) &&
|
||||
(g_model.potsWarnEnabled & (1 << btn_id))) {
|
||||
SAVE_POT_POSITION(btn_id);
|
||||
}
|
||||
SET_DIRTY();
|
||||
}
|
||||
|
||||
bool PotWarnMatrix::isActive(uint8_t btn_id)
|
||||
{
|
||||
return (g_model.potsWarnEnabled & (1 << btn_id)) != 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "page.h"
|
||||
|
||||
struct PreflightChecks : public Page {
|
||||
PreflightChecks();
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 "throttle_params.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
static int16_t getThrottleSource()
|
||||
{
|
||||
return throttleSource2Source(g_model.thrTraceSrc);
|
||||
}
|
||||
|
||||
static void setThrottleSource(int16_t src)
|
||||
{
|
||||
int16_t val = source2ThrottleSource(src);
|
||||
if (val >= 0) {
|
||||
g_model.thrTraceSrc = val;
|
||||
SET_DIRTY();
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t getThrottleTrimSource()
|
||||
{
|
||||
return g_model.getThrottleStickTrimSource();
|
||||
}
|
||||
|
||||
static void setThrottleTrimSource(int16_t src)
|
||||
{
|
||||
g_model.setThrottleStickTrimSource(src);
|
||||
}
|
||||
|
||||
ThrottleParams::ThrottleParams() : Page(ICON_MODEL_SETUP)
|
||||
{
|
||||
new StaticText(&header,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_THROTTLE_LABEL, 0, COLOR_THEME_PRIMARY2);
|
||||
|
||||
body.setFlexLayout();
|
||||
FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
|
||||
|
||||
// Throttle reversed
|
||||
auto line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_THROTTLEREVERSE, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.throttleReversed));
|
||||
|
||||
// Throttle source
|
||||
line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_TTRACE, 0, COLOR_THEME_PRIMARY1);
|
||||
auto sc = new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST_CH,
|
||||
getThrottleSource, setThrottleSource,
|
||||
0, COLOR_THEME_PRIMARY1);
|
||||
sc->setAvailableHandler(isThrottleSourceAvailable);
|
||||
|
||||
// Throttle trim
|
||||
line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_TTRIM, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.thrTrim));
|
||||
|
||||
// Throttle trim source
|
||||
line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_TTRIM_SW, 0, COLOR_THEME_PRIMARY1);
|
||||
new SourceChoice(
|
||||
line, rect_t{}, MIXSRC_FIRST_TRIM, MIXSRC_LAST_TRIM,
|
||||
getThrottleTrimSource, setThrottleTrimSource, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "page.h"
|
||||
|
||||
struct ThrottleParams : public Page {
|
||||
ThrottleParams();
|
||||
};
|
||||
@@ -24,16 +24,6 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
TimerButton::TimerButton(Window* parent, const rect_t& rect, uint8_t timer) :
|
||||
TextButton(parent, rect, std::string(STR_TIMER) + std::to_string(timer + 1))
|
||||
{
|
||||
// TODO: add start time
|
||||
setPressHandler([=]() {
|
||||
new TimerWindow(timer);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: translation
|
||||
const char* STR_TIMER_MODES[] = {"OFF", "ON", "Start",
|
||||
"Throttle", "Throttle %", "Throttle Start"};
|
||||
|
||||
@@ -22,11 +22,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "page.h"
|
||||
#include "button.h"
|
||||
|
||||
struct TimerButton : public TextButton {
|
||||
TimerButton(Window* parent, const rect_t& rect, uint8_t timer);
|
||||
};
|
||||
|
||||
struct TimerWindow : public Page {
|
||||
TimerWindow(uint8_t timer);
|
||||
|
||||
@@ -24,6 +24,49 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
#include "form.h"
|
||||
#include "menu.h"
|
||||
#include "static.h"
|
||||
#include "button.h"
|
||||
#include "numberedit.h"
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
#include "bluetooth.h"
|
||||
#endif
|
||||
|
||||
class TrChoice;
|
||||
|
||||
class TrainerModuleWindow : public FormGroup
|
||||
{
|
||||
public:
|
||||
TrainerModuleWindow(FormWindow *parent, const rect_t &rect);
|
||||
|
||||
void checkEvents() override;
|
||||
void update();
|
||||
|
||||
protected:
|
||||
TrChoice *trainerChoice = nullptr;
|
||||
NumberEdit *channelStart = nullptr;
|
||||
NumberEdit *channelEnd = nullptr;
|
||||
bool trChoiceOpen = false;
|
||||
#if defined(BLUETOOTH)
|
||||
StaticText *btChannelEnd = nullptr;
|
||||
StaticText *btDistAddress = nullptr;
|
||||
TextButton *btMasterButton = nullptr;
|
||||
Menu *btPopUpMenu = nullptr;
|
||||
bool btCanceled = false;
|
||||
|
||||
private:
|
||||
bool popupopen = false;
|
||||
int devicecount = 0;
|
||||
uint8_t lastbluetoothstate = BLUETOOTH_STATE_OFF;
|
||||
|
||||
void btDiscoverMenuItemChosen();
|
||||
void btDiscoverMenuAddItem(const char *itm);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
class TrChoice : public Choice
|
||||
{
|
||||
public:
|
||||
@@ -283,3 +326,13 @@ void TrainerModuleWindow::btDiscoverMenuAddItem(const char *itm)
|
||||
itm, std::bind(&TrainerModuleWindow::btDiscoverMenuItemChosen, this));
|
||||
}
|
||||
#endif
|
||||
|
||||
TrainerPage::TrainerPage() : Page(ICON_MODEL_SETUP)
|
||||
{
|
||||
new StaticText(&header,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_TRAINER, 0, COLOR_THEME_PRIMARY2);
|
||||
|
||||
new TrainerModuleWindow(&body, {0, 0, width(), 0});
|
||||
}
|
||||
|
||||
@@ -21,45 +21,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "form.h"
|
||||
#include "menu.h"
|
||||
#include "static.h"
|
||||
#include "button.h"
|
||||
#include "numberedit.h"
|
||||
#include "page.h"
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
#include "bluetooth.h"
|
||||
#endif
|
||||
|
||||
class TrChoice;
|
||||
|
||||
class TrainerModuleWindow : public FormGroup
|
||||
{
|
||||
public:
|
||||
TrainerModuleWindow(FormWindow *parent, const rect_t &rect);
|
||||
|
||||
void checkEvents() override;
|
||||
void update();
|
||||
|
||||
protected:
|
||||
TrChoice *trainerChoice = nullptr;
|
||||
NumberEdit *channelStart = nullptr;
|
||||
NumberEdit *channelEnd = nullptr;
|
||||
bool trChoiceOpen = false;
|
||||
#if defined(BLUETOOTH)
|
||||
StaticText *btChannelEnd = nullptr;
|
||||
StaticText *btDistAddress = nullptr;
|
||||
TextButton *btMasterButton = nullptr;
|
||||
Menu *btPopUpMenu = nullptr;
|
||||
bool btCanceled = false;
|
||||
|
||||
private:
|
||||
bool popupopen = false;
|
||||
int devicecount = 0;
|
||||
uint8_t lastbluetoothstate = BLUETOOTH_STATE_OFF;
|
||||
|
||||
void btDiscoverMenuItemChosen();
|
||||
void btDiscoverMenuAddItem(const char *itm);
|
||||
|
||||
#endif
|
||||
struct TrainerPage: public Page {
|
||||
TrainerPage();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 "trims_setup.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
static void resetTrims()
|
||||
{
|
||||
for (auto &fm : g_model.flightModeData) memclear(&fm.trim, sizeof(fm.trim));
|
||||
SET_DIRTY();
|
||||
AUDIO_WARNING1();
|
||||
}
|
||||
|
||||
TrimsSetup::TrimsSetup() : Page(ICON_MODEL_SETUP)
|
||||
{
|
||||
new StaticText(&header,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_TRIMS, 0, COLOR_THEME_PRIMARY2);
|
||||
|
||||
body.setFlexLayout();
|
||||
FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
|
||||
|
||||
// Trim step
|
||||
auto line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_TRIMINC, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new Choice(line, rect_t{}, STR_VTRIMINC, -2, 2,
|
||||
GET_SET_DEFAULT(g_model.trimInc));
|
||||
|
||||
// Extended trims
|
||||
line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_ETRIMS, 0, COLOR_THEME_PRIMARY1);
|
||||
new CheckBox(line, rect_t{}, GET_SET_DEFAULT(g_model.extendedTrims));
|
||||
|
||||
// Reset trims
|
||||
line = body.newLine(&grid);
|
||||
new TextButton(line, rect_t{}, STR_RESET_BTN, []() -> uint8_t {
|
||||
resetTrims();
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Display trims
|
||||
// TODO: move to "Screen setup" ?
|
||||
line = body.newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_DISPLAY_TRIMS, 0, COLOR_THEME_PRIMARY1);
|
||||
new Choice(line, rect_t{}, STR_VDISPLAYTRIMS, 0, 2,
|
||||
GET_SET_DEFAULT(g_model.displayTrims));
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "page.h"
|
||||
|
||||
struct TrimsSetup : public Page {
|
||||
TrimsSetup();
|
||||
};
|
||||
@@ -1001,7 +1001,7 @@ const char* STR_SUBTYPE_HUBSAN[] = {"H107","H301","H501"};
|
||||
const char* STR_SUBTYPE_FRSKY[] = {"D16","D8","D16 8ch","V8","LBT(EU)","LBT 8ch","D8Cloned","D16Cloned"};
|
||||
const char* STR_SUBTYPE_HISKY[] = {"Std","HK310"};
|
||||
const char* STR_SUBTYPE_V2X2[] = {"Std","JXD506","MR101"};
|
||||
const char* STR_SUBTYPE_DSM[] = {"2 1F","2 2F","X 1F,""X 2F,""Auto","R 1F"};
|
||||
const char* STR_SUBTYPE_DSM[] = {"2 1F","2 2F","X 1F","X 2F","Auto","R 1F"};
|
||||
const char* STR_SUBTYPE_DEVO[] = {"8ch","10ch","12ch","6ch","7ch"};
|
||||
const char* STR_SUBTYPE_YD717[] = {"Std","SkyWlkr","Syma X4","XINXUN","NIHUI"};
|
||||
const char* STR_SUBTYPE_KN[] = {"WLtoys","FeiLun"};
|
||||
|
||||
Vendored
+1
-1
Submodule radio/src/thirdparty/libopenui updated: a877a5ff4b...5bd6a5ddac
Reference in New Issue
Block a user