diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 84e41732b..4ac29d8c9 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -54,6 +54,7 @@ set(GUI_SRC trainer_setup.cpp custom_failsafe.cpp ppm_settings.cpp + channel_range.cpp module_setup.cpp timer_setup.cpp trims_setup.cpp diff --git a/radio/src/gui/colorlcd/channel_range.cpp b/radio/src/gui/colorlcd/channel_range.cpp new file mode 100644 index 000000000..2590451cf --- /dev/null +++ b/radio/src/gui/colorlcd/channel_range.cpp @@ -0,0 +1,192 @@ +/* + * 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 "channel_range.h" +#include "opentx.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +ChannelRange::ChannelRange(Window* parent) : + FormGroup(parent, rect_t{}) +{ + setFlexLayout(LV_FLEX_FLOW_ROW); +} + +void ChannelRange::build() +{ + chStart = new NumberEdit(this, rect_t{}, 1, 1, GET_DEFAULT(1 + getChannelsStart())); + chStart->setSetValueHandler([=](int newValue) { setStart(newValue); }); + chStart->setPrefix(STR_CH); + + chEnd = new NumberEdit(this, rect_t{}, 8, 8, + GET_DEFAULT(getChannelsStart() + 8 + getChannelsCount())); + + chEnd->setPrefix(STR_CH); + chEnd->setSetValueHandler([=](int newValue) { setEnd(newValue); }); +} + +void ChannelRange::setStart(uint8_t newValue) +{ + setChannelsStart(newValue - 1); + updateEnd(); + SET_DIRTY(); +} + +void ChannelRange::setEnd(uint8_t newValue) +{ + setChannelsCount(newValue - getChannelsStart() - 8); + updateStart(); + SET_DIRTY(); +} + +void ChannelRange::updateEnd() +{ + auto min_ch = getChannelsStart() + getChannelsMin(); + chEnd->setMin(min_ch); + + auto max_ch = getChannelsStart() + getChannelsMax(); + max_ch = min(MAX_OUTPUT_CHANNELS, max_ch); + chEnd->setMax(max_ch); + chEnd->setDefault(max_ch); + + chEnd->update(); +} + +void ChannelRange::updateStart() +{ + chStart->setMax(MAX_OUTPUT_CHANNELS - getChannelsUsed() + 1); +} + +void ChannelRange::update() +{ + updateStart(); + updateEnd(); +} + +ModuleChannelRange::ModuleChannelRange(Window* parent, uint8_t moduleIdx) : + ChannelRange(parent), moduleIdx(moduleIdx) +{ + build(); + update(); +} + +void ModuleChannelRange::update() +{ + ChannelRange::update(); + + auto min_mod_ch = minModuleChannels(moduleIdx); + auto max_mod_ch = maxModuleChannels(moduleIdx); + chEnd->enable(min_mod_ch < max_mod_ch); + + if (chEnd->getValue() > chEnd->getMax()) + chEnd->setValue(chEnd->getMax()); + + if (!isModulePXX2(moduleIdx)) { + chEnd->setAvailableHandler(nullptr); + } +#if defined(PXX2) + else { + chEnd->setAvailableHandler( + [=](int value) { return isPxx2IsrmChannelsCountAllowed(value - 8); }); + } +#endif +} + +uint8_t ModuleChannelRange::getChannelsStart() +{ + ModuleData* md = &g_model.moduleData[moduleIdx]; + return md->channelsStart; +} + +void ModuleChannelRange::setChannelsStart(uint8_t val) +{ + ModuleData* md = &g_model.moduleData[moduleIdx]; + md->channelsStart = val; +} + +int8_t ModuleChannelRange::getChannelsCount() +{ + ModuleData* md = &g_model.moduleData[moduleIdx]; + return md->channelsCount; +} + +void ModuleChannelRange::setChannelsCount(int8_t val) +{ + ModuleData* md = &g_model.moduleData[moduleIdx]; + md->channelsCount = val; +} + +uint8_t ModuleChannelRange::getChannelsUsed() +{ + return sentModuleChannels(moduleIdx); +} + +uint8_t ModuleChannelRange::getChannelsMin() +{ + return minModuleChannels(moduleIdx); +} + +uint8_t ModuleChannelRange::getChannelsMax() +{ + return maxModuleChannels(moduleIdx); +} + +TrainerChannelRange::TrainerChannelRange(Window* parent) : + ChannelRange(parent) +{ + build(); + update(); +} + +uint8_t TrainerChannelRange::getChannelsStart() +{ + return g_model.trainerData.channelsStart; +} + +void TrainerChannelRange::setChannelsStart(uint8_t val) +{ + g_model.trainerData.channelsStart = val; +} + +int8_t TrainerChannelRange::getChannelsCount() +{ + return g_model.trainerData.channelsCount; +} + +void TrainerChannelRange::setChannelsCount(int8_t val) +{ + g_model.trainerData.channelsCount = val; +} + +uint8_t TrainerChannelRange::getChannelsUsed() +{ + return 8 + getChannelsCount(); +} + +uint8_t TrainerChannelRange::getChannelsMin() +{ + return MIN_TRAINER_CHANNELS; +} + +uint8_t TrainerChannelRange::getChannelsMax() +{ + return MAX_TRAINER_CHANNELS; +} diff --git a/radio/src/gui/colorlcd/channel_range.h b/radio/src/gui/colorlcd/channel_range.h new file mode 100644 index 000000000..87dd07696 --- /dev/null +++ b/radio/src/gui/colorlcd/channel_range.h @@ -0,0 +1,90 @@ +/* + * 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 "form.h" +#include "numberedit.h" + +class ChannelRange : public FormGroup +{ + public: + ChannelRange(Window* parent); + + void setStart(uint8_t newValue); + void setEnd(uint8_t newValue); + + virtual void update(); + void updateStart(); + void updateEnd(); + + protected: + NumberEdit* chStart; + NumberEdit* chEnd; + + void build(); + + virtual uint8_t getChannelsStart() = 0; + virtual void setChannelsStart(uint8_t val) = 0; + + virtual int8_t getChannelsCount() = 0; + virtual void setChannelsCount(int8_t val) = 0; + + virtual uint8_t getChannelsUsed() = 0; + virtual uint8_t getChannelsMin() = 0; + virtual uint8_t getChannelsMax() = 0; +}; + +class ModuleChannelRange : public ChannelRange +{ + uint8_t moduleIdx; + + void update() override; + + uint8_t getChannelsStart() override; + void setChannelsStart(uint8_t val) override; + + int8_t getChannelsCount() override; + void setChannelsCount(int8_t val) override; + + uint8_t getChannelsUsed() override; + uint8_t getChannelsMin() override; + uint8_t getChannelsMax() override; + + public: + ModuleChannelRange(Window* parent, uint8_t moduleIdx); +}; + +class TrainerChannelRange : public ChannelRange +{ + uint8_t getChannelsStart() override; + void setChannelsStart(uint8_t val) override; + + int8_t getChannelsCount() override; + void setChannelsCount(int8_t val) override; + + uint8_t getChannelsUsed() override; + uint8_t getChannelsMin() override; + uint8_t getChannelsMax() override; + + public: + TrainerChannelRange(Window* parent); +}; diff --git a/radio/src/gui/colorlcd/module_setup.cpp b/radio/src/gui/colorlcd/module_setup.cpp index c6791a1fe..031912938 100644 --- a/radio/src/gui/colorlcd/module_setup.cpp +++ b/radio/src/gui/colorlcd/module_setup.cpp @@ -30,6 +30,7 @@ #include "bind_menu_d16.h" #include "custom_failsafe.h" #include "ppm_settings.h" +#include "channel_range.h" #if defined(PXX2) #include "access_settings.h" @@ -60,101 +61,6 @@ static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; -struct ChannelRange : public FormGroup { - uint8_t moduleIdx; - NumberEdit* chStart; - NumberEdit* chEnd; - - ChannelRange(Window* parent, uint8_t moduleIdx); - - void setStart(uint32_t newValue); - void setEnd(uint32_t newValue); - - void update(); - void updateStart(); - void updateEnd(); -}; - -ChannelRange::ChannelRange(Window* parent, uint8_t moduleIdx) : - FormGroup(parent, rect_t{}), moduleIdx(moduleIdx) -{ - setFlexLayout(LV_FLEX_FLOW_ROW); - - ModuleData* md = &g_model.moduleData[moduleIdx]; - chStart = new NumberEdit(this, rect_t{}, 1, 1, GET_DEFAULT(1 + md->channelsStart)); - - chStart->setPrefix(STR_CH); - chStart->setSetValueHandler([=](int32_t newValue) { setStart(newValue); }); - - chEnd = new NumberEdit(this, rect_t{}, 8, 8, - GET_DEFAULT(md->channelsStart + 8 + md->channelsCount)); - - chEnd->setPrefix(STR_CH); - chEnd->setSetValueHandler([=](int32_t newValue) { setEnd(newValue); }); - - update(); -} - -void ChannelRange::setStart(uint32_t newValue) -{ - ModuleData* md = &g_model.moduleData[moduleIdx]; - md->channelsStart = newValue - 1; - updateEnd(); - SET_DIRTY(); -} - -void ChannelRange::setEnd(uint32_t newValue) -{ - ModuleData* md = &g_model.moduleData[moduleIdx]; - md->channelsCount = newValue - md->channelsStart - 8; - updateStart(); - SET_DIRTY(); -} - -void ChannelRange::updateEnd() -{ - ModuleData* md = &g_model.moduleData[moduleIdx]; - auto min_ch = md->channelsStart + minModuleChannels(moduleIdx); - chEnd->setMin(min_ch); - - auto max_ch = md->channelsStart + maxModuleChannels(moduleIdx); - max_ch = min(MAX_OUTPUT_CHANNELS, max_ch); - chEnd->setMax(max_ch); - chEnd->setDefault(max_ch); - - chEnd->update(); -} - -void ChannelRange::updateStart() -{ - chStart->setMax(MAX_OUTPUT_CHANNELS - sentModuleChannels(moduleIdx) + 1); -} - -void ChannelRange::update() -{ - // ModuleData* md = &g_model.moduleData[moduleIdx]; - - updateStart(); - updateEnd(); - - auto min_mod_ch = minModuleChannels(moduleIdx); - auto max_mod_ch = maxModuleChannels(moduleIdx); - chEnd->enable(min_mod_ch < max_mod_ch); - - if (chEnd->getValue() > chEnd->getMax()) - chEnd->setValue(chEnd->getMax()); - - if (!isModulePXX2(moduleIdx)) { - chEnd->setAvailableHandler(nullptr); - } -#if defined(PXX2) - else { - chEnd->setAvailableHandler( - [=](int value) { return isPxx2IsrmChannelsCountAllowed(value - 8); }); - } -#endif -} - class ModuleWindow : public FormGroup { public: @@ -259,7 +165,7 @@ void ModuleWindow::updateModule() // Channel Range auto line = newLine(&grid); new StaticText(line, rect_t{}, STR_CHANNELRANGE, 0, COLOR_THEME_PRIMARY1); - chRange = new ChannelRange(line, moduleIdx); + chRange = new ModuleChannelRange(line, moduleIdx); // PPM modules if (isModulePPM(moduleIdx)) { diff --git a/radio/src/gui/colorlcd/trainer_setup.cpp b/radio/src/gui/colorlcd/trainer_setup.cpp index ddd247aa7..4b91defb4 100644 --- a/radio/src/gui/colorlcd/trainer_setup.cpp +++ b/radio/src/gui/colorlcd/trainer_setup.cpp @@ -188,6 +188,7 @@ void TrainerModuleWindow::update() } else #endif if (g_model.trainerData.mode == TRAINER_MODE_SLAVE) { + // TODO: use generic ChannelRange #define PPMCH_START_MIN 1 #define PPMCH_START_MAX \ (MAX_OUTPUT_CHANNELS - g_model.trainerData.channelsCount + 1 - \