diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d846e898..74e6ccca0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ project(OpenTX) set(VERSION_MAJOR "2") set(VERSION_MINOR "3") -set(VERSION_REVISION "11") +set(VERSION_REVISION "12") set(VERSION_SUFFIX $ENV{OPENTX_VERSION_SUFFIX}) set(VERSION_FAMILY ${VERSION_MAJOR}.${VERSION_MINOR}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}${VERSION_SUFFIX}) diff --git a/CREDITS.txt b/CREDITS.txt index 5fb57cece..85246719c 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -2069,3 +2069,32 @@ Raoul Piccioli Uwe Probst Glendon Satchell Trevor Collins +Horst Grashauser +Miguel José Cárdenas Herrera +Mike Jennings +José Bernardo +Carlos Dangle +Gordon Evans +Pablo Peinado Abad +Carl Payne +Adam Sosnowski +Гасак Сергей +SaltCtyRacingFPV +Georg Bernhardt +James Mildenhall +Dave Plummer +Ivan Mokris +Patrick Daniels +Stuart Olson +Cory Znebel +Andrey Yarovoy +Christian Pons +Burt Pickard-Richardson +Michal Mesaros +Conrad Young +Martin Mathes +Jens Rainer Hansen +Mark Trible +Marc Dubois +Alan Wilkins +Daniel Hryciuk diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 2f05ab859..3853466d9 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -347,6 +347,8 @@ elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TLITE) set(FLAVOUR tlite) elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TX12) set(FLAVOUR tx12) +elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T8) + set(FLAVOUR t8) elseif(PCB STREQUAL X9D+ AND PCBREV STREQUAL 2019) set(FLAVOUR x9d+2019) elseif(PCB STREQUAL X10 AND PCBREV STREQUAL EXPRESS) diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc index e4d15c183..c76418135 100644 --- a/companion/src/companion.qrc +++ b/companion/src/companion.qrc @@ -200,6 +200,18 @@ images/simulator/TX12/right-mdl.png images/simulator/TX12/bottom.png images/simulator/TX12/top.png + images/simulator/T8/left.png + images/simulator/T8/left-pageup.png + images/simulator/T8/left-pagedn.png + images/simulator/T8/left-rtn.png + images/simulator/T8/left-sys.png + images/simulator/T8/right.png + images/simulator/T8/right-ent.png + images/simulator/T8/right-mdl.png + images/simulator/T8/right-up.png + images/simulator/T8/right-dn.png + images/simulator/T8/bottom.png + images/simulator/T8/top.png images/simulator/JumperT16/left.png images/simulator/JumperT16/right.png images/simulator/JumperT16/top.png diff --git a/companion/src/datamodels/CMakeLists.txt b/companion/src/datamodels/CMakeLists.txt index beb7d4d2d..446f161b3 100644 --- a/companion/src/datamodels/CMakeLists.txt +++ b/companion/src/datamodels/CMakeLists.txt @@ -1,12 +1,12 @@ set(datamodels_SRCS - rawitemdatamodels.cpp - rawitemfilteredmodel.cpp + compounditemmodels.cpp + filtereditemmodels.cpp ) set(datamodels_HDRS - rawitemdatamodels.h - rawitemfilteredmodel.h + compounditemmodels.h + filtereditemmodels.h ) qt5_wrap_cpp(datamodels_SRCS ${datamodels_HDRS}) diff --git a/companion/src/datamodels/compounditemmodels.cpp b/companion/src/datamodels/compounditemmodels.cpp new file mode 100644 index 000000000..039e90244 --- /dev/null +++ b/companion/src/datamodels/compounditemmodels.cpp @@ -0,0 +1,705 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "compounditemmodels.h" +#include "generalsettings.h" +#include "eeprominterface.h" +#include "modeldata.h" +#include "adjustmentreference.h" + +// static +QString AbstractItemModel::idToString(const int value) +{ + switch (value) { + case IMID_Unknown: + return "Unknown"; + case IMID_RawSource: + return "RawSource"; + case IMID_RawSwitch: + return "RawSwitch"; + case IMID_Curve: + return "Curve"; + case IMID_GVarRef: + return "GVarRef"; + case IMID_ThrSource: + return "ThrSource"; + case IMID_CustomFuncAction: + return "CustomFuncAction"; + case IMID_CustomFuncResetParam: + return "CustomFuncResetParam"; + case IMID_TeleSource: + return "TeleSource"; + case IMID_CurveRefType: + return "CurveRefType"; + case IMID_CurveRefFunc: + return "CurveRefFunc"; + default: + return "Custom"; + } +} + +// static +void AbstractItemModel::dumpItemModelContents(AbstractItemModel * itemModel) +{ + if (itemModel) { + qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName(); + + for (int i = 0; i < itemModel->rowCount(); ++i) { + qDebug() << "row:" << i + << "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString() + << "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt() + << "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool() + << "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt() + << "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt(); + } + } + else + qDebug() << "Error: model not of class AbstractItemModel"; +} + +// +// AbstractStaticItemModel +// + +void AbstractStaticItemModel::loadItemList() +{ + foreach (const ListItem *item, itemList) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(item->text); + modelItem->setData(item->id, IMDR_Id); + modelItem->setData(item->type, IMDR_Type); + modelItem->setData(item->flags, IMDR_Flags); + modelItem->setData(item->isAvailable, IMDR_Available); + appendRow(modelItem); + } + + itemList.clear(); +}; + +// +// RawSourceItemModel +// + +RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_RawSource); + setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts)); + + addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1); + for (int i = 0; i < firmware->getCapability(LuaScripts); i++) + addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16); + addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs)); + addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs)); + addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, firmware->getCapability(RotaryEncoders)); + addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims)); + addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1); + addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches)); + addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, firmware->getCapability(LogicalSwitches)); + addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC); + addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs)); + addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, firmware->getCapability(Outputs)); + addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5); + addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, firmware->getCapability(Sensors) * 3); + addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, firmware->getCapability(Gvars)); +} + +void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const +{ + item->setText(src.toString(modelData, generalSettings, boardType)); + item->setData(src.isAvailable(modelData, generalSettings, boardType), IMDR_Available); +} + +void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start) +{ + for (int i = start; i < start + count; i++) { + const RawSource src = RawSource(type, i); + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(src.toValue(), IMDR_Id); + modelItem->setData(type, IMDR_Type); + modelItem->setData(group, IMDR_Flags); + setDynamicItemData(modelItem, src); + appendRow(modelItem); + } +} + +void RawSourceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), RawSource(item(i)->data(IMDR_Id).toInt())); + + emit updateComplete(); + } +} + +// +// RawSwitchItemModel +// + +RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_RawSwitch); + setUpdateMask(IMUE_FlightModes | IMUE_LogicalSwitches | IMUE_TeleSensors); + + // Descending switch direction: NOT (!) switches + addItems(SWITCH_TYPE_ACT, -1); + addItems(SWITCH_TYPE_SENSOR, -firmware->getCapability(Sensors)); + addItems(SWITCH_TYPE_TELEMETRY, -1); + addItems(SWITCH_TYPE_FLIGHT_MODE, -firmware->getCapability(FlightModes)); + addItems(SWITCH_TYPE_VIRTUAL, -firmware->getCapability(LogicalSwitches)); + addItems(SWITCH_TYPE_ROTARY_ENCODER, -firmware->getCapability(RotaryEncoders)); + addItems(SWITCH_TYPE_TRIM, -board->getCapability(Board::NumTrimSwitches)); + addItems(SWITCH_TYPE_MULTIPOS_POT, -(board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions))); + addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchPositions)); + + // Ascending switch direction (including zero) + addItems(SWITCH_TYPE_TIMER_MODE, 5); + addItems(SWITCH_TYPE_NONE, 1); + addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchPositions)); + addItems(SWITCH_TYPE_MULTIPOS_POT, board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions)); + addItems(SWITCH_TYPE_TRIM, board->getCapability(Board::NumTrimSwitches)); + addItems(SWITCH_TYPE_ROTARY_ENCODER, firmware->getCapability(RotaryEncoders)); + addItems(SWITCH_TYPE_VIRTUAL, firmware->getCapability(LogicalSwitches)); + addItems(SWITCH_TYPE_FLIGHT_MODE, firmware->getCapability(FlightModes)); + addItems(SWITCH_TYPE_TELEMETRY, 1); + addItems(SWITCH_TYPE_SENSOR, firmware->getCapability(Sensors)); + addItems(SWITCH_TYPE_ON, 1); + addItems(SWITCH_TYPE_ONE, 1); + addItems(SWITCH_TYPE_ACT, 1); +} + +void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const +{ + item->setText(rsw.toString(boardType, generalSettings, modelData)); + item->setData(rsw.isAvailable(modelData, generalSettings, boardType), IMDR_Available); +} + +void RawSwitchItemModel::addItems(const RawSwitchType & type, int count) +{ + // Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule: + const static QVector rawSwitchIndexBaseZeroTypes = QVector() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE; + // handle exceptions in RawSwitch() index values + const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0; + + // determine cotext flags + int context = RawSwitch::AllSwitchContexts; + switch (type) { + case SWITCH_TYPE_FLIGHT_MODE: + context &= ~RawSwitch::MixesContext; + // fallthrough + case SWITCH_TYPE_VIRTUAL: + case SWITCH_TYPE_SENSOR: + context &= ~RawSwitch::GlobalFunctionsContext; + break; + + case SWITCH_TYPE_TIMER_MODE: + context = RawSwitch::TimersContext; + break; + + case SWITCH_TYPE_NONE: + context &= ~RawSwitch::TimersContext; + break; + + case SWITCH_TYPE_ON: + case SWITCH_TYPE_ONE: + context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext; + break; + + default: + break; + } + + int i = (count < 0 ? count : 1); + count = (i < 0 ? 0 : count + i); + for ( ; i < count; ++i) { + RawSwitch rs(type, i + rawIdxAdj); + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(rs.toValue(), IMDR_Id); + modelItem->setData(type, IMDR_Type); + modelItem->setData(context, IMDR_Flags); + setDynamicItemData(modelItem, rs); + appendRow(modelItem); + } +} + +void RawSwitchItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), RawSwitch(item(i)->data(IMDR_Id).toInt())); + + emit updateComplete(); + } +} + +// +// CurveItemModel +// + +CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_Curve); + + if (!modelData) + return; + + setUpdateMask(IMUE_Curves); + + const int count = firmware->getCapability(NumCurves); + + for (int i = -count ; i <= count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CurveItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + CurveReference cr = CurveReference(CurveReference::CURVE_REF_CUSTOM, value); + item->setText(cr.toString(modelData, false)); + item->setData(cr.isAvailable(), IMDR_Available); +} + +void CurveItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// GVarReferenceItemModel +// + +GVarReferenceItemModel::GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_GVarRef); + + if (!modelData) + return; + + setUpdateMask(IMUE_GVars | IMUE_FlightModes | IMUE_LogicalSwitches); + + const int count = firmware->getCapability(Gvars); + + if (count > 0) { + addItems(-count); + addItems(count); + } +} + +void GVarReferenceItemModel::addItems(int count) +{ + int i = (count < 0 ? count : 1); + count = (i < 0 ? 0 : count + i); + for ( ; i < count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + AdjustmentReference ar(AdjustmentReference::ADJUST_REF_GVAR, i); + modelItem->setData(ar.toValue(), IMDR_Id); + modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); + setDynamicItemData(modelItem, ar); + appendRow(modelItem); + } +} + +void GVarReferenceItemModel::setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const +{ + item->setText(ar.toString(modelData, false)); + item->setData(ar.isAvailable(), IMDR_Available); +} + +void GVarReferenceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), AdjustmentReference(item(i)->data(IMDR_Id).toInt())); + + emit updateComplete(); + } +} + +// +// ThrottleSourceItemModel +// + +ThrottleSourceItemModel::ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_ThrSource); + + if (!modelData) + return; + + setUpdateMask(IMUE_Timers | IMUE_Inputs | IMUE_TeleSensors); + + for (int i = 0; i < modelData->thrTraceSrcCount(); i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void ThrottleSourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + item->setText(modelData->thrTraceSrcToString(value)); + item->setData(modelData->isThrTraceSrcAvailable(generalSettings, value), IMDR_Available); +} + +void ThrottleSourceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// CustomFuncActionItemModel +// + +CustomFuncActionItemModel::CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CustomFuncAction); + setUpdateMask(IMUE_All &~ (IMUE_Curves | IMUE_Scripts)); + + for (int i = 0; i < AssignFunc::FuncCount; i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + modelItem->setData(CustomFunctionData::funcContext(i), IMDR_Flags); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CustomFuncActionItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + item->setText(CustomFunctionData(AssignFunc(value)).funcToString(modelData)); + item->setData(CustomFunctionData::isFuncAvailable(value), IMDR_Available); +} + +void CustomFuncActionItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// CustomFuncResetParamItemModel +// + +CustomFuncResetParamItemModel::CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CustomFuncResetParam); + setUpdateMask(IMUE_TeleSensors); + + for (int i = 0; i < CustomFunctionData::resetParamCount(modelData); i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void CustomFuncResetParamItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + CustomFunctionData cfd = CustomFunctionData(AssignFunc::FuncReset); + cfd.param = value; + item->setText(cfd.paramToString(modelData)); + item->setData(CustomFunctionData::isResetParamAvailable(modelData, value), IMDR_Available); +} + +void CustomFuncResetParamItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + + emit updateComplete(); + } +} + +// +// TelemetrySourceItemModel +// + +TelemetrySourceItemModel::TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_TeleSource); + + if (!modelData) + return; + + setUpdateMask(IMUE_TeleSensors); + const int count = firmware->getCapability(Sensors); + + for (int i = -count; i <= count; ++i) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setData(i, IMDR_Id); + modelItem->setData(i < 0 ? IMDG_Negative : i > 0 ? IMDG_Positive : IMDG_None, IMDR_Flags); + setDynamicItemData(modelItem, i); + appendRow(modelItem); + } +} + +void TelemetrySourceItemModel::setDynamicItemData(QStandardItem * item, const int value) const +{ + item->setText(SensorData::sourceToString(modelData, value)); + item->setData(SensorData::isSourceAvailable(modelData, value), IMDR_Available); +} + +void TelemetrySourceItemModel::update(const int event) +{ + if (doUpdate(event)) { + emit aboutToBeUpdated(); + + for (int i = 0; i < rowCount(); ++i) { + setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt()); + } + + emit updateComplete(); + } +} + +// +// CurveRefTypeItemModel +// + +CurveRefTypeItemModel::CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CurveRefType); + + for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(CurveReference::typeToString((CurveReference::CurveRefType)i)); + modelItem->setData(i, IMDR_Id); + modelItem->setData(CurveReference::isTypeAvailable((CurveReference::CurveRefType)i), IMDR_Available); + appendRow(modelItem); + } +} + +// +// CurveRefFuncItemModel +// + +CurveRefFuncItemModel::CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractStaticItemModel(generalSettings, modelData, firmware, board, boardType) +{ + setId(IMID_CurveRefFunc); + + for (int i = 1; i <= CurveReference::functionCount(); i++) { + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(CurveReference::functionToString(i)); + modelItem->setData(i, IMDR_Id); + modelItem->setData(CurveReference::isFunctionAvailable(i), IMDR_Available); + appendRow(modelItem); + } +} + +// +// PrecisionItemModel +// + +PrecisionItemModel::PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix, const bool placeholders) : + AbstractStaticItemModel() +{ + for (int i = minDecimals, j = maxDecimals; j >= 0; i++, j--) { + QString str = QString("0.%1").arg(QString(i, '0')); + if (placeholders) + str.append(QString(j, '_')); + if (!suffix.isEmpty()) + str.append(QString(" %1").arg(suffix)); + QStandardItem * modelItem = new QStandardItem(); + modelItem->setText(str); + modelItem->setData(i, IMDR_Id); + modelItem->setData(true, IMDR_Available); + appendRow(modelItem); + } +} + +// +// CompoundItemModelFactory +// + +CompoundItemModelFactory::CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData) : + generalSettings(generalSettings), + modelData(modelData) +{ + firmware = getCurrentFirmware(); + board = new Boards(getCurrentBoard()); + boardType = getCurrentBoard(); +} + +CompoundItemModelFactory::~CompoundItemModelFactory() +{ + unregisterItemModels(); + delete board; +} + +void CompoundItemModelFactory::addItemModel(const int id) +{ + switch (id) { + case AbstractItemModel::IMID_RawSource: + registerItemModel(new RawSourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_RawSwitch: + registerItemModel(new RawSwitchItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_Curve: + registerItemModel(new CurveItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_GVarRef: + registerItemModel(new GVarReferenceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_ThrSource: + registerItemModel(new ThrottleSourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CustomFuncAction: + registerItemModel(new CustomFuncActionItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CustomFuncResetParam: + registerItemModel(new CustomFuncResetParamItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_TeleSource: + registerItemModel(new TelemetrySourceItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CurveRefType: + registerItemModel(new CurveRefTypeItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + case AbstractItemModel::IMID_CurveRefFunc: + registerItemModel(new CurveRefFuncItemModel(generalSettings, modelData, firmware, board, boardType)); + break; + default: + qDebug() << "Error: unknown item model: id"; + break; + } +} + +int CompoundItemModelFactory::registerItemModel(AbstractItemModel * itemModel) +{ + if (itemModel) { + if (!isItemModelRegistered(itemModel->getId())) { + setSourceId(itemModel); + registeredItemModels.append(itemModel); + return itemModel->getId(); + } + else + return itemModel->getId(); + } + return -1; +} + +void CompoundItemModelFactory::unregisterItemModels() +{ + foreach (AbstractItemModel *itemModel, registeredItemModels) { + delete itemModel; + } +} + +void CompoundItemModelFactory::unregisterItemModel(const int id) +{ + AbstractItemModel * itemModel = getItemModel(id); + if (itemModel) + delete itemModel; +} + +AbstractItemModel * CompoundItemModelFactory::getItemModel(const int id) const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return itemModel; + } + + return nullptr; +} + +bool CompoundItemModelFactory::isItemModelRegistered(const int id) const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return true; + } + + return false; +} + +void CompoundItemModelFactory::update(const int event) +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + itemModel->update(event); + } +} + +void CompoundItemModelFactory::dumpAllItemModelContents() const +{ + foreach (AbstractItemModel * itemModel, registeredItemModels) { + AbstractItemModel::dumpItemModelContents(itemModel); + } +} + +void CompoundItemModelFactory::setSourceId(AbstractItemModel * itemModel) +{ + if (itemModel && itemModel->getId() == AbstractItemModel::IMID_Unknown) + itemModel->setId(AbstractItemModel::IMID_ReservedCount + registeredItemModels.count()); +} diff --git a/companion/src/datamodels/compounditemmodels.h b/companion/src/datamodels/compounditemmodels.h new file mode 100644 index 000000000..de32fc902 --- /dev/null +++ b/companion/src/datamodels/compounditemmodels.h @@ -0,0 +1,365 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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. + */ + +#ifndef COMPOUNDITEMMODELS_H +#define COMPOUNDITEMMODELS_H + +#include "rawsource.h" +#include "rawswitch.h" + +#include + +class GeneralSettings; +class ModelData; +class AdjustmentReference; + +class AbstractItemModel: public QStandardItemModel +{ + Q_OBJECT + public: + enum ItemModelId { + IMID_Unknown, + IMID_RawSource, + IMID_RawSwitch, + IMID_Curve, + IMID_GVarRef, + IMID_ThrSource, + IMID_CustomFuncAction, + IMID_CustomFuncResetParam, + IMID_TeleSource, + IMID_CurveRefType, + IMID_CurveRefFunc, + IMID_ReservedCount, + IMID_Custom + }; + Q_ENUM(ItemModelId) + + enum ItemModelDataRoles { + IMDR_Id = Qt::UserRole, + IMDR_Type, + IMDR_Flags, + IMDR_Available + }; + Q_ENUM(ItemModelDataRoles) + + enum ItemModelDataGroups { + IMDG_None = 0x01, + IMDG_Negative = 0x02, + IMDG_Positive = 0x04 + }; + Q_ENUM(ItemModelDataGroups) + + enum ItemModelUpdateEvent { + IMUE_None = 0, + IMUE_SystemRefresh = 1 << 0, + IMUE_Channels = 1 << 1, + IMUE_Curves = 1 << 2, + IMUE_FlightModes = 1 << 3, + IMUE_GVars = 1 << 4, + IMUE_Inputs = 1 << 5, + IMUE_LogicalSwitches = 1 << 6, + IMUE_Scripts = 1 << 7, + IMUE_TeleSensors = 1 << 8, + IMUE_Timers = 1 << 9, + IMUE_All = IMUE_SystemRefresh | IMUE_Channels | IMUE_Curves | IMUE_FlightModes | IMUE_GVars | IMUE_Inputs | + IMUE_LogicalSwitches | IMUE_Scripts | IMUE_TeleSensors | IMUE_Timers + }; + Q_ENUM(ItemModelUpdateEvent) + + explicit AbstractItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + QStandardItemModel(nullptr), + generalSettings(generalSettings), + modelData(modelData), + firmware(firmware), + board(board), + boardType(boardType), + m_id(IMID_Unknown), + m_name(""), + m_updateMask(IMUE_None) + {} + + virtual ~AbstractItemModel() {} + + void setId(int id) { m_id = id; } + int getId () const { return m_id; } + bool isReservedModelId() const { return m_id > IMID_Unknown && m_id < IMID_ReservedCount; } + void setName(QString name) { m_name = name; } + QString getName() const { return isReservedModelId() ? idToString(m_id) : m_name; } + void setUpdateMask(const int mask) { m_updateMask = mask; } + int getUpdateMask() const { return m_updateMask; } + + inline bool doUpdate(const int event) const { return m_updateMask & event; } + + AbstractItemModel * getItemModel(const int id) const; + + static void dumpItemModelContents(AbstractItemModel * itemModel); + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) = 0; + + protected: + const GeneralSettings * generalSettings; + const ModelData * modelData; + Firmware * firmware; + const Boards * board; + const Board::Type boardType; + + private: + int m_id = IMID_Unknown; + QString m_name = ""; + int m_updateMask = IMUE_None; + + static QString idToString(const int value); +}; + +class AbstractStaticItemModel: public AbstractItemModel +{ + Q_OBJECT + public: + explicit AbstractStaticItemModel(const GeneralSettings * const generalSettings = nullptr, const ModelData * const modelData = nullptr, + Firmware * firmware = nullptr, const Boards * const board = nullptr, + const Board::Type boardType = Board::BOARD_UNKNOWN) : + AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {} + virtual ~AbstractStaticItemModel() {}; + + inline void appendToItemList(QString text, int id, bool isAvailable = true, int type = 0, int flags = 0) + { itemList.append(new ListItem(text, id, isAvailable, type, flags)); } + + void loadItemList(); + + public slots: + virtual void update(const int event) override final {} + + protected: + struct ListItem + { + QString text; + int id; + bool isAvailable; + int type; + int flags; + + ListItem() {} + ListItem(QString p_text, int p_id, bool p_isAvailable, int p_type, int p_flags) : + text(p_text), id(p_id), isAvailable(p_isAvailable), type(p_type), flags(p_flags) {} + }; + + QVector itemList; +}; + +class AbstractDynamicItemModel: public AbstractItemModel +{ + Q_OBJECT + public: + explicit AbstractDynamicItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType) : + AbstractItemModel(generalSettings, modelData, firmware, board, boardType) {} + virtual ~AbstractDynamicItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) {} + + signals: + void aboutToBeUpdated(); + void updateComplete(); +}; + +class RawSourceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~RawSourceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const RawSource & src) const; + void addItems(const RawSourceType & type, const int group, const int count, const int start = 0); +}; + +class RawSwitchItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~RawSwitchItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const; + void addItems(const RawSwitchType & type, int count); +}; + +class CurveItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CurveItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class GVarReferenceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit GVarReferenceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~GVarReferenceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const AdjustmentReference & ar) const; + void addItems(int count); +}; + +class ThrottleSourceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit ThrottleSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~ThrottleSourceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class CustomFuncActionItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit CustomFuncActionItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CustomFuncActionItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class CustomFuncResetParamItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit CustomFuncResetParamItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CustomFuncResetParamItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class TelemetrySourceItemModel: public AbstractDynamicItemModel +{ + Q_OBJECT + public: + explicit TelemetrySourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~TelemetrySourceItemModel() {}; + + public slots: + virtual void update(const int event = IMUE_SystemRefresh) override; + + protected: + virtual void setDynamicItemData(QStandardItem * item, const int value) const; +}; + +class CurveRefTypeItemModel : public AbstractStaticItemModel +{ + Q_OBJECT + public: + explicit CurveRefTypeItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CurveRefTypeItemModel() {}; +}; + +class CurveRefFuncItemModel : public AbstractStaticItemModel +{ + Q_OBJECT + public: + explicit CurveRefFuncItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, + Firmware * firmware, const Boards * const board, const Board::Type boardType); + virtual ~CurveRefFuncItemModel() {}; +}; + +class PrecisionItemModel : public AbstractStaticItemModel +{ + Q_OBJECT + public: + explicit PrecisionItemModel(const int minDecimals, const int maxDecimals, const QString suffix = "", const bool placeholders = false); + virtual ~PrecisionItemModel() {}; +}; + +// +// CompoundItemModelFactory +// + +class CompoundItemModelFactory +{ + public: + CompoundItemModelFactory(const GeneralSettings * const generalSettings, const ModelData * const modelData); + virtual ~CompoundItemModelFactory(); + + void addItemModel(const int id); + int registerItemModel(AbstractItemModel * itemModel); + void unregisterItemModels(); + void unregisterItemModel(const int id); + bool isItemModelRegistered(const int id) const; + AbstractItemModel * getItemModel(const int id) const; + void update(const int event = AbstractItemModel::IMUE_SystemRefresh); + void dumpAllItemModelContents() const; + + protected: + const GeneralSettings * generalSettings; + const ModelData * modelData; + Firmware * firmware; + Boards * board; + Board::Type boardType; + QVector registeredItemModels; + + private: + void setSourceId(AbstractItemModel * itemModel); +}; + +#endif // COMPOUNDITEMMODELS_H diff --git a/companion/src/datamodels/filtereditemmodels.cpp b/companion/src/datamodels/filtereditemmodels.cpp new file mode 100644 index 000000000..4f4e27262 --- /dev/null +++ b/companion/src/datamodels/filtereditemmodels.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "filtereditemmodels.h" + +FilteredItemModel::FilteredItemModel(AbstractItemModel * sourceModel, int flags) : + QSortFilterProxyModel(nullptr), + filterFlags(0), + m_id(0), + m_name("") +{ + setFilterRole(AbstractItemModel::IMDR_Available); + setFilterKeyColumn(0); + setFilterFlags(flags); + setDynamicSortFilter(true); + setSourceModel(sourceModel); + + AbstractDynamicItemModel * itemModel = qobject_cast(sourceModel); + if (itemModel) { + connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &FilteredItemModel::onAboutToBeUpdated); + connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &FilteredItemModel::onUpdateComplete); + } +} + +void FilteredItemModel::setFilterFlags(int flags) +{ + if (filterFlags != flags) { + filterFlags = flags; + invalidateFilter(); + } +} + +bool FilteredItemModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const +{ + const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent); + if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool()) + return false; + + if (!filterFlags) + return true; + + bool ok; + const int flags = sourceModel()->data(srcIdx, AbstractItemModel::IMDR_Flags).toInt(&ok); + return (ok && (!flags || (filterFlags & flags))); +} + +void FilteredItemModel::update() const +{ + AbstractDynamicItemModel * itemModel = qobject_cast(sourceModel()); + if (itemModel) + itemModel->update(); +} + +void FilteredItemModel::onAboutToBeUpdated() +{ + emit aboutToBeUpdated(); +} + +void FilteredItemModel::onUpdateComplete() +{ + emit updateComplete(); +} + +// static +void FilteredItemModel::dumpItemModelContents(FilteredItemModel * itemModel) +{ + if (itemModel) { + qDebug() << "id:" << itemModel->getId() << "name:" << itemModel->getName(); + + for (int i = 0; i < itemModel->rowCount(); ++i) { + qDebug() << "row:" << i + << "text:" << itemModel->data(itemModel->index(i, 0), Qt::DisplayRole).toString() + << "id:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Id).toInt() + << "avail:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Available).toBool() + << "flags:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Flags).toInt() + << "type:" << itemModel->data(itemModel->index(i, 0), AbstractItemModel::IMDR_Type).toInt(); + } + } + else + qDebug() << "Error: model not of class FilteredItemModel"; +} + +// +// FilteredItemModelFactory +// + +FilteredItemModelFactory::FilteredItemModelFactory() +{ +} + +FilteredItemModelFactory::~FilteredItemModelFactory() +{ + unregisterItemModels(); +} + +int FilteredItemModelFactory::registerItemModel(FilteredItemModel * itemModel, const QString name, const int id) +{ + if (itemModel) { + if (isItemModelRegistered(name)) { + qDebug() << "Error: item model already registered with name:" << name; + return 0; + } + else if (id > -1 && isItemModelRegistered(id)) { + qDebug() << "Error: item model already registered with id:" << id; + return 0; + } + else { + int fid = id; + if (fid < 0) { + fid = registeredItemModels.count() + 1; + AbstractItemModel * mdl = qobject_cast(itemModel->sourceModel()); + if (mdl) { + fid += mdl->getId() * 128; + } + } + itemModel->setId(fid); + itemModel->setName(name); + registeredItemModels.append(itemModel); + return fid; + } + } + + qDebug() << "Error: invalid filtered item model pointer"; + return 0; +} + +void FilteredItemModelFactory::unregisterItemModels() +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + delete itemModel; + } +} + +void FilteredItemModelFactory::unregisterItemModel(const int id) +{ + FilteredItemModel * itemModel = getItemModel(id); + if (itemModel) + delete itemModel; +} + +bool FilteredItemModelFactory::isItemModelRegistered(const int id) const +{ + return getItemModel(id); +} + +bool FilteredItemModelFactory::isItemModelRegistered(const QString name) const +{ + return getItemModel(name); +} + +FilteredItemModel * FilteredItemModelFactory::getItemModel(const int id) const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + if (itemModel->getId() == id) + return itemModel; + } + + return nullptr; +} + +FilteredItemModel * FilteredItemModelFactory::getItemModel(const QString name) const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + if (itemModel->getName() == name) + return itemModel; + } + + return nullptr; +} + +void FilteredItemModelFactory::update() +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + itemModel->update(); + } +} + +void FilteredItemModelFactory::dumpItemModelContents(const int id) const +{ + FilteredItemModel::dumpItemModelContents(getItemModel(id)); +} + +void FilteredItemModelFactory::dumpItemModelContents(const QString name) const +{ + FilteredItemModel::dumpItemModelContents(getItemModel(name)); +} + +void FilteredItemModelFactory::dumpAllItemModelContents() const +{ + foreach (FilteredItemModel * itemModel, registeredItemModels) { + FilteredItemModel::dumpItemModelContents(itemModel); + } +} + +// +// CurveRefFilteredFactory +// + +CurveRefFilteredFactory::CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags, const int gvarRefFlags) +{ + if (!sharedItemModels) { + qDebug() << "Error: invalid compound item model factory pointer"; + return; + } + + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve), curveFlags), + fidToString(CRFIM_CURVE), CRFIM_CURVE); + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_GVarRef), gvarRefFlags), + fidToString(CRFIM_GVARREF), CRFIM_GVARREF); + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefType)), + fidToString(CRFIM_TYPE), CRFIM_TYPE); + registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_CurveRefFunc)), + fidToString(CRFIM_FUNC), CRFIM_FUNC); +} + +CurveRefFilteredFactory::~CurveRefFilteredFactory() +{ +} + +// static +QString CurveRefFilteredFactory::fidToString(const int value) +{ + switch(value) { + case CRFIM_CURVE: + return "Curves"; + case CRFIM_GVARREF: + return "Global Variables"; + case CRFIM_TYPE: + return "Types"; + case CRFIM_FUNC: + return "Functions"; + default: + return CPN_STR_UNKNOWN_ITEM; + } +} diff --git a/companion/src/datamodels/filtereditemmodels.h b/companion/src/datamodels/filtereditemmodels.h new file mode 100644 index 000000000..24668704d --- /dev/null +++ b/companion/src/datamodels/filtereditemmodels.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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. + */ + +#ifndef FILTEREDITEMMODELS_H +#define FILTEREDITEMMODELS_H + +#include "compounditemmodels.h" + +#include +#include +#include + +class FilteredItemModel: public QSortFilterProxyModel +{ + Q_OBJECT + public: + enum DataFilters { + AllFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None | AbstractItemModel::IMDG_Positive, + AllExcludeNoneFilter = AllFilter &~ AbstractItemModel::IMDG_None, + NegativeFilter = AbstractItemModel::IMDG_Negative | AbstractItemModel::IMDG_None, + NegativeExcludeNoneFilter = AbstractItemModel::IMDG_Negative, + PositiveFilter = AbstractItemModel::IMDG_Positive | AbstractItemModel::IMDG_None, + PositiveExcludeNoneFilter = AbstractItemModel::IMDG_Positive + }; + Q_ENUM(DataFilters) + + explicit FilteredItemModel(AbstractItemModel * sourceModel, int flags); + explicit FilteredItemModel(AbstractItemModel * sourceModel) : + FilteredItemModel(sourceModel, 0) {} + virtual ~FilteredItemModel() {}; + + void setId(int id) { m_id = id; } + int getId() const { return m_id; }; + void setName(QString name) { m_name = name; } + QString getName() const { return m_name; } + + static void dumpItemModelContents(FilteredItemModel * itemModel); + + public slots: + void setFilterFlags(int flags); + void update() const; + void onAboutToBeUpdated(); + void onUpdateComplete(); + + signals: + void aboutToBeUpdated(); + void updateComplete(); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; + + int filterFlags; + + private: + int m_id = 0; + QString m_name = ""; +}; + +class FilteredItemModelFactory +{ + public: + explicit FilteredItemModelFactory(); + virtual ~FilteredItemModelFactory(); + + int registerItemModel(FilteredItemModel * itemModel, const QString name, const int id = -1); + void unregisterItemModels(); + void unregisterItemModel(const int id); + bool isItemModelRegistered(const int id) const; + bool isItemModelRegistered(const QString name) const; + FilteredItemModel * getItemModel(const int id) const; + FilteredItemModel * getItemModel(const QString name) const; + void update(); + + void dumpItemModelContents(const int id) const; + void dumpItemModelContents(const QString name) const; + void dumpAllItemModelContents() const; + + protected: + QVector registeredItemModels; +}; + +class CurveRefFilteredFactory : public FilteredItemModelFactory +{ + public: + enum FilteredItemModelId { + CRFIM_CURVE, + CRFIM_GVARREF, + CRFIM_TYPE, + CRFIM_FUNC + }; + + explicit CurveRefFilteredFactory(CompoundItemModelFactory * sharedItemModels, const int curveFlags = 0, const int gvarRefFlags = 0); + virtual ~CurveRefFilteredFactory(); + + static QString fidToString(const int value); +}; + +#endif // FILTEREDITEMMODELS_H diff --git a/companion/src/datamodels/rawitemdatamodels.cpp b/companion/src/datamodels/rawitemdatamodels.cpp deleted file mode 100644 index d7c1b6682..000000000 --- a/companion/src/datamodels/rawitemdatamodels.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * 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 "rawitemdatamodels.h" -#include "generalsettings.h" -#include "eeprominterface.h" -#include "modeldata.h" - -RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - const Boards board = Boards(getCurrentBoard()); - Firmware * fw = getCurrentFirmware(); - - addItems(SOURCE_TYPE_NONE, RawSource::NoneGroup, 1); - for (int i = 0; i < fw->getCapability(LuaScripts); i++) - addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, fw->getCapability(LuaOutputsPerScript), i * 16); - addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, fw->getCapability(VirtualInputs)); - addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board.getCapability(Board::MaxAnalogs)); - addItems(SOURCE_TYPE_ROTARY_ENCODER, RawSource::SourcesGroup, fw->getCapability(RotaryEncoders)); - addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board.getCapability(Board::NumTrims)); - addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1); - addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board.getCapability(Board::Switches)); - addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, fw->getCapability(LogicalSwitches)); - addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC); - addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, fw->getCapability(TrainerInputs)); - addItems(SOURCE_TYPE_CH, RawSource::SourcesGroup, fw->getCapability(Outputs)); - addItems(SOURCE_TYPE_SPECIAL, RawSource::TelemGroup, 5); - addItems(SOURCE_TYPE_TELEMETRY, RawSource::TelemGroup, fw->getCapability(Sensors) * 3); - addItems(SOURCE_TYPE_GVAR, RawSource::GVarsGroup, fw->getCapability(Gvars)); -} - -void RawSourceItemModel::setDynamicItemData(QStandardItem * item, const RawSource & src) const -{ - Board::Type board = getCurrentBoard(); - item->setText(src.toString(modelData, generalSettings, board)); - item->setData(src.isAvailable(modelData, generalSettings, board), IsAvailableRole); -} - -void RawSourceItemModel::addItems(const RawSourceType & type, const int group, const int count, const int start) -{ - for (int i = start; i < start + count; i++) { - const RawSource src = RawSource(type, i); - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(src.toValue(), ItemIdRole); - modelItem->setData(type, ItemTypeRole); - modelItem->setData(group, ItemFlagsRole); - setDynamicItemData(modelItem, src); - appendRow(modelItem); - } -} - -void RawSourceItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), RawSource(item(i)->data(ItemIdRole).toInt())); - - emit dataUpdateComplete(); -} - - -// -// RawSwitchItemModel -// - -RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - Boards board = Boards(getCurrentBoard()); - Firmware * fw = getCurrentFirmware(); - - // Descending switch direction: NOT (!) switches - addItems(SWITCH_TYPE_ACT, -1); - addItems(SWITCH_TYPE_SENSOR, -fw->getCapability(Sensors)); - addItems(SWITCH_TYPE_TELEMETRY, -1); - addItems(SWITCH_TYPE_FLIGHT_MODE, -fw->getCapability(FlightModes)); - addItems(SWITCH_TYPE_VIRTUAL, -fw->getCapability(LogicalSwitches)); - addItems(SWITCH_TYPE_ROTARY_ENCODER, -fw->getCapability(RotaryEncoders)); - addItems(SWITCH_TYPE_TRIM, -board.getCapability(Board::NumTrimSwitches)); - addItems(SWITCH_TYPE_MULTIPOS_POT, -(board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions))); - addItems(SWITCH_TYPE_SWITCH, -board.getCapability(Board::SwitchPositions)); - - // Ascending switch direction (including zero) - addItems(SWITCH_TYPE_TIMER_MODE, 5); - addItems(SWITCH_TYPE_NONE, 1); - addItems(SWITCH_TYPE_SWITCH, board.getCapability(Board::SwitchPositions)); - addItems(SWITCH_TYPE_MULTIPOS_POT, board.getCapability(Board::MultiposPots) * board.getCapability(Board::MultiposPotsPositions)); - addItems(SWITCH_TYPE_TRIM, board.getCapability(Board::NumTrimSwitches)); - addItems(SWITCH_TYPE_ROTARY_ENCODER, fw->getCapability(RotaryEncoders)); - addItems(SWITCH_TYPE_VIRTUAL, fw->getCapability(LogicalSwitches)); - addItems(SWITCH_TYPE_FLIGHT_MODE, fw->getCapability(FlightModes)); - addItems(SWITCH_TYPE_TELEMETRY, 1); - addItems(SWITCH_TYPE_SENSOR, fw->getCapability(Sensors)); - addItems(SWITCH_TYPE_ON, 1); - addItems(SWITCH_TYPE_ONE, 1); - addItems(SWITCH_TYPE_ACT, 1); -} - -void RawSwitchItemModel::setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const -{ - const Board::Type board = getCurrentBoard(); - item->setText(rsw.toString(board, generalSettings, modelData)); - item->setData(rsw.isAvailable(modelData, generalSettings, board), IsAvailableRole); -} - -void RawSwitchItemModel::addItems(const RawSwitchType & type, int count) -{ - // Most RawSwitch() indices are one-based (vs. typical zero); these are exceptions to the rule: - const static QVector rawSwitchIndexBaseZeroTypes = QVector() << SWITCH_TYPE_NONE << SWITCH_TYPE_ON << SWITCH_TYPE_OFF << SWITCH_TYPE_TIMER_MODE; - // handle exceptions in RawSwitch() index values - const short rawIdxAdj = rawSwitchIndexBaseZeroTypes.contains(type) ? -1 : 0; - - // determine cotext flags - int context = RawSwitch::AllSwitchContexts; - switch (type) { - case SWITCH_TYPE_FLIGHT_MODE: - context &= ~RawSwitch::MixesContext; - // fallthrough - case SWITCH_TYPE_VIRTUAL: - case SWITCH_TYPE_SENSOR: - context &= ~RawSwitch::GlobalFunctionsContext; - break; - - case SWITCH_TYPE_TIMER_MODE: - context = RawSwitch::TimersContext; - break; - - case SWITCH_TYPE_NONE: - context &= ~RawSwitch::TimersContext; - break; - - case SWITCH_TYPE_ON: - case SWITCH_TYPE_ONE: - context = RawSwitch::SpecialFunctionsContext | RawSwitch::GlobalFunctionsContext; - break; - - default: - break; - } - - int i = (count < 0 ? count : 1); - count = (i < 0 ? 0 : count + i); - for ( ; i < count; ++i) { - RawSwitch rs(type, i + rawIdxAdj); - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(rs.toValue(), ItemIdRole); - modelItem->setData(type, ItemTypeRole); - modelItem->setData(context, ItemFlagsRole); - setDynamicItemData(modelItem, rs); - appendRow(modelItem); - } -} - -void RawSwitchItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), RawSwitch(item(i)->data(ItemIdRole).toInt())); - - emit dataUpdateComplete(); -} - -// -// CurveItemModel -// - -CurveItemModel::CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - AbstractRawItemDataModel(generalSettings, modelData, parent) -{ - const int count = getCurrentFirmware()->getCapability(NumCurves); - - for (int i = -count ; i <= count; ++i) { - QStandardItem * modelItem = new QStandardItem(); - modelItem->setData(i, ItemIdRole); - int flags; - if (i < 0) - flags = DataGroups::NegativeGroup; - else if (i > 0) - flags = DataGroups::PositiveGroup; - else - flags = DataGroups::NoneGroup; - modelItem->setData(flags, ItemFlagsRole); - setDynamicItemData(modelItem, i); - appendRow(modelItem); - } -} - -void CurveItemModel::setDynamicItemData(QStandardItem * item, int index) const -{ - item->setText(CurveReference(CurveReference::CURVE_REF_CUSTOM, index).toString(modelData, false)); - item->setData(true, IsAvailableRole); -} - -void CurveItemModel::update() -{ - emit dataAboutToBeUpdated(); - - for (int i = 0; i < rowCount(); ++i) - setDynamicItemData(item(i), item(i)->data(ItemIdRole).toInt()); - - emit dataUpdateComplete(); -} - -// -// CommonItemModels -// - -CommonItemModels::CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent) : - QObject(parent) -{ - m_rawSourceItemModel = new RawSourceItemModel(generalSettings, modelData, parent); - m_rawSwitchItemModel = new RawSwitchItemModel(generalSettings, modelData, parent); - m_curveItemModel = new CurveItemModel(generalSettings, modelData, parent); -} - -CommonItemModels::~CommonItemModels() -{ -} - -void CommonItemModels::update(const RadioModelObjects radioModelObjects) -{ - switch (radioModelObjects) { - case RMO_CHANNELS: - case RMO_INPUTS: - case RMO_TELEMETRY_SENSORS: - case RMO_TIMERS: - m_rawSourceItemModel->update(); - break; - case RMO_FLIGHT_MODES: - case RMO_GLOBAL_VARIABLES: - case RMO_LOGICAL_SWITCHES: - m_rawSourceItemModel->update(); - m_rawSwitchItemModel->update(); - break; - case RMO_CURVES: - m_curveItemModel->update(); - break; - case RMO_SCRIPTS: - // no need to refresh - break; - default: - qDebug() << "Unknown RadioModelObject:" << radioModelObjects; - } -} diff --git a/companion/src/datamodels/rawitemdatamodels.h b/companion/src/datamodels/rawitemdatamodels.h deleted file mode 100644 index 48cb55fd2..000000000 --- a/companion/src/datamodels/rawitemdatamodels.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * 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. - */ - -#ifndef RAWITEMDATAMODELS_H -#define RAWITEMDATAMODELS_H - -#include "rawsource.h" -#include "rawswitch.h" - -#include - -class GeneralSettings; -class ModelData; - -class AbstractRawItemDataModel: public QStandardItemModel -{ - Q_OBJECT - public: - enum DataRoles { ItemIdRole = Qt::UserRole, ItemTypeRole, ItemFlagsRole, IsAvailableRole }; - Q_ENUM(DataRoles) - - enum DataGroups { - NoneGroup = 0x01, - NegativeGroup = 0x02, - PositiveGroup = 0x04 - }; - Q_ENUM(DataGroups) - - explicit AbstractRawItemDataModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr) : - QStandardItemModel(parent), - generalSettings(generalSettings), - modelData(modelData) - {} - - public slots: - virtual void update() = 0; - - signals: - void dataAboutToBeUpdated(); - void dataUpdateComplete(); - - protected: - const GeneralSettings * generalSettings; - const ModelData * modelData; -}; - - -class RawSourceItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit RawSourceItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const RawSource & src) const; - void addItems(const RawSourceType & type, const int group, const int count, const int start = 0); -}; - - -class RawSwitchItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit RawSwitchItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, const RawSwitch & rsw) const; - void addItems(const RawSwitchType & type, int count); -}; - - -class CurveItemModel: public AbstractRawItemDataModel -{ - Q_OBJECT - public: - explicit CurveItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - - public slots: - void update() override; - - protected: - void setDynamicItemData(QStandardItem * item, int index) const; -}; - - -class CommonItemModels: public QObject -{ - Q_OBJECT - public: - enum RadioModelObjects { - RMO_CHANNELS, - RMO_CURVES, - RMO_FLIGHT_MODES, - RMO_GLOBAL_VARIABLES, - RMO_INPUTS, - RMO_LOGICAL_SWITCHES, - RMO_SCRIPTS, - RMO_TELEMETRY_SENSORS, - RMO_TIMERS - }; - Q_ENUM(RadioModelObjects) - - explicit CommonItemModels(const GeneralSettings * const generalSettings, const ModelData * const modelData, QObject * parent = nullptr); - ~CommonItemModels(); - - void update(const RadioModelObjects radioModelObjects); - RawSourceItemModel * rawSourceItemModel() const { return m_rawSourceItemModel; } - RawSwitchItemModel * rawSwitchItemModel() const { return m_rawSwitchItemModel; } - CurveItemModel * curveItemModel() const { return m_curveItemModel; } - - private: - RawSourceItemModel *m_rawSourceItemModel; - RawSwitchItemModel *m_rawSwitchItemModel; - CurveItemModel *m_curveItemModel; -}; - -#endif // RAWITEMDATAMODELS_H diff --git a/companion/src/datamodels/rawitemfilteredmodel.cpp b/companion/src/datamodels/rawitemfilteredmodel.cpp deleted file mode 100644 index abe9ca08e..000000000 --- a/companion/src/datamodels/rawitemfilteredmodel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * 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 "rawitemfilteredmodel.h" - -RawItemFilteredModel::RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent) : - QSortFilterProxyModel(parent), - filterFlags(0) -{ - setFilterRole(AbstractRawItemDataModel::IsAvailableRole); - setFilterKeyColumn(0); - setFilterFlags(flags); - setDynamicSortFilter(true); - setSourceModel(sourceModel); - - AbstractRawItemDataModel * itemModel = qobject_cast(sourceModel); - if (itemModel) { - connect(itemModel, &AbstractRawItemDataModel::dataAboutToBeUpdated, this, &RawItemFilteredModel::onDataAboutToBeUpdated); - connect(itemModel, &AbstractRawItemDataModel::dataUpdateComplete, this, &RawItemFilteredModel::onDataUpdateComplete); - } -} - -void RawItemFilteredModel::setFilterFlags(int flags) -{ - if (filterFlags != flags) { - filterFlags = flags; - invalidateFilter(); - } -} - -bool RawItemFilteredModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const -{ - const QModelIndex & srcIdx = sourceModel()->index(sourceRow, 0, sourceParent); - if (!srcIdx.isValid() || !sourceModel()->data(srcIdx, filterRole()).toBool()) - return false; - - if (!filterFlags) - return true; - - bool ok; - const int flags = sourceModel()->data(srcIdx, AbstractRawItemDataModel::ItemFlagsRole).toInt(&ok); - return (ok && (!flags || (filterFlags & flags))); -} - -void RawItemFilteredModel::update() const -{ - AbstractRawItemDataModel * itemModel = qobject_cast(sourceModel()); - if (itemModel) - itemModel->update(); -} - -void RawItemFilteredModel::onDataAboutToBeUpdated() -{ - emit dataAboutToBeUpdated(); -} - -void RawItemFilteredModel::onDataUpdateComplete() -{ - emit dataUpdateComplete(); -} diff --git a/companion/src/datamodels/rawitemfilteredmodel.h b/companion/src/datamodels/rawitemfilteredmodel.h deleted file mode 100644 index 3274460f7..000000000 --- a/companion/src/datamodels/rawitemfilteredmodel.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * 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. - */ - -#ifndef RAWITEMFILTEREDMODEL_H -#define RAWITEMFILTEREDMODEL_H - -#include "rawitemdatamodels.h" - -#include - -class GeneralSettings; -class ModelData; - -class RawItemFilteredModel: public QSortFilterProxyModel -{ - Q_OBJECT - public: - enum DataFilters { - AllFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup | AbstractRawItemDataModel::PositiveGroup, - AllExcludeNoneFilter = AllFilter &~ AbstractRawItemDataModel::NoneGroup, - NegativeFilter = AbstractRawItemDataModel::NegativeGroup | AbstractRawItemDataModel::NoneGroup, - NegativeExcludeNoneFilter = AbstractRawItemDataModel::NegativeGroup, - PositiveFilter = AbstractRawItemDataModel::PositiveGroup | AbstractRawItemDataModel::NoneGroup, - PositiveExcludeNoneFilter = AbstractRawItemDataModel::PositiveGroup - }; - Q_ENUM(DataFilters) - - explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, int flags, QObject * parent = nullptr); - explicit RawItemFilteredModel(QAbstractItemModel * sourceModel, QObject * parent = nullptr) : RawItemFilteredModel(sourceModel, 0, parent) {} - - public slots: - void setFilterFlags(int flags); - void update() const; - void onDataAboutToBeUpdated(); - void onDataUpdateComplete(); - - signals: - void dataAboutToBeUpdated(); - void dataUpdateComplete(); - - protected: - bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; - - int filterFlags; -}; -#endif // RAWITEMFILTEREDMODEL_H diff --git a/companion/src/firmwares/adjustmentreference.cpp b/companion/src/firmwares/adjustmentreference.cpp index 7181e15dd..ae487effa 100644 --- a/companion/src/firmwares/adjustmentreference.cpp +++ b/companion/src/firmwares/adjustmentreference.cpp @@ -19,7 +19,7 @@ */ #include "adjustmentreference.h" -#include "radiodata.h" // for ModelData +#include "modeldata.h" AdjustmentReference::AdjustmentReference(int value) { @@ -76,3 +76,8 @@ QString AdjustmentReference::toString(const ModelData * model, const bool sign) } return ret; } + +const bool AdjustmentReference::isAvailable() const +{ + return true; +} diff --git a/companion/src/firmwares/adjustmentreference.h b/companion/src/firmwares/adjustmentreference.h index 2a7b7e141..9377cd5e8 100644 --- a/companion/src/firmwares/adjustmentreference.h +++ b/companion/src/firmwares/adjustmentreference.h @@ -45,6 +45,7 @@ class AdjustmentReference { bool isSet() const { return type != ADJUST_REF_VALUE || value != 0; } bool isValid(const int value) const; QString toString(const ModelData * model = nullptr, const bool sign = false) const; + const bool isAvailable() const; inline const int toValue() const { diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp index 23179fd60..779712b65 100644 --- a/companion/src/firmwares/boards.cpp +++ b/companion/src/firmwares/boards.cpp @@ -89,6 +89,8 @@ uint32_t Boards::getFourCC(Type board) return 0x3878746F; case BOARD_RADIOMASTER_TX12: return 0x4178746F; + case BOARD_RADIOMASTER_T8: + return 0x4378746F; case BOARD_UNKNOWN: break; } @@ -117,6 +119,7 @@ int Boards::getEEpromSize(Board::Type board) case BOARD_JUMPER_T12: case BOARD_JUMPER_TLITE: case BOARD_RADIOMASTER_TX12: + case BOARD_RADIOMASTER_T8: return EESIZE_TARANIS; case BOARD_UNKNOWN: return EESIZE_MAX; @@ -153,6 +156,7 @@ int Boards::getFlashSize(Type board) case BOARD_JUMPER_T12: case BOARD_JUMPER_TLITE: case BOARD_RADIOMASTER_TX12: + case BOARD_RADIOMASTER_T8: return FSIZE_TARANIS; case BOARD_HORUS_X12S: case BOARD_X10: @@ -195,7 +199,20 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index) if (index < DIM(switches)) return switches[index]; } - else if (IS_TARANIS_X7(board)) { + else if (board == BOARD_TARANIS_X7_ACCESS) { + const Board::SwitchInfo switches[] = { + {SWITCH_3POS, "SA"}, + {SWITCH_3POS, "SB"}, + {SWITCH_3POS, "SC"}, + {SWITCH_3POS, "SD"}, + {SWITCH_2POS, "SF"}, + {SWITCH_TOGGLE, "SH"}, + {SWITCH_2POS, "SI"} + }; + if (index < DIM(switches)) + return switches[index]; + } + else if (board == BOARD_TARANIS_X7) { const Board::SwitchInfo switches[] = { {SWITCH_3POS, "SA"}, {SWITCH_3POS, "SB"}, @@ -223,6 +240,16 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index) if (index < DIM(switches)) return switches[index]; } + else if (IS_RADIOMASTER_T8(board)) { + const Board::SwitchInfo switches[] = { + {SWITCH_TOGGLE, "SA"}, + {SWITCH_3POS, "SB"}, + {SWITCH_3POS, "SC"}, + {SWITCH_TOGGLE, "SD"} + }; + if (index < DIM(switches)) + return switches[index]; + } else if (IS_JUMPER_T12(board)) { const Board::SwitchInfo switches[] = { {SWITCH_3POS, "SA"}, @@ -360,7 +387,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability) return 5; else if (board == Board::BOARD_TARANIS_X9LITES) return 7; - else if (IS_TARANIS_X7(board)) + else if (board == BOARD_TARANIS_X7_ACCESS) + return 7; + else if (board == BOARD_TARANIS_X7) return 8; else if (IS_FAMILY_T12(board)) return 8; @@ -573,6 +602,8 @@ QString Boards::getBoardName(Board::Type board) return "Radiomaster TX16S"; case BOARD_RADIOMASTER_TX12: return "Radiomaster TX12"; + case BOARD_RADIOMASTER_T8: + return "Radiomaster T8"; default: return tr("Unknown"); } diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h index a1ef1c629..4d2f03b9d 100644 --- a/companion/src/firmwares/boards.h +++ b/companion/src/firmwares/boards.h @@ -53,9 +53,11 @@ namespace Board { BOARD_RADIOMASTER_TX16S, BOARD_JUMPER_T18, BOARD_RADIOMASTER_TX12, + BOARD_RADIOMASTER_T8, BOARD_JUMPER_TLITE }; + constexpr int BOARD_TYPE_MAX = BOARD_JUMPER_TLITE; enum PotType @@ -232,6 +234,11 @@ inline bool IS_RADIOMASTER_TX12(Board::Type board) return board == Board::BOARD_RADIOMASTER_TX12; } +inline bool IS_RADIOMASTER_T8(Board::Type board) +{ + return board == Board::BOARD_RADIOMASTER_T8; +} + inline bool IS_FAMILY_T16(Board::Type board) { return board == Board::BOARD_JUMPER_T16 || board == Board::BOARD_RADIOMASTER_TX16S || board == Board::BOARD_JUMPER_T18; @@ -239,7 +246,7 @@ inline bool IS_FAMILY_T16(Board::Type board) inline bool IS_FAMILY_T12(Board::Type board) { - return board == Board::BOARD_JUMPER_T12 || board == Board::BOARD_RADIOMASTER_TX12 || board == Board::BOARD_JUMPER_TLITE;; + return board == Board::BOARD_JUMPER_T12 || board == Board::BOARD_RADIOMASTER_TX12 || board == Board::BOARD_RADIOMASTER_T8 || board == Board::BOARD_JUMPER_TLITE; } inline bool IS_TARANIS_XLITE(Board::Type board) diff --git a/companion/src/firmwares/curvereference.cpp b/companion/src/firmwares/curvereference.cpp index 449dc0266..926c2d2ae 100644 --- a/companion/src/firmwares/curvereference.cpp +++ b/companion/src/firmwares/curvereference.cpp @@ -22,7 +22,7 @@ #include "adjustmentreference.h" #include "helpers.h" #include "modeldata.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" const QString CurveReference::toString(const ModelData * model, bool verbose) const { @@ -63,6 +63,11 @@ const bool CurveReference::isValueNumber() const return (type == CURVE_REF_DIFF || type == CURVE_REF_EXPO) && AdjustmentReference(value).type == AdjustmentReference::ADJUST_REF_VALUE; } +const bool CurveReference::isAvailable() const +{ + return true; +} + // static int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar) { @@ -77,7 +82,7 @@ int CurveReference::getDefaultValue(const CurveRefType type, const bool isGVar) // static QString CurveReference::typeToString(const CurveRefType type) { - const QStringList strl = { "Diff", "Expo" , "Func", "Curve" }; + const QStringList strl = { tr("Diff"), tr("Expo") , tr("Func"), tr("Curve") }; int idx = (int)type; if (idx < 0 || idx >= strl.count()) @@ -86,8 +91,6 @@ QString CurveReference::typeToString(const CurveRefType type) return strl.at(idx); } -constexpr int MAX_CURVE_REF_FUNC { 6 }; - // static QString CurveReference::functionToString(const int value) { @@ -100,76 +103,65 @@ QString CurveReference::functionToString(const int value) return strl.at(idx); } +// static +bool CurveReference::isTypeAvailable(const CurveRefType type) +{ + bool ret = false; + Firmware * fw = getCurrentFirmware(); + + switch(type) { + case CURVE_REF_DIFF: + if (fw->getCapability(HasInputDiff)) + ret = true; + break; + case CURVE_REF_EXPO: + if (fw->getCapability(HasMixerExpo)) + ret = true; + break; + case CURVE_REF_FUNC: + case CURVE_REF_CUSTOM: + ret = true; + break; + } + + return ret; +} + +// static +bool CurveReference::isFunctionAvailable(const int value) +{ + return true; +} + +// static +int CurveReference::functionCount() +{ + return 6; +} + + /* * CurveReferenceUIManager */ -constexpr int CURVE_REF_UI_HIDE_DIFF { 0x01 }; -constexpr int CURVE_REF_UI_HIDE_EXPO { 0x02 }; -constexpr int CURVE_REF_UI_HIDE_NEGATIVE_CURVES { 0x04 }; - -// static -bool CurveReferenceUIManager::firsttime { true }; -int CurveReferenceUIManager::flags { 0 }; -bool CurveReferenceUIManager::hasCapabilityGvars { false }; -int CurveReferenceUIManager::numCurves { 0 }; -RawItemFilteredModel * CurveReferenceUIManager::curveItemModel { nullptr }; -QStandardItemModel * CurveReferenceUIManager::tempModel { nullptr }; - -CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveValueCB, CurveReference & curve, const ModelData & model, - RawItemFilteredModel * curveItemModel, QObject * parent) : - QObject(parent), - curveTypeCB(nullptr), - curveGVarCB(nullptr), - curveValueSB(nullptr), - curveValueCB(curveValueCB), - curve(curve), - model(model), - lock(false) -{ - init(curveItemModel); -} - CurveReferenceUIManager::CurveReferenceUIManager(QComboBox * curveTypeCB, QCheckBox * curveGVarCB, QSpinBox * curveValueSB, - QComboBox * curveValueCB, CurveReference & curve, const ModelData & model, - RawItemFilteredModel * curveItemModel, QObject * parent) : + QComboBox * curveValueCB, CurveReference & curveRef, const ModelData & model, + CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent) : QObject(parent), curveTypeCB(curveTypeCB), curveGVarCB(curveGVarCB), curveValueSB(curveValueSB), curveValueCB(curveValueCB), - curve(curve), + curveRef(curveRef), model(model), - lock(false) + lock(false), + filteredModelFactory(curveRefFilteredFactory) { - init(curveItemModel); -} - -CurveReferenceUIManager::~CurveReferenceUIManager() -{ - delete tempModel; -} - -void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel) -{ - tempModel = new QStandardItemModel(); - - if (firsttime) { - firsttime = false; - Firmware * fw = getCurrentFirmware(); - hasCapabilityGvars = fw->getCapability(Gvars); - numCurves = fw->getCapability(NumCurves); - curveItemModel = curveModel; - - if (!fw->getCapability(HasInputDiff)) - flags |= (CURVE_REF_UI_HIDE_DIFF | CURVE_REF_UI_HIDE_NEGATIVE_CURVES); - - if (!fw->getCapability(HasMixerExpo)) - flags |= CURVE_REF_UI_HIDE_EXPO; - } + hasCapabilityGvars = getCurrentFirmware()->getCapability(Gvars); if (curveTypeCB) { - populateTypeCB(curveTypeCB, curve); + curveTypeCB->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_TYPE)); + curveTypeCB->setCurrentIndex(curveTypeCB->findData((int)curveRef.type)); connect(curveTypeCB, SIGNAL(currentIndexChanged(int)), this, SLOT(typeChanged(int))); } @@ -182,13 +174,20 @@ void CurveReferenceUIManager::init(RawItemFilteredModel * curveModel) connect(curveValueSB, SIGNAL(editingFinished()), this, SLOT(valueSBChanged())); } - curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); - curveValueCB->setMaxVisibleItems(10); - connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged())); + if (curveValueCB) { + curveValueCB->setSizeAdjustPolicy(QComboBox::AdjustToContents); + curveValueCB->setMaxVisibleItems(10); + connect(curveValueCB, SIGNAL(currentIndexChanged(int)), this, SLOT(valueCBChanged())); + } update(); } +CurveReferenceUIManager::~CurveReferenceUIManager() +{ + delete filteredModelFactory; +} + #define CURVE_REF_UI_GVAR_SHOW (1<<0) #define CURVE_REF_UI_VALUE_SHOW (1<<1) #define CURVE_REF_UI_REF_SHOW (1<<2) @@ -198,12 +197,12 @@ void CurveReferenceUIManager::update() lock = true; int widgetsMask = 0; - if (curve.type == CurveReference::CURVE_REF_DIFF || curve.type == CurveReference::CURVE_REF_EXPO) { + if (curveRef.type == CurveReference::CURVE_REF_DIFF || curveRef.type == CurveReference::CURVE_REF_EXPO) { if (hasCapabilityGvars) widgetsMask |= CURVE_REF_UI_GVAR_SHOW; - if (curve.isValueNumber()) { + if (curveRef.isValueNumber()) { curveGVarCB->setChecked(false); - curveValueSB->setValue(curve.value); + curveValueSB->setValue(curveRef.value); widgetsMask |= CURVE_REF_UI_VALUE_SHOW; } else { @@ -216,7 +215,7 @@ void CurveReferenceUIManager::update() } if(curveTypeCB) { - curveTypeCB->setCurrentIndex(curveTypeCB->findData(curve.type)); + curveTypeCB->setCurrentIndex(curveTypeCB->findData(curveRef.type)); curveTypeCB->show(); } if(curveGVarCB) @@ -224,8 +223,8 @@ void CurveReferenceUIManager::update() if(curveValueSB) curveValueSB->setVisible(widgetsMask & CURVE_REF_UI_VALUE_SHOW); if(curveValueCB) { - if (curve.isValueReference()) - populateValueCB(curveValueCB, curve, &model); + if (curveRef.isValueReference()) + populateValueCB(curveValueCB); curveValueCB->setVisible(widgetsMask & CURVE_REF_UI_REF_SHOW); } @@ -235,7 +234,7 @@ void CurveReferenceUIManager::update() void CurveReferenceUIManager::gvarCBChanged(int state) { if (!lock) { - curve.value = CurveReference::getDefaultValue(curve.type, state); + curveRef.value = CurveReference::getDefaultValue(curveRef.type, state); update(); } } @@ -244,7 +243,7 @@ void CurveReferenceUIManager::typeChanged(int value) { if (!lock) { CurveReference::CurveRefType type = (CurveReference::CurveRefType)curveTypeCB->itemData(curveTypeCB->currentIndex()).toInt(); - curve = CurveReference(type, CurveReference::getDefaultValue(type)); + curveRef = CurveReference(type, CurveReference::getDefaultValue(type)); update(); } } @@ -252,7 +251,7 @@ void CurveReferenceUIManager::typeChanged(int value) void CurveReferenceUIManager::valueSBChanged() { if (!lock) { - curve.value = curveValueSB->value(); + curveRef.value = curveValueSB->value(); update(); } } @@ -260,47 +259,24 @@ void CurveReferenceUIManager::valueSBChanged() void CurveReferenceUIManager::valueCBChanged() { if (!lock) { - curve.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt(); + curveRef.value = curveValueCB->itemData(curveValueCB->currentIndex()).toInt(); update(); } } -// static -void CurveReferenceUIManager::populateTypeCB(QComboBox * cb, const CurveReference & curveRef) +void CurveReferenceUIManager::populateValueCB(QComboBox * cb) { if (cb) { - cb->clear(); - for (int i = 0; i <= CurveReference::MAX_CURVE_REF_TYPE; i++) { - if ((curveRef.type == CurveReference::CURVE_REF_DIFF && !(flags & CURVE_REF_UI_HIDE_DIFF)) || - (curveRef.type == CurveReference::CURVE_REF_EXPO && !(flags & CURVE_REF_UI_HIDE_EXPO)) || - (curveRef.type != CurveReference::CURVE_REF_DIFF && curveRef.type != CurveReference::CURVE_REF_EXPO)) - cb->addItem(CurveReference::typeToString((CurveReference::CurveRefType)i), i); - } - - cb->setCurrentIndex(cb->findData((int)curveRef.type)); - } -} - -// static -void CurveReferenceUIManager::populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model) -{ - if (cb) { - cb->setModel(tempModel); // do not want to clear/alter the shared curves model and set to nullptr is invalid - switch (curveRef.type) { case CurveReference::CURVE_REF_DIFF: case CurveReference::CURVE_REF_EXPO: - cb->clear(); - Helpers::populateGVCB(*cb, curveRef.value, *model); + cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_GVARREF)); break; case CurveReference::CURVE_REF_FUNC: - cb->clear(); - for (int i = 1; i <= MAX_CURVE_REF_FUNC; i++) { - cb->addItem(CurveReference::functionToString(i), i); - } + cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_FUNC)); break; case CurveReference::CURVE_REF_CUSTOM: - cb->setModel(curveItemModel); + cb->setModel(filteredModelFactory->getItemModel(CurveRefFilteredFactory::CRFIM_CURVE)); break; default: break; diff --git a/companion/src/firmwares/curvereference.h b/companion/src/firmwares/curvereference.h index 0a1c7a180..c4482c742 100644 --- a/companion/src/firmwares/curvereference.h +++ b/companion/src/firmwares/curvereference.h @@ -29,7 +29,7 @@ class ModelData; -class RawItemFilteredModel; +class CurveRefFilteredFactory; class CurveReference { @@ -63,6 +63,7 @@ class CurveReference { const bool isValueNumber() const; const bool isValueReference() const { return !isValueNumber(); } const QString toString(const ModelData * model = nullptr, bool verbose = true) const; + const bool isAvailable() const; CurveRefType type; int value; @@ -78,6 +79,9 @@ class CurveReference { static int getDefaultValue(const CurveRefType type, const bool isGVar = false); static QString typeToString(const CurveRefType type); static QString functionToString(const int value); + static bool isTypeAvailable(const CurveRefType type); + static bool isFunctionAvailable(const int value); + static int functionCount(); }; class CurveReferenceUIManager : public QObject { @@ -85,38 +89,34 @@ class CurveReferenceUIManager : public QObject { Q_OBJECT public: - CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model, - RawItemFilteredModel * curveItemModel, QObject * parent = nullptr); - CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB, - CurveReference & curve, const ModelData & model, RawItemFilteredModel * curveItemModel, QObject * parent = nullptr); + explicit CurveReferenceUIManager(QComboBox *curveTypeCB, QCheckBox *curveGVarCB, QSpinBox *curveValueSB, QComboBox *curveValueCB, + CurveReference & curve, const ModelData & model, CurveRefFilteredFactory * curveRefFilteredFactory, + QObject * parent = nullptr); + + explicit CurveReferenceUIManager(QComboBox *curveValueCB, CurveReference & curve, const ModelData & model, + CurveRefFilteredFactory * curveRefFilteredFactory, QObject * parent = nullptr) : + CurveReferenceUIManager(nullptr, nullptr, nullptr, curveValueCB, curve, model, curveRefFilteredFactory, parent) {} + virtual ~CurveReferenceUIManager(); - void init(RawItemFilteredModel * curveModel); - void update(); protected slots: void gvarCBChanged(int); void typeChanged(int); void valueSBChanged(); void valueCBChanged(); + void update(); - protected: + private: QComboBox *curveTypeCB; QCheckBox *curveGVarCB; QSpinBox *curveValueSB; QComboBox *curveValueCB; - CurveReference & curve; + CurveReference & curveRef; const ModelData & model; bool lock; - - static bool firsttime; - static int flags; - static bool hasCapabilityGvars; - static int numCurves; - static RawItemFilteredModel * curveItemModel; - static QStandardItemModel * tempModel; - - static void populateTypeCB(QComboBox * cb, const CurveReference & curveRef); - static void populateValueCB(QComboBox * cb, const CurveReference & curveRef, const ModelData * model = nullptr); + bool hasCapabilityGvars; + CurveRefFilteredFactory *filteredModelFactory; + void populateValueCB(QComboBox * cb); }; #endif // CURVEREFERENCE_H diff --git a/companion/src/firmwares/customfunctiondata.cpp b/companion/src/firmwares/customfunctiondata.cpp index d6918e27c..d4942c60c 100644 --- a/companion/src/firmwares/customfunctiondata.cpp +++ b/companion/src/firmwares/customfunctiondata.cpp @@ -38,12 +38,12 @@ bool CustomFunctionData::isEmpty() const QString CustomFunctionData::nameToString(int index, bool globalContext) const { - return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index+1, 0, true); + return RadioData::getElementName((globalContext ? tr("GF") : tr("SF")), index + 1, 0, true); } QString CustomFunctionData::funcToString(const ModelData * model) const { - if (func >= FuncOverrideCH1 && func <= FuncOverrideCH32) + if (func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) return tr("Override %1").arg(RawSource(SOURCE_TYPE_CH, func).toString(model)); else if (func == FuncTrainer) return tr("Trainer Sticks"); @@ -65,8 +65,8 @@ QString CustomFunctionData::funcToString(const ModelData * model) const return tr("Haptic"); else if (func == FuncReset) return tr("Reset"); - else if (func >= FuncSetTimer1 && func <= FuncSetTimer3) - return tr("Set Timer %1").arg(func-FuncSetTimer1+1); + else if (func >= FuncSetTimer1 && func <= FuncSetTimerLast) + return tr("Set %1").arg(RawSource(SOURCE_TYPE_SPECIAL, SOURCE_TYPE_SPECIAL_TIMER1_IDX + func - FuncSetTimer1).toString(model)); else if (func == FuncVario) return tr("Vario"); else if (func == FuncPlayPrompt) @@ -90,7 +90,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const else if (func == FuncBackgroundMusicPause) return tr("Background Music Pause"); else if (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) - return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func-FuncAdjustGV1).toString(model)); + return tr("Adjust %1").arg(RawSource(SOURCE_TYPE_GVAR, func - FuncAdjustGV1).toString(model)); else if (func == FuncSetFailsafe) return tr("Set Failsafe"); else if (func == FuncRangeCheckInternalModule) @@ -102,7 +102,7 @@ QString CustomFunctionData::funcToString(const ModelData * model) const else if (func == FuncBindExternalModule) return tr("Bind Ext. Module"); else { - return QString("???"); // Highlight unknown functions with output of question marks.(BTW should not happen that we do not know what a function is) + return QString(CPN_STR_UNKNOWN_ITEM); } } @@ -111,11 +111,16 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox int val = 0; Firmware * firmware = Firmware::getCurrentVariant(); - b->addItem(tr("Timer1"), val++); - b->addItem(tr("Timer2"), val++); - b->addItem( tr("Timer3"), val++); + for (int i = 0; i < CPN_MAX_TIMERS; i++, val++) { + if (i < firmware->getCapability(Timers)) { + RawSource item = RawSource(SOURCE_TYPE_SPECIAL, i + SOURCE_TYPE_SPECIAL_TIMER1_IDX); + b->addItem(item.toString(model), val); + } + } + b->addItem(tr("Flight"), val++); b->addItem(tr("Telemetry"), val++); + int reCount = firmware->getCapability(RotaryEncoders); if (reCount == 1) { b->addItem(tr("Rotary Encoder"), val++); @@ -124,6 +129,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox b->addItem(tr("REa"), val++); b->addItem(tr("REb"), val++); } + if (model) { for (int i = 0; i < firmware->getCapability(Sensors); ++i) { if (model->sensorData[i].isAvailable()) { @@ -132,6 +138,7 @@ void CustomFunctionData::populateResetParams(const ModelData * model, QComboBox } } } + b->setCurrentIndex(b->findData(value)); } @@ -153,18 +160,18 @@ QString CustomFunctionData::paramToString(const ModelData * model) const return QString("%1").arg(param); } else if (func == FuncLogs) { - return QString("%1").arg(param/10.0) + tr("s"); + return QString("%1").arg(param / 10.0) + tr("s"); } else if (func == FuncPlaySound) { CustomFunctionData::populatePlaySoundParams(qs); - if (param>=0 && param<(int)qs.count()) + if (param >= 0 && param < (int)qs.count()) return qs.at(param); else return tr("Inconsistent parameter"); } else if (func == FuncPlayHaptic) { CustomFunctionData::populateHapticParams(qs); - if (param>=0 && param<(int)qs.count()) + if (param >= 0 && param < (int)qs.count()) return qs.at(param); else return tr("Inconsistent parameter"); @@ -193,7 +200,7 @@ QString CustomFunctionData::paramToString(const ModelData * model) const else if (func >= FuncAdjustGV1 && func < FuncCount) { switch (adjustMode) { case FUNC_ADJUST_GVAR_CONSTANT: - return tr("Value ")+QString("%1").arg(param); + return tr("Value ") + QString("%1").arg(param); case FUNC_ADJUST_GVAR_SOURCE: case FUNC_ADJUST_GVAR_GVAR: return RawSource(param).toString(); @@ -218,16 +225,16 @@ QString CustomFunctionData::repeatToString() const } else { unsigned int step = 1; - return tr("repeat(%1s)").arg(step*repeatParam); + return tr("repeat(%1s)").arg(step * repeatParam); } } QString CustomFunctionData::enabledToString() const { - if ((func >= FuncOverrideCH1 && func <= FuncOverrideCH32) || + if ((func >= FuncOverrideCH1 && func <= FuncOverrideCHLast) || (func >= FuncAdjustGV1 && func <= FuncAdjustGVLast) || (func == FuncReset) || - (func >= FuncSetTimer1 && func <= FuncSetTimer2) || + (func >= FuncSetTimer1 && func <= FuncSetTimerLast) || (func == FuncVolume) || (func == FuncBacklight) || (func <= FuncInstantTrim)) { @@ -238,6 +245,64 @@ QString CustomFunctionData::enabledToString() const return ""; } +// static +bool CustomFunctionData::isFuncAvailable(int index) +{ + Firmware * fw = getCurrentFirmware(); + + bool ret = (((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) && !fw->getCapability(SafetyChannelCustomFunction)) || + ((index == FuncVolume || index == FuncBackgroundMusic || index == FuncBackgroundMusicPause) && !fw->getCapability(HasVolume)) || + ((index == FuncPlayScript && !IS_HORUS_OR_TARANIS(fw->getBoard()))) || + ((index == FuncPlayHaptic) && !fw->getCapability(Haptic)) || + ((index == FuncPlayBoth) && !fw->getCapability(HasBeeper)) || + ((index == FuncLogs) && !fw->getCapability(HasSDLogs)) || + ((index >= FuncSetTimer1 && index <= FuncSetTimerLast) && index > FuncSetTimer1 + fw->getCapability(Timers)) || + ((index == FuncScreenshot) && !IS_HORUS_OR_TARANIS(fw->getBoard())) || + ((index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) && !fw->getCapability(DangerousFunctions)) || + ((index >= FuncAdjustGV1 && index <= FuncAdjustGVLast) && !fw->getCapability(Gvars)) + ); + return !ret; +} + +// static +int CustomFunctionData::funcContext(int index) +{ + int ret = AllFunctionContexts; + + if ((index >= FuncOverrideCH1 && index <= FuncOverrideCHLast) || + (index >= FuncRangeCheckInternalModule && index <= FuncBindExternalModule) || + (index >= FuncAdjustGV1 && index <= FuncAdjustGVLast)) + ret &= ~GlobalFunctionsContext; + + return ret; +} +// static +int CustomFunctionData::resetParamCount(const ModelData * model) +{ + QComboBox cb; + CustomFunctionData::populateResetParams(model, &cb); + return cb.count(); +} + +// static +bool CustomFunctionData::isResetParamAvailable(const ModelData * model, int index) +{ + Firmware * firmware = getCurrentFirmware(); + + if (index < CPN_MAX_TIMERS) { + if (index < firmware->getCapability(Timers)) + return true; + else + return false; + } + else if (index < CPN_MAX_TIMERS + firmware->getCapability(RotaryEncoders)) + return true; + else if (model && index < CPN_MAX_TIMERS + firmware->getCapability(RotaryEncoders) + firmware->getCapability(Sensors)) + return model->sensorData[index - CPN_MAX_TIMERS - firmware->getCapability(RotaryEncoders)].isAvailable(); + + return false; +} + void CustomFunctionData::convert(RadioDataConversionState & cstate) { cstate.setComponent(tr("CFN"), 8); diff --git a/companion/src/firmwares/customfunctiondata.h b/companion/src/firmwares/customfunctiondata.h index 93f9969e8..9e597441f 100644 --- a/companion/src/firmwares/customfunctiondata.h +++ b/companion/src/firmwares/customfunctiondata.h @@ -35,7 +35,8 @@ class RadioDataConversionState; enum AssignFunc { FuncOverrideCH1 = 0, - FuncOverrideCH32 = FuncOverrideCH1+CPN_MAX_CHNOUT-1, + FuncOverrideCHLast = FuncOverrideCH1 + CPN_MAX_CHNOUT - 1, + FuncOverrideCH32 = FuncOverrideCHLast, // TODO remove FuncTrainer, FuncTrainerRUD, FuncTrainerELE, @@ -47,8 +48,9 @@ enum AssignFunc { FuncPlayHaptic, FuncReset, FuncSetTimer1, - FuncSetTimer2, - FuncSetTimer3, + FuncSetTimer2, // TODO remove + FuncSetTimer3, // TODO remove + FuncSetTimerLast = FuncSetTimer1 + CPN_MAX_TIMERS - 1, FuncVario, FuncPlayPrompt, FuncPlayBoth, @@ -61,7 +63,7 @@ enum AssignFunc { FuncBackgroundMusic, FuncBackgroundMusicPause, FuncAdjustGV1, - FuncAdjustGVLast = FuncAdjustGV1+CPN_MAX_GVARS-1, + FuncAdjustGVLast = FuncAdjustGV1 + CPN_MAX_GVARS - 1, FuncSetFailsafe, FuncRangeCheckInternalModule, FuncRangeCheckExternalModule, @@ -83,7 +85,15 @@ class CustomFunctionData { Q_DECLARE_TR_FUNCTIONS(CustomFunctionData) public: - CustomFunctionData(AssignFunc func=FuncOverrideCH1) { clear(); this->func = func; } + enum CustomFunctionContext + { + GlobalFunctionsContext = 0x01, + SpecialFunctionsContext = 0x02, + + AllFunctionContexts = GlobalFunctionsContext | SpecialFunctionsContext + }; + + CustomFunctionData(AssignFunc func = FuncOverrideCH1) { clear(); this->func = func; } RawSwitch swtch; AssignFunc func; int param; @@ -95,7 +105,7 @@ class CustomFunctionData { void clear(); bool isEmpty() const; QString nameToString(int index, bool globalContext = false) const; - QString funcToString(const ModelData * model = NULL) const; + QString funcToString(const ModelData * model = nullptr) const; QString paramToString(const ModelData * model) const; QString repeatToString() const; QString enabledToString() const; @@ -103,6 +113,10 @@ class CustomFunctionData { static void populateResetParams(const ModelData * model, QComboBox * b, unsigned int value); static void populatePlaySoundParams(QStringList & qs); static void populateHapticParams(QStringList & qs); + static bool isFuncAvailable(int index); + static int funcContext(int index); + static int resetParamCount(const ModelData * model); + static bool isResetParamAvailable(const ModelData * model, int index); void convert(RadioDataConversionState & cstate); diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp index 930df092c..7657e2798 100644 --- a/companion/src/firmwares/modeldata.cpp +++ b/companion/src/firmwares/modeldata.cpp @@ -1439,3 +1439,42 @@ void ModelData::updateResetParam(CustomFunctionData * cfd) updRefInfo.updcnt++; } } + +QString ModelData::thrTraceSrcToString() const +{ + return thrTraceSrcToString((int)thrTraceSrc); +} + +QString ModelData::thrTraceSrcToString(const int index) const +{ + Firmware * firmware = getCurrentFirmware(); + const Boards board = Boards(getCurrentBoard()); + const int pscnt = board.getCapability(Board::Pots) + board.getCapability(Board::Sliders); + + if (index == 0) + return tr("THR"); + else if (index <= pscnt) + return board.getAnalogInputName(index + board.getCapability(Board::Sticks) - 1); + else if (index <= pscnt + firmware->getCapability(Outputs)) + return RawSource(SOURCE_TYPE_CH, index - pscnt - 1).toString(this); + + return QString(CPN_STR_UNKNOWN_ITEM); +} + +int ModelData::thrTraceSrcCount() const +{ + const Boards board = Boards(getCurrentBoard()); + Firmware * firmware = getCurrentFirmware(); + + return 1 + board.getCapability(Board::Pots) + board.getCapability(Board::Sliders) + firmware->getCapability(Outputs); +} + +bool ModelData::isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const +{ + const Boards board = Boards(getCurrentBoard()); + + if (index > 0 && index <= board.getCapability(Board::Pots) + board.getCapability(Board::Sliders)) + return RawSource(SOURCE_TYPE_STICK, index + board.getCapability(Board::Sticks) - 1).isAvailable(this, generalSettings, board.getBoardType()); + else + return true; +} diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h index 7eacdc26d..2b277568f 100644 --- a/companion/src/firmwares/modeldata.h +++ b/companion/src/firmwares/modeldata.h @@ -283,6 +283,10 @@ class ModelData { bool hasExpoChildren(const int index); bool hasExpoSiblings(const int index); void removeMix(const int idx); + QString thrTraceSrcToString() const; + QString thrTraceSrcToString(const int index) const; + int thrTraceSrcCount() const; + bool isThrTraceSrcAvailable(const GeneralSettings * generalSettings, const int index) const; protected: void removeGlobalVar(int & var); diff --git a/companion/src/firmwares/moduledata.h b/companion/src/firmwares/moduledata.h index 550509a46..119f44eb8 100644 --- a/companion/src/firmwares/moduledata.h +++ b/companion/src/firmwares/moduledata.h @@ -141,8 +141,9 @@ enum MultiModuleRFProtocols { MODULE_SUBTYPE_MULTI_REALACC, MODULE_SUBTYPE_MULTI_OMP, MODULE_SUBTYPE_MULTI_MLINK, - MODULE_SUBTYPE_MULTI_WFLYRF, - MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_WFLYRF + MODULE_SUBTYPE_MULTI_WFLY2, + MODULE_SUBTYPE_MULTI_E016HV2, + MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_E016HV2 }; enum TrainerProtocol { diff --git a/companion/src/firmwares/multiprotocols.cpp b/companion/src/firmwares/multiprotocols.cpp index bc4fe4151..1aedbc7d5 100644 --- a/companion/src/firmwares/multiprotocols.cpp +++ b/companion/src/firmwares/multiprotocols.cpp @@ -90,10 +90,10 @@ static const QStringList STR_SUBTYPE_FRSKYL {"LR12", "LR12 6-Channel"}; static const QStringList STR_SUBTYPE_ESKY150V2 {"150 V2"}; static const QStringList STR_SUBTYPE_JJRC345 {"Standard", "SkyTumbler"}; static const QStringList STR_SUBTYPE_KYOSHO {"FHSS", "Hype"}; -static const QStringList STR_SUBTYPE_RLINK {"Surface", "Air"}; +static const QStringList STR_SUBTYPE_RLINK {"Surface", "Air", "DumboRC"}; static const QStringList STR_SUBTYPE_ELRS {"Not Available WIP"}; static const QStringList STR_SUBTYPE_REALACC {"R11"}; -static const QStringList STR_SUBTYPE_WFLYRF {"RF20x"}; +static const QStringList STR_SUBTYPE_WFLY2 {"RF20x"}; static const QStringList NO_SUBTYPE {STR_MULTI_DEFAULT}; @@ -159,11 +159,12 @@ const Multiprotocols multiProtocols { {MODULE_SUBTYPE_MULTI_JJRC345, 1, false, STR_SUBTYPE_JJRC345, nullptr}, {MODULE_SUBTYPE_MULTI_Q90C, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_KYOSHO, 1, false, STR_SUBTYPE_KYOSHO, nullptr}, - {MODULE_SUBTYPE_MULTI_RLINK, 1, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE}, + {MODULE_SUBTYPE_MULTI_RLINK, 2, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_ELRS, 0, false, STR_SUBTYPE_ELRS, nullptr}, {MODULE_SUBTYPE_MULTI_REALACC, 0, false, STR_SUBTYPE_REALACC, nullptr}, {MODULE_SUBTYPE_MULTI_OMP, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, - {MODULE_SUBTYPE_MULTI_WFLYRF, 0, false, STR_SUBTYPE_WFLYRF, nullptr}, + {MODULE_SUBTYPE_MULTI_WFLY2, 0, false, STR_SUBTYPE_WFLY2, STR_MULTI_OPTION}, + {MODULE_SUBTYPE_MULTI_E016HV2, 0, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MM_RF_CUSTOM_SELECTED, 7, true, STR_SUBTYPE_CUSTOM, STR_MULTI_OPTION}, // Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff) @@ -208,7 +209,8 @@ QString Multiprotocols::protocolToString(int protocol, bool custom) "Hitec", "Wfly", "Bugs", "Bugs Mini", "Traxxas", "NCC-1701-A", "E01X", "WL Heli V911S", "GD00X", "Volantex V761", "KFPlan KF606", "Redpine", "Potensic", "ZSX", "Height", "Scanner", "FrSky RX", "FlySky AFHDS2A RX", "HoTT", "Fx816", "Bayang RX", "Pelikan", "Tiger", "XK", "XN297 Dump", "FrSky X 2.1", "FrSky R9", "Propel", "FrSky L", "Skyartec", - "ESky 150v2", "DSM RX", "JJRC345", "Q90C", "Kyosho", "RadioLink", "ExpressLRS", "Realacc", "OMP", "M-Link", "Wfly RF" + "ESky 150v2", "DSM RX", "JJRC345", "Q90C", "Kyosho", "RadioLink", "ExpressLRS", "Realacc", "OMP", "M-Link", "Wfly 2", + "E016H v2" }); return strings.value(protocol, CPN_STR_UNKNOWN_ITEM); diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp index f6adcc563..264a3ad6a 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.cpp +++ b/companion/src/firmwares/opentx/opentxeeprom.cpp @@ -48,6 +48,9 @@ inline int MAX_SWITCHES(Board::Type board, int version) if (IS_FAMILY_T12(board)) return 8; + if (IS_TARANIS_X7(board)) + return 8; + return Boards::getCapability(board, Board::Switches); } diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h index 115885474..c3395693d 100644 --- a/companion/src/firmwares/opentx/opentxeeprom.h +++ b/companion/src/firmwares/opentx/opentxeeprom.h @@ -38,6 +38,7 @@ #define JUMPER_T12_VARIANT 0x4001 #define RADIOMASTER_TX12_VARIANT 0x4002 #define JUMPER_TLITE_VARIANT 0x4003 +#define RADIOMASTER_T8_VARIANT 0x4004 class OpenTxGeneralData: public TransformedField { public: diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 0b22e4f37..a9b3f69e9 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -70,6 +70,8 @@ const char * OpenTxEepromInterface::getName() return "OpenTX for Radiomaster TX16S"; case BOARD_RADIOMASTER_TX12: return "OpenTX for Radiomaster TX12"; + case BOARD_RADIOMASTER_T8: + return "OpenTX for Radiomaster T8"; case BOARD_TARANIS_X9D: return "OpenTX for FrSky Taranis X9D"; case BOARD_TARANIS_X9DP: @@ -344,6 +346,9 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u else if (IS_RADIOMASTER_TX12(board)) { variant |= RADIOMASTER_TX12_VARIANT; } + else if (IS_RADIOMASTER_T8(board)) { + variant |= RADIOMASTER_T8_VARIANT; + } OpenTxGeneralData generator((GeneralSettings &)radioData.generalSettings, board, version, variant); // generator.dump(); QByteArray data; @@ -692,6 +697,8 @@ int OpenTxFirmware::getCapability(::Capability capability) return JUMPER_TLITE_VARIANT; else if (IS_RADIOMASTER_TX12(board)) return RADIOMASTER_TX12_VARIANT; + else if (IS_RADIOMASTER_T8(board)) + return RADIOMASTER_T8_VARIANT; else return 0; case MavlinkTelemetry: @@ -966,6 +973,11 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari variantError = true; } } + else if (IS_RADIOMASTER_T8(board)) { + if (variant != RADIOMASTER_T8_VARIANT) { + variantError = true; + } + } else if (IS_TARANIS(board)) { if (variant != 0) { variantError = true; @@ -1316,6 +1328,17 @@ void registerOpenTxFirmwares() registerOpenTxFirmware(firmware); addOpenTxRfOptions(firmware, FLEX); + /* Radiomaster T8 board */ + firmware = new OpenTxFirmware("opentx-t8", QCoreApplication::translate("Firmware", "Radiomaster T8"), BOARD_RADIOMASTER_T8); + addOpenTxCommonOptions(firmware); + firmware->addOption("noheli", Firmware::tr("Disable HELI menu and cyclic mix support")); + firmware->addOption("nogvars", Firmware::tr("Disable Global variables")); + firmware->addOption("lua", Firmware::tr("Enable Lua custom scripts screen")); + addOpenTxFontOptions(firmware); + registerOpenTxFirmware(firmware); + addOpenTxRfOptions(firmware, NONE); + firmware->addOption("bindkey", Firmware::tr("Allow bind using bind key")); + /* Radiomaster TX16S board */ firmware = new OpenTxFirmware("opentx-tx16s", Firmware::tr("Radiomaster TX16S / SE / Hall / Masterfire"), BOARD_RADIOMASTER_TX16S); addOpenTxFrskyOptions(firmware); diff --git a/companion/src/firmwares/rawsource.cpp b/companion/src/firmwares/rawsource.cpp index 67a640c33..67ad743b6 100644 --- a/companion/src/firmwares/rawsource.cpp +++ b/companion/src/firmwares/rawsource.cpp @@ -143,14 +143,14 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con static const QString rotary[] = { tr("REa"), tr("REb") }; if (index<0) { - return tr("???"); + return QString(CPN_STR_UNKNOWN_ITEM); } QString result; int genAryIdx = 0; switch (type) { case SOURCE_TYPE_NONE: - return tr("----"); + return QString(CPN_STR_NONE_ITEM); case SOURCE_TYPE_VIRTUAL_INPUT: { @@ -161,7 +161,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con } case SOURCE_TYPE_LUA_OUTPUT: - return tr("LUA%1%2").arg(index/16+1).arg(QChar('a'+index%16)); + return tr("LUA%1%2").arg(index / 16 + 1).arg(QChar('a' + index % 16)); case SOURCE_TYPE_STICK: if (generalSettings) { @@ -193,10 +193,10 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return result; case SOURCE_TYPE_CUSTOM_SWITCH: - return RawSwitch(SWITCH_TYPE_VIRTUAL, index+1).toString(); + return RawSwitch(SWITCH_TYPE_VIRTUAL, index + 1).toString(); case SOURCE_TYPE_CYC: - return tr("CYC%1").arg(index+1); + return tr("CYC%1").arg(index + 1); case SOURCE_TYPE_PPM: return RadioData::getElementName(tr("TR", "as in Trainer"), index + 1); @@ -208,18 +208,15 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return LimitData().nameToString(index); case SOURCE_TYPE_SPECIAL: - result = CHECK_IN_ARRAY(special, index); - // TODO refactor timers into own source type - if (result.startsWith("Timer")) { - bool ok; - int n = result.right(1).toInt(&ok); - if (ok) { - if (model) - result = model->timers[n - 1].nameToString(n - 1); - else - result = TimerData().nameToString(n - 1); - } + if (index >= SOURCE_TYPE_SPECIAL_TIMER1_IDX && index <= SOURCE_TYPE_SPECIAL_TIMER1_IDX + CPN_MAX_TIMERS - 1) { + if (model) + result = model->timers[index - SOURCE_TYPE_SPECIAL_TIMER1_IDX].nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX); + else + result = TimerData().nameToString(index - SOURCE_TYPE_SPECIAL_TIMER1_IDX); } + else + result = CHECK_IN_ARRAY(special, index); + return result; case SOURCE_TYPE_TELEMETRY: @@ -241,7 +238,7 @@ QString RawSource::toString(const ModelData * model, const GeneralSettings * con return GVarData().nameToString(index); default: - return tr("???"); + return QString(CPN_STR_UNKNOWN_ITEM); } } @@ -409,4 +406,3 @@ QStringList RawSource::getSwitchList(Boards board) const } return ret; } - diff --git a/companion/src/firmwares/rawsource.h b/companion/src/firmwares/rawsource.h index 9d0b19450..a7d293173 100644 --- a/companion/src/firmwares/rawsource.h +++ b/companion/src/firmwares/rawsource.h @@ -178,6 +178,9 @@ enum RawSourceType { MAX_SOURCE_TYPE }; +constexpr int SOURCE_TYPE_STICK_THR_IDX { 3 }; // TODO is there a function to determine index? +constexpr int SOURCE_TYPE_SPECIAL_TIMER1_IDX { 2 }; // TODO temp const until Timers own source type + class RawSourceRange { Q_DECLARE_TR_FUNCTIONS(RawSourceRange) diff --git a/companion/src/firmwares/sensordata.cpp b/companion/src/firmwares/sensordata.cpp index a9b8d7640..ebcccfa6a 100644 --- a/companion/src/firmwares/sensordata.cpp +++ b/companion/src/firmwares/sensordata.cpp @@ -22,6 +22,8 @@ #include "radiodata.h" #include "modeldata.h" +#include "eeprominterface.h" +#include "compounditemmodels.h" void SensorData::updateUnit() { @@ -31,9 +33,18 @@ void SensorData::updateUnit() } } +// TODO depreciated QString SensorData::unitString() const { - switch (unit) { + return unitToString(unit); +} + +// static +QString SensorData::unitToString(const int value) +{ + switch (value) { + case UNIT_RAW: + return tr("Raw (-)"); case UNIT_VOLTS: return tr("V"); case UNIT_AMPS: @@ -91,7 +102,7 @@ QString SensorData::unitString() const case UNIT_US: return tr("uS"); default: - return ""; + return CPN_STR_UNKNOWN_ITEM; } } @@ -118,3 +129,166 @@ bool SensorData::isEmpty() const { return (!isAvailable() && type == 0 && id == 0 && subid == 0 && instance == 0 && rxIdx == 0 && moduleIdx == 0 && unit == 0 && ratio == 0 && prec == 0 && offset == 0 && autoOffset == 0 && filter == 0 && onlyPositive == 0 && logs == 0); } + +// static +QString SensorData::typeToString(const int value) +{ + switch(value) { + case TELEM_TYPE_CUSTOM: + return tr("Custom"); + case TELEM_TYPE_CALCULATED: + return tr("Calculated"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString SensorData::formulaToString(const int value) +{ + switch(value) { + case TELEM_FORMULA_ADD: + return tr("Add"); + case TELEM_FORMULA_AVERAGE: + return tr("Average"); + case TELEM_FORMULA_MIN: + return tr("Minimum"); + case TELEM_FORMULA_MAX: + return tr("Maximum"); + case TELEM_FORMULA_MULTIPLY: + return tr("Multiply"); + case TELEM_FORMULA_TOTALIZE: + return tr("Totalize"); + case TELEM_FORMULA_CELL: + return tr("Cell"); + case TELEM_FORMULA_CONSUMPTION: + return tr("Consumption"); + case TELEM_FORMULA_DIST: + return tr("Distance"); + default: + return CPN_STR_UNKNOWN_ITEM; + } +} + +// static +QString SensorData::cellIndexToString(const int value) +{ + if (value == TELEM_CELL_INDEX_LOWEST) + return tr("Lowest"); + if (value > TELEM_CELL_INDEX_LOWEST && value < TELEM_CELL_INDEX_HIGHEST) + return tr("Cell %1").arg(value - TELEM_CELL_INDEX_LOWEST); + if (value== TELEM_CELL_INDEX_HIGHEST) + return tr("Highest"); + if (value == TELEM_CELL_INDEX_DELTA) + return tr("Delta"); + return CPN_STR_UNKNOWN_ITEM; +} + +// static +QString SensorData::precisionToString(const int value) +{ + return QString("0.%1").arg(QString(value, '0')); +} + +// static +QString SensorData::sourceToString(const ModelData * model, const int index, const bool sign) +{ + if (model) { + const QString prfx = sign ? index < 0 ? "-" : "+" : ""; + + if (abs(index) > 0) { + const SensorData &sd = model->sensorData[abs(index) - 1]; + if (sd.type == SensorData::TELEM_TYPE_CUSTOM) + return QString("%1%2 (%3)").arg(prfx).arg(sd.label).arg(sd.getOrigin(model)); + else + return QString("%1%2").arg(prfx).arg(sd.label); + } + else + return CPN_STR_NONE_ITEM; + } + + return ""; +} + +// static +bool SensorData::isSourceAvailable(const ModelData * model, const int index) +{ + Firmware * firmware = getCurrentFirmware(); + const int sensorcnt = firmware->getCapability(Sensors); + const int i = abs(index); + + if (model && sensorcnt > 0 && i <= sensorcnt) { + if (i > 0) + return model->sensorData[i - 1].isAvailable(); + else + return true; + } + + return false; +} + +// static +AbstractStaticItemModel * SensorData::typeItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.type"); + + for (int i = 0; i <= TELEM_TYPE_LAST; i++) { + mdl->appendToItemList(typeToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * SensorData::formulaItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.formula"); + + for (int i = 0; i <= TELEM_FORMULA_LAST; i++) { + mdl->appendToItemList(formulaToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * SensorData::cellIndexItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.cellindex"); + + for (int i = 0; i <= TELEM_CELL_INDEX_LAST; i++) { + mdl->appendToItemList(cellIndexToString(i), i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +AbstractStaticItemModel * SensorData::unitItemModel() +{ + AbstractStaticItemModel * mdl = new AbstractStaticItemModel(); + mdl->setName("sensordata.unit"); + + for (int i = 0; i <= UNIT_MAX; i++) { + QString str = unitToString(i); + if (str != CPN_STR_UNKNOWN_ITEM) + mdl->appendToItemList(str, i); + } + + mdl->loadItemList(); + return mdl; +} + +// static +PrecisionItemModel * SensorData::precisionItemModel() +{ + PrecisionItemModel * mdl = new PrecisionItemModel(0, 2); + mdl->setName("sensordata.precision"); + return mdl; +} diff --git a/companion/src/firmwares/sensordata.h b/companion/src/firmwares/sensordata.h index a2b993bcc..afd9d7891 100644 --- a/companion/src/firmwares/sensordata.h +++ b/companion/src/firmwares/sensordata.h @@ -27,6 +27,8 @@ constexpr int CPN_MAX_SENSORS = 60; constexpr int SENSOR_LABEL_LEN = 4; class ModelData; +class AbstractStaticItemModel; +class PrecisionItemModel; class SensorData { Q_DECLARE_TR_FUNCTIONS(SensorData) @@ -36,7 +38,8 @@ class SensorData { enum { TELEM_TYPE_CUSTOM, - TELEM_TYPE_CALCULATED + TELEM_TYPE_CALCULATED, + TELEM_TYPE_LAST = TELEM_TYPE_CALCULATED }; enum @@ -63,6 +66,7 @@ class SensorData { TELEM_CELL_INDEX_6, TELEM_CELL_INDEX_HIGHEST, TELEM_CELL_INDEX_DELTA, + TELEM_CELL_INDEX_LAST = TELEM_CELL_INDEX_DELTA }; enum @@ -168,6 +172,20 @@ class SensorData { QString getOrigin(const ModelData* model) const; void clear() { memset(this, 0, sizeof(SensorData)); } bool isEmpty() const; + + static QString sourceToString(const ModelData * model, const int index, const bool sign = false); + static bool isSourceAvailable(const ModelData * model, const int index); + static QString typeToString(const int value); + static QString formulaToString(const int value); + static QString cellIndexToString(const int value); + static QString unitToString(const int value); + static QString precisionToString(const int value); + + static AbstractStaticItemModel * typeItemModel(); + static AbstractStaticItemModel * formulaItemModel(); + static AbstractStaticItemModel * cellIndexItemModel(); + static AbstractStaticItemModel * unitItemModel(); + static PrecisionItemModel * precisionItemModel(); }; #endif // SENSORDATA_H diff --git a/companion/src/generaledit/generaledit.cpp b/companion/src/generaledit/generaledit.cpp index bff9d3f83..e80038f9f 100644 --- a/companion/src/generaledit/generaledit.cpp +++ b/companion/src/generaledit/generaledit.cpp @@ -28,7 +28,7 @@ #include "hardware.h" #include "../modeledit/customfunctions.h" #include "verticalscrollarea.h" -#include "rawitemdatamodels.h" +#include "compounditemmodels.h" GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * firmware) : QDialog(parent), @@ -56,10 +56,14 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir } } - commonItemModels = new CommonItemModels(&generalSettings, nullptr, this); + sharedItemModels = new CompoundItemModelFactory(&generalSettings, nullptr); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam); addTab(new GeneralSetupPanel(this, generalSettings, firmware), tr("Setup")); - addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, commonItemModels), tr("Global Functions")); + addTab(new CustomFunctionsPanel(this, nullptr, generalSettings, firmware, sharedItemModels), tr("Global Functions")); addTab(new TrainerPanel(this, generalSettings, firmware), tr("Trainer")); addTab(new HardwarePanel(this, generalSettings, firmware), tr("Hardware")); addTab(new CalibrationPanel(this, generalSettings, firmware), tr("Calibration")); @@ -70,6 +74,7 @@ GeneralEdit::GeneralEdit(QWidget * parent, RadioData & radioData, Firmware * fir GeneralEdit::~GeneralEdit() { delete ui; + delete sharedItemModels; } void GeneralEdit::closeEvent(QCloseEvent *event) diff --git a/companion/src/generaledit/generaledit.h b/companion/src/generaledit/generaledit.h index 3f73a9e01..b2e6caa82 100644 --- a/companion/src/generaledit/generaledit.h +++ b/companion/src/generaledit/generaledit.h @@ -25,7 +25,7 @@ #include "eeprominterface.h" #include "genericpanel.h" -class CommonItemModels; +class CompoundItemModelFactory; namespace Ui { class GeneralEdit; @@ -73,7 +73,7 @@ class GeneralEdit : public QDialog QVector panels; void addTab(GenericPanel *panel, QString text); void closeEvent(QCloseEvent *event); - CommonItemModels *commonItemModels; + CompoundItemModelFactory *sharedItemModels; }; #endif // _GENERALEDIT_H_ diff --git a/companion/src/images/simulator/T8/bottom.png b/companion/src/images/simulator/T8/bottom.png new file mode 100644 index 000000000..055c7db62 Binary files /dev/null and b/companion/src/images/simulator/T8/bottom.png differ diff --git a/companion/src/images/simulator/T8/left-pagedn.png b/companion/src/images/simulator/T8/left-pagedn.png new file mode 100644 index 000000000..6b290e368 Binary files /dev/null and b/companion/src/images/simulator/T8/left-pagedn.png differ diff --git a/companion/src/images/simulator/T8/left-pageup.png b/companion/src/images/simulator/T8/left-pageup.png new file mode 100644 index 000000000..c155649a1 Binary files /dev/null and b/companion/src/images/simulator/T8/left-pageup.png differ diff --git a/companion/src/images/simulator/T8/left-rtn.png b/companion/src/images/simulator/T8/left-rtn.png new file mode 100644 index 000000000..95cc700f6 Binary files /dev/null and b/companion/src/images/simulator/T8/left-rtn.png differ diff --git a/companion/src/images/simulator/T8/left-sys.png b/companion/src/images/simulator/T8/left-sys.png new file mode 100644 index 000000000..7943ed93d Binary files /dev/null and b/companion/src/images/simulator/T8/left-sys.png differ diff --git a/companion/src/images/simulator/T8/left.png b/companion/src/images/simulator/T8/left.png new file mode 100644 index 000000000..ff25c9543 Binary files /dev/null and b/companion/src/images/simulator/T8/left.png differ diff --git a/companion/src/images/simulator/T8/right-dn.png b/companion/src/images/simulator/T8/right-dn.png new file mode 100644 index 000000000..82a383576 Binary files /dev/null and b/companion/src/images/simulator/T8/right-dn.png differ diff --git a/companion/src/images/simulator/T8/right-ent.png b/companion/src/images/simulator/T8/right-ent.png new file mode 100644 index 000000000..8c3be3a56 Binary files /dev/null and b/companion/src/images/simulator/T8/right-ent.png differ diff --git a/companion/src/images/simulator/T8/right-mdl.png b/companion/src/images/simulator/T8/right-mdl.png new file mode 100644 index 000000000..f385c652e Binary files /dev/null and b/companion/src/images/simulator/T8/right-mdl.png differ diff --git a/companion/src/images/simulator/T8/right-up.png b/companion/src/images/simulator/T8/right-up.png new file mode 100644 index 000000000..5e3bd39ed Binary files /dev/null and b/companion/src/images/simulator/T8/right-up.png differ diff --git a/companion/src/images/simulator/T8/right.png b/companion/src/images/simulator/T8/right.png new file mode 100644 index 000000000..1016d8de5 Binary files /dev/null and b/companion/src/images/simulator/T8/right.png differ diff --git a/companion/src/images/simulator/T8/top.png b/companion/src/images/simulator/T8/top.png new file mode 100644 index 000000000..962119223 Binary files /dev/null and b/companion/src/images/simulator/T8/top.png differ diff --git a/companion/src/mainwindow.cpp b/companion/src/mainwindow.cpp index 9d490da39..23c5f71b7 100644 --- a/companion/src/mainwindow.cpp +++ b/companion/src/mainwindow.cpp @@ -1585,7 +1585,7 @@ void MainWindow::updateWindowActions() QString scut; if (++count < 10) scut = tr("Alt+%1").arg(count); - QAction * act = addActToGroup(windowsListActions, "", "", "window_ptr", qVariantFromValue(win), QVariant(), scut); + QAction * act = addActToGroup(windowsListActions, "", "", "window_ptr", QVariant::fromValue(win), QVariant(), scut); act->setChecked(win == mdiArea->activeSubWindow()); updateWindowActionTitle(win, act); } diff --git a/companion/src/modeledit/channels.cpp b/companion/src/modeledit/channels.cpp index d2818368e..27374a8c4 100644 --- a/companion/src/modeledit/channels.cpp +++ b/companion/src/modeledit/channels.cpp @@ -20,7 +20,7 @@ #include "channels.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" LimitsGroup::LimitsGroup(Firmware * firmware, TableLayout * tableLayout, int row, int col, int & value, const ModelData & model, int min, int max, int deflt, ModelPanel * panel): firmware(firmware), @@ -96,16 +96,15 @@ void LimitsGroup::updateMinMax(int max) } } } -ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +ChannelsPanel::ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { chnCapability = firmware->getCapability(Outputs); int channelNameMaxLen = firmware->getCapability(ChannelsName); - curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); - connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &ChannelsPanel::onModelDataAboutToBeUpdated); - connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &ChannelsPanel::onModelDataUpdateComplete); + curveFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_Curve)); + connectItemModelEvents(curveFilteredModel); QStringList headerLabels; headerLabels << "#"; @@ -214,6 +213,7 @@ ChannelsPanel::~ChannelsPanel() delete centerSB[i]; delete symlimitsChk[i]; } + delete curveFilteredModel; } void ChannelsPanel::symlimitsEdited() @@ -474,12 +474,18 @@ void ChannelsPanel::swapData(int idx1, int idx2) } } -void ChannelsPanel::onModelDataAboutToBeUpdated() +void ChannelsPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &ChannelsPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &ChannelsPanel::onItemModelUpdateComplete); +} + +void ChannelsPanel::onItemModelAboutToBeUpdated() { lock = true; } -void ChannelsPanel::onModelDataUpdateComplete() +void ChannelsPanel::onItemModelUpdateComplete() { update(); lock = false; @@ -487,5 +493,5 @@ void ChannelsPanel::onModelDataUpdateComplete() void ChannelsPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_CHANNELS); + sharedItemModels->update(AbstractItemModel::IMUE_Channels); } diff --git a/companion/src/modeledit/channels.h b/companion/src/modeledit/channels.h index a481feec2..2a65f497a 100644 --- a/companion/src/modeledit/channels.h +++ b/companion/src/modeledit/channels.h @@ -26,8 +26,8 @@ #include -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; constexpr char MIMETYPE_CHANNEL[] = "application/x-companion-channel"; @@ -57,8 +57,8 @@ class ChannelsPanel : public ModelPanel Q_OBJECT public: - ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); - ~ChannelsPanel(); + ChannelsPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + virtual ~ChannelsPanel(); public slots: void refreshExtendedLimits(); @@ -81,8 +81,8 @@ class ChannelsPanel : public ModelPanel void cmClear(bool prompt = true); void cmClearAll(); void onCustomContextMenuRequested(QPoint pos); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: bool hasClipboardData(QByteArray * data = nullptr) const; @@ -100,9 +100,10 @@ class ChannelsPanel : public ModelPanel QCheckBox *symlimitsChk[CPN_MAX_CHNOUT]; int selectedIndex; int chnCapability; - CommonItemModels * commonItemModels; - RawItemFilteredModel *curveFilteredModel; + CompoundItemModelFactory *sharedItemModels; + FilteredItemModel *curveFilteredModel; void updateItemModels(); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _CHANNELS_H_ diff --git a/companion/src/modeledit/curves.cpp b/companion/src/modeledit/curves.cpp index 9e60f30c3..7f8b80219 100644 --- a/companion/src/modeledit/curves.cpp +++ b/companion/src/modeledit/curves.cpp @@ -23,7 +23,7 @@ #include "node.h" #include "edge.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #define GFX_MARGIN 16 @@ -109,11 +109,12 @@ float curveSymmetricalX(float x, float coeff, float yMin, float yMid, float yMax return y; } -CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +CurvesPanel::CurvesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Curves), currentCurve(0), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { ui->setupUi(this); @@ -812,7 +813,7 @@ void CurvesPanel::swapData(int idx1, int idx2) void CurvesPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_CURVES); + sharedItemModels->update(AbstractItemModel::IMUE_Curves); } CustomScene::CustomScene(QGraphicsView * view) : diff --git a/companion/src/modeledit/curves.h b/companion/src/modeledit/curves.h index 8df3a8528..c66f79cb7 100644 --- a/companion/src/modeledit/curves.h +++ b/companion/src/modeledit/curves.h @@ -26,7 +26,7 @@ #include #include -class CommonItemModels; +class CompoundItemModelFactory; constexpr char MIMETYPE_CURVE[] = "application/x-companion-curve"; @@ -61,7 +61,7 @@ class CurvesPanel : public ModelPanel Q_OBJECT public: - CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + CurvesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~CurvesPanel(); virtual void update(); @@ -121,7 +121,7 @@ class CurvesPanel : public ModelPanel bool moveDownAllowed() const; bool moveUpAllowed() const; void swapData(int idx1, int idx2); - CommonItemModels * commonItemModels; + CompoundItemModelFactory * sharedItemModels; void updateItemModels(); }; diff --git a/companion/src/modeledit/customfunctions.cpp b/companion/src/modeledit/customfunctions.cpp index c3ee895b7..5c15bd538 100644 --- a/companion/src/modeledit/customfunctions.cpp +++ b/companion/src/modeledit/customfunctions.cpp @@ -19,7 +19,7 @@ */ #include "customfunctions.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" #include "appdata.h" @@ -66,10 +66,10 @@ void RepeatComboBox::update() setCurrentIndex(value); } -CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): GenericPanel(parent, model, generalSettings, firmware), functions(model ? model->customFn : generalSettings.customFn), - commonItemModels(commonItemModels), mediaPlayerCurrent(-1), mediaPlayer(nullptr), modelsUpdateCnt(0) @@ -77,21 +77,18 @@ CustomFunctionsPanel::CustomFunctionsPanel(QWidget * parent, ModelData * model, lock = true; fswCapability = model ? firmware->getCapability(CustomFunctions) : firmware->getCapability(GlobalFunctions); - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + model ? RawSwitch::SpecialFunctionsContext : RawSwitch::GlobalFunctionsContext); + connectItemModelEvents(rawSwitchFilteredModel); - rawSourceAllModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this); - connect(rawSourceAllModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceAllModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSourceAllModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource)); + connectItemModelEvents(rawSourceAllModel); - rawSourceInputsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this); - connect(rawSourceInputsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceInputsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSourceInputsModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::InputSourceGroups); + connectItemModelEvents(rawSourceInputsModel); - rawSourceGVarsModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::GVarsGroup, this); - connect(rawSourceGVarsModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &CustomFunctionsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceGVarsModel, &RawItemFilteredModel::dataUpdateComplete, this, &CustomFunctionsPanel::onModelDataUpdateComplete); + rawSourceGVarsModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::GVarsGroup); + connectItemModelEvents(rawSourceGVarsModel); if (!firmware->getCapability(VoicesAsNumbers)) { tracksSet = getFilesSet(getSoundsPath(generalSettings), QStringList() << "*.wav" << "*.WAV", firmware->getCapability(VoicesMaxLength)); @@ -253,6 +250,10 @@ CustomFunctionsPanel::~CustomFunctionsPanel() { if (mediaPlayer) stopSound(mediaPlayerCurrent); + delete rawSwitchFilteredModel; + delete rawSourceAllModel; + delete rawSourceInputsModel; + delete rawSourceGVarsModel; } void CustomFunctionsPanel::onMediaPlayerStateChanged(QMediaPlayer::State state) @@ -827,13 +828,19 @@ bool CustomFunctionsPanel::moveUpAllowed() const return selectedIndex > 0; } -void CustomFunctionsPanel::onModelDataAboutToBeUpdated() +void CustomFunctionsPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &CustomFunctionsPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &CustomFunctionsPanel::onItemModelUpdateComplete); +} + +void CustomFunctionsPanel::onItemModelAboutToBeUpdated() { lock = true; modelsUpdateCnt++; } -void CustomFunctionsPanel::onModelDataUpdateComplete() +void CustomFunctionsPanel::onItemModelUpdateComplete() { modelsUpdateCnt--; if (modelsUpdateCnt < 1) { diff --git a/companion/src/modeledit/customfunctions.h b/companion/src/modeledit/customfunctions.h index 9b3e3d238..e41baf672 100644 --- a/companion/src/modeledit/customfunctions.h +++ b/companion/src/modeledit/customfunctions.h @@ -26,8 +26,8 @@ #include -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; class TimerEdit; constexpr char MIMETYPE_CUSTOM_FUNCTION[] = "application/x-companion-custom-function"; @@ -55,8 +55,8 @@ class CustomFunctionsPanel : public GenericPanel Q_OBJECT public: - CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); - ~CustomFunctionsPanel(); + CustomFunctionsPanel(QWidget *parent, ModelData * model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + virtual ~CustomFunctionsPanel(); virtual void update(); @@ -83,8 +83,8 @@ class CustomFunctionsPanel : public GenericPanel void cmInsert(); void cmClear(bool prompt = true); void cmClearAll(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: void populateFuncCB(QComboBox *b, unsigned int value); @@ -96,11 +96,12 @@ class CustomFunctionsPanel : public GenericPanel bool moveUpAllowed() const; void swapData(int idx1, int idx2); void resetCBsAndRefresh(int idx); - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSwitchFilteredModel; - RawItemFilteredModel * rawSourceAllModel; - RawItemFilteredModel * rawSourceInputsModel; - RawItemFilteredModel * rawSourceGVarsModel; + void connectItemModelEvents(const FilteredItemModel * itemModel); + + FilteredItemModel * rawSwitchFilteredModel; + FilteredItemModel * rawSourceAllModel; + FilteredItemModel * rawSourceInputsModel; + FilteredItemModel * rawSourceGVarsModel; QSet tracksSet; QSet scriptsSet; diff --git a/companion/src/modeledit/expodialog.cpp b/companion/src/modeledit/expodialog.cpp index afebbeb27..808cff7ba 100644 --- a/companion/src/modeledit/expodialog.cpp +++ b/companion/src/modeledit/expodialog.cpp @@ -20,12 +20,11 @@ #include "expodialog.h" #include "ui_expodialog.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, GeneralSettings & generalSettings, - Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceModel, - RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) : + Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels) : QDialog(parent), ui(new Ui::ExpoDialog), model(model), @@ -38,6 +37,9 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G { ui->setupUi(this); + dialogFilteredItemModels = new FilteredItemModelFactory(); + int id; + QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 }; for (int i = 0; i < CPN_MAX_FLIGHT_MODES; i++) { @@ -50,9 +52,15 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, ed->weight, model, 100, -100, 100); gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, ed->offset, model, 0, -100, 100); - curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, curveItemModel, this); - ui->switchesCB->setModel(rawSwitchModel); + curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, + firmware->getCapability(HasInputDiff) ? 0 : FilteredItemModel::PositiveFilter); + curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, ed->curve, model, + curveRefFilteredItemModels, this); + + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::MixesContext), "RawSwitch"); + ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(ed->swtch.toValue())); ui->sideCB->setCurrentIndex(ed->mode - 1); @@ -83,7 +91,10 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G if (firmware->getCapability(VirtualInputs)) { ui->inputName->setMaxLength(firmware->getCapability(InputsLength)); - ui->sourceCB->setModel(rawSourceModel); + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + (RawSource::InputSourceGroups & ~ RawSource::NoneGroup & ~RawSource::InputsGroup)), + "RawSource"); + ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(ed->srcRaw.toValue())); ui->inputName->setValidator(new QRegExpValidator(rx, this)); ui->inputName->setText(inputName); @@ -135,9 +146,10 @@ ExpoDialog::ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expoData, G ExpoDialog::~ExpoDialog() { + delete ui; delete gvWeightGroup; delete gvOffsetGroup; - delete ui; + delete dialogFilteredItemModels; } void ExpoDialog::updateScale() diff --git a/companion/src/modeledit/expodialog.h b/companion/src/modeledit/expodialog.h index b77d55852..f4980d344 100644 --- a/companion/src/modeledit/expodialog.h +++ b/companion/src/modeledit/expodialog.h @@ -26,7 +26,9 @@ #include "modelprinter.h" class GVarGroup; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModelFactory; +class CurveRefFilteredFactory; class CurveReferenceUIManager; namespace Ui { @@ -37,9 +39,8 @@ class ExpoDialog : public QDialog { Q_OBJECT public: ExpoDialog(QWidget *parent, ModelData & model, ExpoData *expodata, GeneralSettings & generalSettings, - Firmware * firmware, QString & inputName, RawItemFilteredModel * rawSourceItemModel, - RawItemFilteredModel * rawSwitchItemModel, RawItemFilteredModel * curveItemModel); - ~ExpoDialog(); + Firmware * firmware, QString & inputName, CompoundItemModelFactory * sharedItemModels); + virtual ~ExpoDialog(); protected: void updateScale(); @@ -65,6 +66,8 @@ class ExpoDialog : public QDialog { ModelPrinter modelPrinter; bool lock; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; + FilteredItemModelFactory *dialogFilteredItemModels; + CurveRefFilteredFactory *curveRefFilteredItemModels; }; #endif // _EXPODIALOG_H_ diff --git a/companion/src/modeledit/flightmodes.cpp b/companion/src/modeledit/flightmodes.cpp index 32188feea..224d69965 100644 --- a/companion/src/modeledit/flightmodes.cpp +++ b/companion/src/modeledit/flightmodes.cpp @@ -20,19 +20,19 @@ #include "flightmodes.h" #include "ui_flightmode.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" #include "customdebug.h" -FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel): +FlightModePanel::FlightModePanel(QWidget * parent, ModelData & model, int phaseIdx, GeneralSettings & generalSettings, Firmware * firmware, + FilteredItemModel * rawSwitchFilteredModel): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::FlightMode), phaseIdx(phaseIdx), phase(model.flightModeData[phaseIdx]) { ui->setupUi(this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &FlightModePanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &FlightModePanel::onModelDataUpdateComplete); + connectItemModelEvents(rawSwitchFilteredModel); ui->labelName->setContextMenuPolicy(Qt::CustomContextMenu); ui->labelName->setToolTip(tr("Popup menu available")); @@ -1361,12 +1361,18 @@ void FlightModePanel::gvSwapData(int idx1, int idx2) } } -void FlightModePanel::onModelDataAboutToBeUpdated() +void FlightModePanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModePanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModePanel::onItemModelUpdateComplete); +} + +void FlightModePanel::onItemModelAboutToBeUpdated() { lock = true; } -void FlightModePanel::onModelDataUpdateComplete() +void FlightModePanel::onItemModelUpdateComplete() { update(); lock = false; @@ -1374,11 +1380,14 @@ void FlightModePanel::onModelDataUpdateComplete() /**********************************************************/ -FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::MixesContext); + connectItemModelEvents(rawSwitchFilteredModel); + modesCount = firmware->getCapability(FlightModes); QGridLayout * gridLayout = new QGridLayout(this); @@ -1403,6 +1412,7 @@ FlightModesPanel::FlightModesPanel(QWidget * parent, ModelData & model, GeneralS FlightModesPanel::~FlightModesPanel() { + delete rawSwitchFilteredModel; } QString FlightModesPanel::getTabName(int index) @@ -1431,10 +1441,24 @@ void FlightModesPanel::update() emit updated(); } +void FlightModesPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &FlightModesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &FlightModesPanel::onItemModelUpdateComplete); +} + +void FlightModesPanel::onItemModelAboutToBeUpdated() +{ +} + +void FlightModesPanel::onItemModelUpdateComplete() +{ +} + void FlightModesPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_FLIGHT_MODES); - commonItemModels->update(CommonItemModels::RMO_GLOBAL_VARIABLES); + sharedItemModels->update(AbstractItemModel::IMUE_FlightModes); + sharedItemModels->update(AbstractItemModel::IMUE_GVars); } void FlightModesPanel::onTabIndexChanged(int index) diff --git a/companion/src/modeledit/flightmodes.h b/companion/src/modeledit/flightmodes.h index ca3619c6c..33fd87e8a 100644 --- a/companion/src/modeledit/flightmodes.h +++ b/companion/src/modeledit/flightmodes.h @@ -24,8 +24,8 @@ #include "modeledit.h" #include "eeprominterface.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; constexpr char MIMETYPE_FLIGHTMODE[] = "application/x-companion-flightmode"; constexpr char MIMETYPE_GVAR_PARAMS[] = "application/x-companion-gvar-params"; @@ -41,7 +41,8 @@ class FlightModePanel : public ModelPanel Q_OBJECT public: - FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSwitchFilteredModel); + FlightModePanel(QWidget *parent, ModelData &model, int modeIdx, GeneralSettings & generalSettings, Firmware * firmware, + FilteredItemModel * rawSwitchFilteredModel); virtual ~FlightModePanel(); virtual void update(); @@ -90,8 +91,8 @@ class FlightModePanel : public ModelPanel void gvCmPaste(); void gvCmMoveDown(); void gvCmMoveUp(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::FlightMode *ui; @@ -138,6 +139,7 @@ class FlightModePanel : public ModelPanel bool gvMoveDownAllowed() const; bool gvMoveUpAllowed() const; void gvSwapData(int idx1, int idx2); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class FlightModesPanel : public ModelPanel @@ -145,7 +147,7 @@ class FlightModesPanel : public ModelPanel Q_OBJECT public: - FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + FlightModesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~FlightModesPanel(); public slots: @@ -157,16 +159,19 @@ class FlightModesPanel : public ModelPanel private slots: void onPhaseNameChanged(); void onTabIndexChanged(int index); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: QString getTabName(int index); int modesCount; QTabWidget *tabWidget; - CommonItemModels *commonItemModels; - RawItemFilteredModel *rawSwitchFilteredModel; + CompoundItemModelFactory *sharedItemModels; + FilteredItemModel *rawSwitchFilteredModel; QVector panels; void updateItemModels(); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _FLIGHTMODES_H_ diff --git a/companion/src/modeledit/heli.cpp b/companion/src/modeledit/heli.cpp index 1b8607799..ef86c5793 100644 --- a/companion/src/modeledit/heli.cpp +++ b/companion/src/modeledit/heli.cpp @@ -21,18 +21,16 @@ #include "heli.h" #include "ui_heli.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" -HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - ui(new Ui::Heli), - commonItemModels(commonItemModels) + ui(new Ui::Heli) { ui->setupUi(this); - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), RawSource::InputSourceGroups, this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &HeliPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &HeliPanel::onModelDataUpdateComplete); + rawSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), RawSource::InputSourceGroups); + connectItemModelEvents(rawSourceFilteredModel); connect(ui->swashType, SIGNAL(currentIndexChanged(int)), this, SLOT(edited())); connect(ui->swashRingVal, SIGNAL(editingFinished()), this, SLOT(edited())); @@ -71,6 +69,7 @@ HeliPanel::HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & gener HeliPanel::~HeliPanel() { delete ui; + delete rawSourceFilteredModel; } void HeliPanel::update() @@ -118,12 +117,18 @@ void HeliPanel::edited() } } -void HeliPanel::onModelDataAboutToBeUpdated() +void HeliPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &HeliPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &HeliPanel::onItemModelUpdateComplete); +} + +void HeliPanel::onItemModelAboutToBeUpdated() { lock = true; } -void HeliPanel::onModelDataUpdateComplete() +void HeliPanel::onItemModelUpdateComplete() { update(); lock = false; diff --git a/companion/src/modeledit/heli.h b/companion/src/modeledit/heli.h index ee9a3ac36..eb3c7d54e 100644 --- a/companion/src/modeledit/heli.h +++ b/companion/src/modeledit/heli.h @@ -23,8 +23,8 @@ #include "modeledit.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; namespace Ui { class Heli; @@ -35,19 +35,19 @@ class HeliPanel : public ModelPanel Q_OBJECT public: - HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); - ~HeliPanel(); + HeliPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); + virtual ~HeliPanel(); void update(); private slots: void edited(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::Heli *ui; - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSourceFilteredModel; + FilteredItemModel * rawSourceFilteredModel; + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _HELI_H_ diff --git a/companion/src/modeledit/inputs.cpp b/companion/src/modeledit/inputs.cpp index ee2347aee..f48d7d916 100644 --- a/companion/src/modeledit/inputs.cpp +++ b/companion/src/modeledit/inputs.cpp @@ -21,25 +21,19 @@ #include "inputs.h" #include "expodialog.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" -InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +InputsPanel::InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), expoInserted(false), modelPrinter(firmware, generalSettings, model), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels), + modelsUpdateCnt(0) { - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), (RawSource::InputSourceGroups & ~ RawSource::NoneGroup & ~RawSource::InputsGroup), this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); - - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); - - curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); - connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &InputsPanel::onModelDataAboutToBeUpdated); - connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &InputsPanel::onModelDataUpdateComplete); + connectItemModelEvents(AbstractItemModel::IMID_RawSource); + connectItemModelEvents(AbstractItemModel::IMID_RawSwitch); + connectItemModelEvents(AbstractItemModel::IMID_Curve); + connectItemModelEvents(AbstractItemModel::IMID_GVarRef); inputsCount = firmware->getCapability(VirtualInputs); if (inputsCount == 0) @@ -194,7 +188,7 @@ void InputsPanel::gm_openExpo(int index) if (firmware->getCapability(VirtualInputs)) inputName = model->inputNames[ed.chn]; - ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel); + ExpoDialog *dlg = new ExpoDialog(this, *model, &ed, generalSettings, firmware, inputName, sharedItemModels); if (dlg->exec()) { model->expoData[index] = ed; if (firmware->getCapability(VirtualInputs)) @@ -730,18 +724,31 @@ int InputsPanel::getInputIndexFromSelected() return idx; } -void InputsPanel::onModelDataAboutToBeUpdated() +void InputsPanel::connectItemModelEvents(const int id) { - lock = true; + AbstractDynamicItemModel * itemModel = qobject_cast(sharedItemModels->getItemModel(id)); + if (itemModel) { + connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &InputsPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &InputsPanel::onItemModelUpdateComplete); + } } -void InputsPanel::onModelDataUpdateComplete() +void InputsPanel::onItemModelAboutToBeUpdated() { - update(); - lock = false; + lock = true; + modelsUpdateCnt++; +} + +void InputsPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } } void InputsPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_INPUTS); + sharedItemModels->update(AbstractItemModel::IMUE_Inputs); } diff --git a/companion/src/modeledit/inputs.h b/companion/src/modeledit/inputs.h index ea1243213..9b360ec19 100644 --- a/companion/src/modeledit/inputs.h +++ b/companion/src/modeledit/inputs.h @@ -25,8 +25,8 @@ #include "mixerslistwidget.h" #include "modelprinter.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; constexpr char MIMETYPE_EXPO[] = "application/x-companion-expo"; @@ -35,7 +35,7 @@ class InputsPanel : public ModelPanel Q_OBJECT public: - InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + InputsPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~InputsPanel(); virtual void update(); @@ -62,8 +62,8 @@ class InputsPanel : public ModelPanel void cmInputInsert(); void cmInputMoveDown(); void cmInputMoveUp(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: bool expoInserted; @@ -72,10 +72,8 @@ class InputsPanel : public ModelPanel ModelPrinter modelPrinter; int selectedIdx; int inputIdx; - CommonItemModels * commonItemModels; - RawItemFilteredModel *rawSourceFilteredModel; - RawItemFilteredModel *rawSwitchFilteredModel; - RawItemFilteredModel *curveFilteredModel; + CompoundItemModelFactory *sharedItemModels; + int modelsUpdateCnt; int getExpoIndex(unsigned int dch); bool gm_insertExpo(int idx); @@ -97,6 +95,7 @@ class InputsPanel : public ModelPanel int getIndexFromSelected(); int getInputIndexFromSelected(); void updateItemModels(); + void connectItemModelEvents(const int id); }; #endif // _INPUTS_H_ diff --git a/companion/src/modeledit/logicalswitches.cpp b/companion/src/modeledit/logicalswitches.cpp index cacd5c6fd..499df9e49 100644 --- a/companion/src/modeledit/logicalswitches.cpp +++ b/companion/src/modeledit/logicalswitches.cpp @@ -19,25 +19,25 @@ */ #include "logicalswitches.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" #include -LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), - commonItemModels(commonItemModels), + sharedItemModels(sharedItemModels), selectedIndex(0), modelsUpdateCnt(0) { - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::LogicalSwitchesContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::LogicalSwitchesContext); + connectItemModelEvents(rawSwitchFilteredModel); const int srcGroups = firmware->getCapability(GvarsInCS) ? 0 : (RawSource::AllSourceGroups & ~RawSource::GVarsGroup); - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), srcGroups, this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &LogicalSwitchesPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &LogicalSwitchesPanel::onModelDataUpdateComplete); + rawSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), srcGroups); + connectItemModelEvents(rawSourceFilteredModel); lsCapability = firmware->getCapability(LogicalSwitches); lsCapabilityExt = firmware->getCapability(LogicalSwitchesExt); @@ -161,6 +161,8 @@ LogicalSwitchesPanel::LogicalSwitchesPanel(QWidget * parent, ModelData & model, LogicalSwitchesPanel::~LogicalSwitchesPanel() { + delete rawSourceFilteredModel; + delete rawSwitchFilteredModel; } void LogicalSwitchesPanel::onFunctionChanged() @@ -644,16 +646,22 @@ void LogicalSwitchesPanel::swapData(int idx1, int idx2) void LogicalSwitchesPanel::updateItemModels() { lock = true; - commonItemModels->update(CommonItemModels::RMO_LOGICAL_SWITCHES); + sharedItemModels->update(AbstractItemModel::IMUE_LogicalSwitches); } -void LogicalSwitchesPanel::onModelDataAboutToBeUpdated() +void LogicalSwitchesPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &LogicalSwitchesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &LogicalSwitchesPanel::onItemModelUpdateComplete); +} + +void LogicalSwitchesPanel::onItemModelAboutToBeUpdated() { lock = true; modelsUpdateCnt++; } -void LogicalSwitchesPanel::onModelDataUpdateComplete() +void LogicalSwitchesPanel::onItemModelUpdateComplete() { modelsUpdateCnt--; if (modelsUpdateCnt < 1) { diff --git a/companion/src/modeledit/logicalswitches.h b/companion/src/modeledit/logicalswitches.h index 87a360408..f1c2f8397 100644 --- a/companion/src/modeledit/logicalswitches.h +++ b/companion/src/modeledit/logicalswitches.h @@ -24,8 +24,8 @@ #include "modeledit.h" #include "radiodata.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; class TimerEdit; constexpr char MIMETYPE_LOGICAL_SWITCH[] = "application/x-companion-logical-switch"; @@ -35,7 +35,7 @@ class LogicalSwitchesPanel : public ModelPanel Q_OBJECT public: - LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + LogicalSwitchesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~LogicalSwitchesPanel(); virtual void update(); @@ -60,8 +60,8 @@ class LogicalSwitchesPanel : public ModelPanel void cmInsert(); void cmClear(bool prompt = true); void cmClearAll(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: QComboBox * cbFunction[CPN_MAX_LOGICAL_SWITCHES]; @@ -74,9 +74,9 @@ class LogicalSwitchesPanel : public ModelPanel QDoubleSpinBox * dsbDelay[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource1[CPN_MAX_LOGICAL_SWITCHES]; QComboBox * cbSource2[CPN_MAX_LOGICAL_SWITCHES]; - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSwitchFilteredModel; - RawItemFilteredModel * rawSourceFilteredModel; + CompoundItemModelFactory * sharedItemModels; + FilteredItemModel * rawSwitchFilteredModel; + FilteredItemModel * rawSourceFilteredModel; int selectedIndex; void populateFunctionCB(QComboBox *b); void updateTimerParam(QDoubleSpinBox *sb, int timer, double minimum=0); @@ -89,6 +89,7 @@ class LogicalSwitchesPanel : public ModelPanel bool moveUpAllowed() const; int modelsUpdateCnt; void updateItemModels(); + void connectItemModelEvents(const FilteredItemModel * itemModel); }; #endif // _LOGICALSWITCHES_H_ diff --git a/companion/src/modeledit/mixerdialog.cpp b/companion/src/modeledit/mixerdialog.cpp index 00d2badc8..67b01f8f6 100644 --- a/companion/src/modeledit/mixerdialog.cpp +++ b/companion/src/modeledit/mixerdialog.cpp @@ -21,11 +21,11 @@ #include "mixerdialog.h" #include "ui_mixerdialog.h" #include "radiodata.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "helpers.h" MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, GeneralSettings & generalSettings, Firmware * firmware, - RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel) : + CompoundItemModelFactory * sharedItemModels) : QDialog(parent), ui(new Ui::MixerDialog), model(model), @@ -36,6 +36,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, { ui->setupUi(this); + dialogFilteredItemModels = new FilteredItemModelFactory(); + int id; + QRegExp rx(CHAR_FOR_NAMES_REGEX); QLabel * lb_fp[CPN_MAX_FLIGHT_MODES] = {ui->lb_FP0, ui->lb_FP1, ui->lb_FP2, ui->lb_FP3, ui->lb_FP4, ui->lb_FP5, ui->lb_FP6, ui->lb_FP7, ui->lb_FP8 }; QCheckBox * tmp[CPN_MAX_FLIGHT_MODES] = {ui->cb_FP0, ui->cb_FP1, ui->cb_FP2, ui->cb_FP3, ui->cb_FP4, ui->cb_FP5, ui->cb_FP6, ui->cb_FP7, ui->cb_FP8 }; @@ -45,14 +48,20 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, this->setWindowTitle(tr("DEST -> %1").arg(RawSource(SOURCE_TYPE_CH, md->destCh - 1).toString(&model, &generalSettings))); - ui->sourceCB->setModel(rawSourceModel); + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource), + ((RawSource::InputSourceGroups | RawSource::ScriptsGroup) & ~ RawSource::NoneGroup)), + "RawSource"); + ui->sourceCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->sourceCB->setCurrentIndex(ui->sourceCB->findData(md->srcRaw.toValue())); int limit = firmware->getCapability(OffsetWeight); gvWeightGroup = new GVarGroup(ui->weightGV, ui->weightSB, ui->weightCB, md->weight, model, 100, -limit, limit); gvOffsetGroup = new GVarGroup(ui->offsetGV, ui->offsetSB, ui->offsetCB, md->sOffset, model, 0, -limit, limit); - curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, curveItemModel, this); + curveRefFilteredItemModels = new CurveRefFilteredFactory(sharedItemModels, + firmware->getCapability(HasMixerExpo) ? 0 : FilteredItemModel::PositiveFilter); + curveGroup = new CurveReferenceUIManager(ui->curveTypeCB, ui->curveGVarCB, ui->curveValueSB, ui->curveValueCB, md->curve, model, + curveRefFilteredItemModels, this); ui->MixDR_CB->setChecked(md->noExpo == 0); @@ -104,7 +113,9 @@ MixerDialog::MixerDialog(QWidget *parent, ModelData & model, MixData * mixdata, } } - ui->switchesCB->setModel(rawSwitchModel); + id = dialogFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), + RawSwitch::MixesContext), "RawSwitch"); + ui->switchesCB->setModel(dialogFilteredItemModels->getItemModel(id)); ui->switchesCB->setCurrentIndex(ui->switchesCB->findData(md->swtch.toValue())); ui->warningCB->setCurrentIndex(md->mixWarn); ui->mltpxCB->setCurrentIndex(md->mltpx); @@ -150,6 +161,7 @@ MixerDialog::~MixerDialog() delete ui; delete gvWeightGroup; delete gvOffsetGroup; + delete dialogFilteredItemModels; } void MixerDialog::changeEvent(QEvent *e) diff --git a/companion/src/modeledit/mixerdialog.h b/companion/src/modeledit/mixerdialog.h index 6d2131de2..04ff1aeaf 100644 --- a/companion/src/modeledit/mixerdialog.h +++ b/companion/src/modeledit/mixerdialog.h @@ -25,7 +25,9 @@ #include "eeprominterface.h" class GVarGroup; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModelFactory; +class CurveRefFilteredFactory; class CurveReferenceUIManager; namespace Ui { @@ -36,7 +38,7 @@ class MixerDialog : public QDialog { Q_OBJECT public: MixerDialog(QWidget *parent, ModelData & model, MixData *mixdata, GeneralSettings & generalSettings, Firmware * firmware, - RawItemFilteredModel * rawSourceModel, RawItemFilteredModel * rawSwitchModel, RawItemFilteredModel * curveItemModel); + CompoundItemModelFactory * sharedItemModels); ~MixerDialog(); protected: @@ -61,6 +63,8 @@ class MixerDialog : public QDialog { GVarGroup * gvOffsetGroup; CurveReferenceUIManager * curveGroup; QCheckBox * cb_fp[CPN_MAX_FLIGHT_MODES]; + FilteredItemModelFactory *dialogFilteredItemModels; + CurveRefFilteredFactory *curveRefFilteredItemModels; }; #endif // _MIXERDIALOG_H_ diff --git a/companion/src/modeledit/mixes.cpp b/companion/src/modeledit/mixes.cpp index f02a57417..3d95bd04d 100644 --- a/companion/src/modeledit/mixes.cpp +++ b/companion/src/modeledit/mixes.cpp @@ -20,26 +20,20 @@ #include "mixes.h" #include "helpers.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" -MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,CommonItemModels * commonItemModels): +MixesPanel::MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), mixInserted(false), highlightedSource(0), modelPrinter(firmware, generalSettings, model), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels), + modelsUpdateCnt(0) { - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), ((RawSource::InputSourceGroups | RawSource::ScriptsGroup) & ~ RawSource::NoneGroup), this); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); - connect(rawSourceFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); - - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::MixesContext, this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); - - curveFilteredModel = new RawItemFilteredModel(commonItemModels->curveItemModel(), RawItemFilteredModel::AllFilter, this); - connect(curveFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &MixesPanel::onModelDataAboutToBeUpdated); - connect(curveFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &MixesPanel::onModelDataUpdateComplete); + connectItemModelEvents(AbstractItemModel::IMID_RawSource); + connectItemModelEvents(AbstractItemModel::IMID_RawSwitch); + connectItemModelEvents(AbstractItemModel::IMID_Curve); + connectItemModelEvents(AbstractItemModel::IMID_GVarRef); QGridLayout * mixesLayout = new QGridLayout(this); @@ -189,7 +183,7 @@ void MixesPanel::gm_openMix(int index) MixData mixd(model->mixData[index]); - MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, rawSourceFilteredModel, rawSwitchFilteredModel, curveFilteredModel); + MixerDialog *dlg = new MixerDialog(this, *model, &mixd, generalSettings, firmware, sharedItemModels); if(dlg->exec()) { model->mixData[index] = mixd; emit modified(); @@ -545,13 +539,26 @@ void MixesPanel::clearMixes() } } -void MixesPanel::onModelDataAboutToBeUpdated() +void MixesPanel::connectItemModelEvents(const int id) { - lock = true; + AbstractDynamicItemModel * itemModel = qobject_cast(sharedItemModels->getItemModel(id)); + if (itemModel) { + connect(itemModel, &AbstractDynamicItemModel::aboutToBeUpdated, this, &MixesPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &AbstractDynamicItemModel::updateComplete, this, &MixesPanel::onItemModelUpdateComplete); + } } -void MixesPanel::onModelDataUpdateComplete() +void MixesPanel::onItemModelAboutToBeUpdated() { - update(); - lock = false; + lock = true; + modelsUpdateCnt++; +} + +void MixesPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } } diff --git a/companion/src/modeledit/mixes.h b/companion/src/modeledit/mixes.h index 014786b74..c298df11a 100644 --- a/companion/src/modeledit/mixes.h +++ b/companion/src/modeledit/mixes.h @@ -26,15 +26,15 @@ #include "mixerdialog.h" #include "modelprinter.h" -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; class MixesPanel : public ModelPanel { Q_OBJECT public: - MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + MixesPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~MixesPanel(); virtual void update(); @@ -60,18 +60,16 @@ class MixesPanel : public ModelPanel void mimeMixerDropped(int index, const QMimeData *data, Qt::DropAction action); void pasteMixerMimeData(const QMimeData * mimeData, int destIdx); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: MixersListWidget * mixersListWidget; bool mixInserted; unsigned int highlightedSource; ModelPrinter modelPrinter; - CommonItemModels * commonItemModels; - RawItemFilteredModel *rawSourceFilteredModel; - RawItemFilteredModel *rawSwitchFilteredModel; - RawItemFilteredModel *curveFilteredModel; + CompoundItemModelFactory *sharedItemModels; + int modelsUpdateCnt; int getMixerIndex(unsigned int dch); bool gm_insertMix(int idx); @@ -83,6 +81,7 @@ class MixesPanel : public ModelPanel void setSelectedByMixList(QList list); void AddMixerLine(int dest); QString getMixerText(int dest, bool newChannel); + void connectItemModelEvents(const int id); }; #endif // _MIXES_H_ diff --git a/companion/src/modeledit/modeledit.cpp b/companion/src/modeledit/modeledit.cpp index 41989ba53..3577be7ae 100644 --- a/companion/src/modeledit/modeledit.cpp +++ b/companion/src/modeledit/modeledit.cpp @@ -33,7 +33,7 @@ #include "customfunctions.h" #include "telemetry.h" #include "appdata.h" -#include "rawitemdatamodels.h" +#include "compounditemmodels.h" ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmware * firmware) : QDialog(parent), @@ -53,42 +53,53 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw GeneralSettings &generalSettings = radioData.generalSettings; ModelData &model = radioData.models[modelId]; - commonItemModels = new CommonItemModels(&generalSettings, &model, this); + sharedItemModels = new CompoundItemModelFactory(&generalSettings, &model); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_RawSwitch); + sharedItemModels->addItemModel(AbstractItemModel::IMID_Curve); + sharedItemModels->addItemModel(AbstractItemModel::IMID_GVarRef); + sharedItemModels->addItemModel(AbstractItemModel::IMID_ThrSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncAction); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CustomFuncResetParam); + sharedItemModels->addItemModel(AbstractItemModel::IMID_TeleSource); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CurveRefType); + sharedItemModels->addItemModel(AbstractItemModel::IMID_CurveRefFunc); + s1.report("Init"); - SetupPanel * setupPanel = new SetupPanel(this, model, generalSettings, firmware, commonItemModels); + SetupPanel * setupPanel = new SetupPanel(this, model, generalSettings, firmware, sharedItemModels); addTab(setupPanel, tr("Setup")); s1.report("Setup"); if (firmware->getCapability(Heli)) { - addTab(new HeliPanel(this, model, generalSettings, firmware, commonItemModels), tr("Heli")); + addTab(new HeliPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Heli")); s1.report("Heli"); } - addTab(new FlightModesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Flight Modes")); + addTab(new FlightModesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Flight Modes")); s1.report("Flight Modes"); - addTab(new InputsPanel(this, model, generalSettings, firmware, commonItemModels), tr("Inputs")); + addTab(new InputsPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Inputs")); s1.report("Inputs"); - addTab(new MixesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Mixes")); + addTab(new MixesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Mixes")); s1.report("Mixes"); - ChannelsPanel * channelsPanel = new ChannelsPanel(this, model, generalSettings, firmware, commonItemModels); + ChannelsPanel * channelsPanel = new ChannelsPanel(this, model, generalSettings, firmware, sharedItemModels); addTab(channelsPanel, tr("Outputs")); s1.report("Outputs"); - addTab(new CurvesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Curves")); + addTab(new CurvesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Curves")); s1.report("Curves"); - addTab(new LogicalSwitchesPanel(this, model, generalSettings, firmware, commonItemModels), tr("Logical Switches")); + addTab(new LogicalSwitchesPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Logical Switches")); s1.report("Logical Switches"); - addTab(new CustomFunctionsPanel(this, &model, generalSettings, firmware, commonItemModels), tr("Special Functions")); + addTab(new CustomFunctionsPanel(this, &model, generalSettings, firmware, sharedItemModels), tr("Special Functions")); s1.report("Special Functions"); if (firmware->getCapability(Telemetry)) { - addTab(new TelemetryPanel(this, model, generalSettings, firmware, commonItemModels), tr("Telemetry")); + addTab(new TelemetryPanel(this, model, generalSettings, firmware, sharedItemModels), tr("Telemetry")); s1.report("Telemetry"); } @@ -104,6 +115,7 @@ ModelEdit::ModelEdit(QWidget * parent, RadioData & radioData, int modelId, Firmw ModelEdit::~ModelEdit() { delete ui; + delete sharedItemModels; } void ModelEdit::closeEvent(QCloseEvent *event) diff --git a/companion/src/modeledit/modeledit.h b/companion/src/modeledit/modeledit.h index 9095101bf..0bd4af9d8 100644 --- a/companion/src/modeledit/modeledit.h +++ b/companion/src/modeledit/modeledit.h @@ -25,7 +25,7 @@ #include "genericpanel.h" class RadioData; -class CommonItemModels; +class CompoundItemModelFactory; namespace Ui { class ModelEdit; @@ -60,12 +60,12 @@ class ModelEdit : public QDialog private: Ui::ModelEdit *ui; int modelId; - RadioData & radioData; - Firmware * firmware; + RadioData &radioData; + Firmware *firmware; QVector panels; - CommonItemModels * commonItemModels; + CompoundItemModelFactory *sharedItemModels; - void addTab(GenericPanel *panel, QString text); + void addTab(GenericPanel * panel, QString text); void launchSimulation(); }; diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp index e4f67178d..25cd576ec 100644 --- a/companion/src/modeledit/setup.cpp +++ b/companion/src/modeledit/setup.cpp @@ -22,7 +22,7 @@ #include "ui_setup.h" #include "ui_setup_timer.h" #include "ui_setup_module.h" -#include "rawitemfilteredmodel.h" +#include "filtereditemmodels.h" #include "appdata.h" #include "modelprinter.h" #include "multiprotocols.h" @@ -31,14 +31,14 @@ #include -TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget * prevFocus, RawItemFilteredModel * rawSwitchFilteredModel): +TimerPanel::TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, + QWidget * prevFocus, FilteredItemModel * rawSwitchFilteredModel): ModelPanel(parent, model, generalSettings, firmware), timer(timer), ui(new Ui::Timer) { ui->setupUi(this); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TimerPanel::onModelDataAboutToBeUpdated); - connect(rawSwitchFilteredModel, &RawItemFilteredModel::dataUpdateComplete, this, &TimerPanel::onModelDataUpdateComplete); + connectItemModelEvents(rawSwitchFilteredModel); lock = true; @@ -172,12 +172,18 @@ void TimerPanel::on_name_editingFinished() } } -void TimerPanel::onModelDataAboutToBeUpdated() +void TimerPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TimerPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TimerPanel::onItemModelUpdateComplete); +} + +void TimerPanel::onItemModelAboutToBeUpdated() { lock = true; } -void TimerPanel::onModelDataUpdateComplete() +void TimerPanel::onItemModelUpdateComplete() { update(); lock = false; @@ -991,13 +997,19 @@ void ModulePanel::onClearAccessRxClicked() /******************************************************************************/ -SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels) : ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Setup), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels) { ui->setupUi(this); - rawSwitchFilteredModel = new RawItemFilteredModel(commonItemModels->rawSwitchItemModel(), RawSwitch::TimersContext, this); + + rawSwitchFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSwitch), RawSwitch::TimersContext); + connectItemModelEvents(rawSwitchFilteredModel); + + thrSourceFilteredModel = new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_ThrSource)); + connectItemModelEvents(thrSourceFilteredModel); Board::Type board = firmware->getBoard(); @@ -1248,6 +1260,8 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge SetupPanel::~SetupPanel() { delete ui; + delete rawSwitchFilteredModel; + delete thrSourceFilteredModel; } void SetupPanel::on_extendedLimits_toggled(bool checked) @@ -1750,7 +1764,21 @@ void SetupPanel::onTimerNameChanged() updateItemModels(); } +void SetupPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &SetupPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &SetupPanel::onItemModelUpdateComplete); +} + +void SetupPanel::onItemModelAboutToBeUpdated() +{ +} + +void SetupPanel::onItemModelUpdateComplete() +{ +} + void SetupPanel::updateItemModels() { - commonItemModels->update(CommonItemModels::RMO_TIMERS); + sharedItemModels->update(AbstractItemModel::IMUE_Timers); } diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h index c56e63ea1..c931f9dd7 100644 --- a/companion/src/modeledit/setup.h +++ b/companion/src/modeledit/setup.h @@ -26,8 +26,8 @@ constexpr char MIMETYPE_TIMER[] = "application/x-companion-timer"; -class CommonItemModels; -class RawItemFilteredModel; +class CompoundItemModelFactory; +class FilteredItemModel; namespace Ui { class Setup; @@ -40,7 +40,8 @@ class TimerPanel : public ModelPanel Q_OBJECT public: - TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, QWidget *prevFocus, RawItemFilteredModel * switchModel); + TimerPanel(QWidget *parent, ModelData & model, TimerData & timer, GeneralSettings & generalSettings, Firmware * firmware, + QWidget *prevFocus, FilteredItemModel * switchModel); virtual ~TimerPanel(); virtual void update(); @@ -51,8 +52,8 @@ class TimerPanel : public ModelPanel void on_value_editingFinished(); void on_minuteBeep_toggled(bool checked); void on_name_editingFinished(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); signals: void nameChanged(); @@ -60,6 +61,7 @@ class TimerPanel : public ModelPanel private: TimerData & timer; Ui::Timer * ui; + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class ModulePanel : public ModelPanel @@ -131,7 +133,7 @@ class SetupPanel : public ModelPanel Q_OBJECT public: - SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + SetupPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CompoundItemModelFactory * sharedItemModels); virtual ~SetupPanel(); virtual void update(); @@ -170,6 +172,8 @@ class SetupPanel : public ModelPanel void cmTimerMoveDown(); void cmTimerMoveUp(); void onTimerNameChanged(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::Setup *ui; @@ -191,9 +195,11 @@ class SetupPanel : public ModelPanel bool moveTimerDownAllowed() const; bool moveTimerUpAllowed() const; void swapTimerData(int idx1, int idx2); - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSwitchFilteredModel; + CompoundItemModelFactory * sharedItemModels; + FilteredItemModel * rawSwitchFilteredModel; + FilteredItemModel * thrSourceFilteredModel; void updateItemModels(); - }; + void connectItemModelEvents(const FilteredItemModel * itemModel); +}; #endif // _SETUP_H_ diff --git a/companion/src/modeledit/telemetry.cpp b/companion/src/modeledit/telemetry.cpp index e980c3943..423e10e5d 100644 --- a/companion/src/modeledit/telemetry.cpp +++ b/companion/src/modeledit/telemetry.cpp @@ -24,24 +24,36 @@ #include "ui_telemetry_sensor.h" #include "helpers.h" #include "appdata.h" -#include "rawitemfilteredmodel.h" #include -TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel): +constexpr char FIM_RAWSOURCE[] {"Raw Source"}; +constexpr char FIM_TELEALLSRC[] {"Tele All Source"}; +constexpr char FIM_TELEPOSSRC[] {"Tele Pos Source"}; +constexpr char FIM_SENSORTYPE[] {"Sensor.Type"}; +constexpr char FIM_SENSORFORMULA[] {"Sensor.Formula"}; +constexpr char FIM_SENSORCELLINDEX[] {"Sensor.CellIndex"}; +constexpr char FIM_SENSORUNIT[] {"Sensor.Unit"}; +constexpr char FIM_SENSORPRECISION[] {"Sensor.Precision"}; + +TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, + Firmware * firmware, const bool & parentLock, FilteredItemModelFactory * panelFilteredItemModels): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetryCustomScreen), - screen(screen) + screen(screen), + modelsUpdateCnt(0), + parentLock(parentLock) { ui->setupUi(this); - connect(rawSourceModel, &RawItemFilteredModel::dataAboutToBeUpdated, this, &TelemetryCustomScreen::onModelDataAboutToBeUpdated); - connect(rawSourceModel, &RawItemFilteredModel::dataUpdateComplete, this, &TelemetryCustomScreen::onModelDataUpdateComplete); + + FilteredItemModel * rawSourceFilteredModel = panelFilteredItemModels->getItemModel(FIM_RAWSOURCE); + connectItemModelEvents(rawSourceFilteredModel); for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensLines); l++) { for (int c = 0; c < firmware->getCapability(TelemetryCustomScreensFieldsPerLine); c++) { fieldsCB[l][c] = new QComboBox(this); fieldsCB[l][c]->setProperty("index", c + (l << 8)); - fieldsCB[l][c]->setModel(rawSourceModel); + fieldsCB[l][c]->setModel(rawSourceFilteredModel); ui->screenNumsLayout->addWidget(fieldsCB[l][c], l, c, 1, 1); connect(fieldsCB[l][c], SIGNAL(activated(int)), this, SLOT(customFieldChanged(int))); } @@ -50,7 +62,7 @@ TelemetryCustomScreen::TelemetryCustomScreen(QWidget *parent, ModelData & model, for (int l = 0; l < firmware->getCapability(TelemetryCustomScreensBars); l++) { barsCB[l] = new QComboBox(this); barsCB[l]->setProperty("index", l); - barsCB[l]->setModel(rawSourceModel); + barsCB[l]->setModel(rawSourceFilteredModel); connect(barsCB[l], SIGNAL(activated(int)), this, SLOT(barSourceChanged(int))); ui->screenBarsLayout->addWidget(barsCB[l], l, 0, 1, 1); @@ -203,7 +215,7 @@ void TelemetryCustomScreen::updateBar(int line) void TelemetryCustomScreen::on_screenType_currentIndexChanged(int index) { - if (!lock) { + if (!isLocked()) { memset(reinterpret_cast(&screen.body), 0, sizeof(screen.body)); update(); emit modified(); @@ -212,7 +224,7 @@ void TelemetryCustomScreen::on_screenType_currentIndexChanged(int index) void TelemetryCustomScreen::scriptNameEdited() { - if (!lock) { + if (!isLocked()) { lock = true; Helpers::getFileComboBoxValue(ui->scriptName, screen.body.script.filename, 8); emit modified(); @@ -222,7 +234,7 @@ void TelemetryCustomScreen::scriptNameEdited() void TelemetryCustomScreen::customFieldChanged(int value) { - if (lock || !sender() || !qobject_cast(sender())) + if (isLocked() || !sender() || !qobject_cast(sender())) return; bool ok; @@ -238,7 +250,7 @@ void TelemetryCustomScreen::customFieldChanged(int value) void TelemetryCustomScreen::barSourceChanged(int value) { - if (lock || !sender() || !qobject_cast(sender())) + if (isLocked() || !sender() || !qobject_cast(sender())) return; bool ok; @@ -256,7 +268,7 @@ void TelemetryCustomScreen::barSourceChanged(int value) void TelemetryCustomScreen::barMinChanged(double value) { - if (!lock) { + if (!isLocked()) { int line = sender()->property("index").toInt(); screen.body.bars[line].barMin = round(value / minSB[line]->singleStep()); // TODO set min (maxSB) @@ -266,7 +278,7 @@ void TelemetryCustomScreen::barMinChanged(double value) void TelemetryCustomScreen::barMaxChanged(double value) { - if (!lock) { + if (!isLocked()) { int line = sender()->property("index").toInt(); screen.body.bars[line].barMax = round((value) / maxSB[line]->singleStep()); // TODO set max (minSB) @@ -276,7 +288,7 @@ void TelemetryCustomScreen::barMaxChanged(double value) void TelemetryCustomScreen::barTimeChanged() { - if (!lock) { + if (!isLocked()) { int line = sender()->property("index").toInt(); int & valRef = (sender()->property("type").toString() == "min" ? screen.body.bars[line].barMin : screen.body.bars[line].barMax); TimerEdit * te = qobject_cast(sender()); @@ -289,29 +301,51 @@ void TelemetryCustomScreen::barTimeChanged() } } -void TelemetryCustomScreen::onModelDataAboutToBeUpdated() +void TelemetryCustomScreen::connectItemModelEvents(const FilteredItemModel * itemModel) { - lock = true; + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TelemetryCustomScreen::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TelemetryCustomScreen::onItemModelUpdateComplete); } -void TelemetryCustomScreen::onModelDataUpdateComplete() +void TelemetryCustomScreen::onItemModelAboutToBeUpdated() { - update(); - lock = false; + lock = true; + modelsUpdateCnt++; +} + +void TelemetryCustomScreen::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + // leave updating to parent + lock = false; + } } /******************************************************/ -TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware): +TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, + GeneralSettings & generalSettings, Firmware * firmware, const bool & parentLock, + FilteredItemModelFactory * panelFilteredItemModels) : ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::TelemetrySensor), sensor(sensor), - lock(false), sensorIndex(sensorIndex), selectedIndex(0), - sensorCapability(sensorCapability) + sensorCapability(sensorCapability), + modelsUpdateCnt(0), + parentLock(parentLock) { + // TODO ui definition housekeeping + // - remove all predefined combobox lists leaving to code + // - use Auto types for consistency ui->setupUi(this); + FilteredItemModel * fltmdl; + + connectItemModelEvents(panelFilteredItemModels->getItemModel(FIM_TELEALLSRC)); + connectItemModelEvents(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); + + lock = true; ui->numLabel->setText(tr("TELE%1").arg(sensorIndex + 1)); ui->numLabel->setProperty("index", sensorIndex); ui->numLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); @@ -326,6 +360,9 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, connect(ui->numLabel, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(on_customContextMenuRequested(QPoint))); ui->id->setField(sensor.id, this); ui->instance->setField(sensor.instance, this); + ui->type->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORTYPE)); + ui->formula->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORFORMULA)); + ui->unit->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORUNIT)); ui->ratio->setField(sensor.ratio, this); ui->offset->setField(sensor.offset, this); ui->autoOffset->setField(sensor.autoOffset, this); @@ -333,21 +370,29 @@ TelemetrySensorPanel::TelemetrySensorPanel(QWidget *parent, SensorData & sensor, ui->logs->setField(sensor.logs, this); ui->persistent->setField(sensor.persistent, this); ui->onlyPositive->setField(sensor.onlyPositive, this); + fltmdl = panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC); + ui->gpsSensor->setModel(fltmdl); ui->gpsSensor->setField(sensor.gps, this); + ui->altSensor->setModel(fltmdl); ui->altSensor->setField(sensor.alt, this); + ui->ampsSensor->setModel(fltmdl); ui->ampsSensor->setField(sensor.amps, this); + ui->cellsSensor->setModel(fltmdl); ui->cellsSensor->setField(sensor.source, this); - ui->cellsIndex->addItem(tr("Lowest"), SensorData::TELEM_CELL_INDEX_LOWEST); - for (int i = SensorData::TELEM_CELL_INDEX_LOWEST + 1; i < SensorData::TELEM_CELL_INDEX_HIGHEST; i++) - ui->cellsIndex->addItem(tr("Cell %1").arg(i), i); - ui->cellsIndex->addItem(tr("Highest"), SensorData::TELEM_CELL_INDEX_HIGHEST); - ui->cellsIndex->addItem(tr("Delta"), SensorData::TELEM_CELL_INDEX_DELTA); + ui->cellsIndex->setModel(panelFilteredItemModels->getItemModel(FIM_SENSORCELLINDEX)); ui->cellsIndex->setField(sensor.index); + fltmdl = panelFilteredItemModels->getItemModel(FIM_TELEALLSRC); + ui->source1->setModel(fltmdl); ui->source1->setField(sensor.sources[0], this); + ui->source2->setModel(fltmdl); ui->source2->setField(sensor.sources[1], this); + ui->source3->setModel(fltmdl); ui->source3->setField(sensor.sources[2], this); + ui->source4->setModel(fltmdl); ui->source4->setField(sensor.sources[3], this); - ui->prec->setField(sensor.prec, 0, 2, false, "", this); + ui->prec->setField(sensor.prec, 0, 2, false, "", this); // TODO replace autoprecisioncombobox with autocombobox and filtereditemmodel + lock = false; + update(); } @@ -358,6 +403,7 @@ TelemetrySensorPanel::~TelemetrySensorPanel() void TelemetrySensorPanel::update() { + // TODO use bit mask bool isConfigurable = false; bool gpsFieldsDisplayed = false; bool cellsFieldsDisplayed = false; @@ -369,8 +415,8 @@ void TelemetrySensorPanel::update() lock = true; ui->name->setText(sensor.label); - ui->type->setCurrentIndex(sensor.type); - ui->unit->setCurrentIndex(sensor.unit); + ui->type->setCurrentIndex(ui->type->findData(sensor.type)); + ui->unit->setCurrentIndex(ui->unit->findData(sensor.unit)); ui->id->updateValue(); ui->instance->updateValue(); ui->ratio->updateValue(); @@ -396,7 +442,7 @@ void TelemetrySensorPanel::update() ui->originLabel->hide(); ui->origin->hide(); ui->formula->show(); - ui->formula->setCurrentIndex(sensor.formula); + ui->formula->setCurrentIndex(ui->formula->findData(sensor.formula)); isConfigurable = (sensor.formula < SensorData::TELEM_FORMULA_CELL); gpsFieldsDisplayed = (sensor.formula == SensorData::TELEM_FORMULA_DIST); cellsFieldsDisplayed = (sensor.formula == SensorData::TELEM_FORMULA_CELL); @@ -404,14 +450,10 @@ void TelemetrySensorPanel::update() sources12FieldsDisplayed = (sensor.formula <= SensorData::TELEM_FORMULA_MULTIPLY); sources34FieldsDisplayed = (sensor.formula < SensorData::TELEM_FORMULA_MULTIPLY); totalizeFieldsDisplayed = (sensor.formula == SensorData::TELEM_FORMULA_TOTALIZE); - updateSourcesComboBox(ui->source1, true); - updateSourcesComboBox(ui->source2, true); - updateSourcesComboBox(ui->source3, true); - updateSourcesComboBox(ui->source4, true); - updateSourcesComboBox(ui->gpsSensor, false); - updateSourcesComboBox(ui->altSensor, false); - updateSourcesComboBox(ui->ampsSensor, false); - updateSourcesComboBox(ui->cellsSensor, false); + ui->source1->updateValue(); + ui->source2->updateValue(); + ui->source3->updateValue(); + ui->source4->updateValue(); } else { ui->idLabel->show(); @@ -483,40 +525,9 @@ void TelemetrySensorPanel::update() lock = false; } -void populateTelemetrySourcesComboBox(AutoComboBox * cb, const ModelData * model, bool negative) -{ - cb->clear(); - if (negative) { - for (int i = -CPN_MAX_SENSORS; i < 0; ++i) { - const SensorData& sensor = model->sensorData[-i - 1]; - if (sensor.isAvailable()) { - if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) - cb->addItem(QString("-%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); - else - cb->addItem(QString("-%1").arg(sensor.label), i); - } - } - } - cb->addItem("---", 0); - for (unsigned i = 1; i <= CPN_MAX_SENSORS; ++i) { - const SensorData& sensor = model->sensorData[i-1]; - if (sensor.isAvailable()) { - if (sensor.type == SensorData::TELEM_TYPE_CUSTOM) - cb->addItem(QString("%1 (%2)").arg(sensor.label, sensor.getOrigin(model)), i); - else - cb->addItem(QString("%1").arg(sensor.label), i); - } - } -} - -void TelemetrySensorPanel::updateSourcesComboBox(AutoComboBox * cb, bool negative) -{ - populateTelemetrySourcesComboBox(cb, model, negative); -} - void TelemetrySensorPanel::on_name_editingFinished() { - if (!lock) { + if (!isLocked() && (sensor.label != ui->name->text().toLatin1())) { strcpy(sensor.label, ui->name->text().toLatin1()); emit dataModified(); } @@ -524,8 +535,8 @@ void TelemetrySensorPanel::on_name_editingFinished() void TelemetrySensorPanel::on_type_currentIndexChanged(int index) { - if (!lock) { - sensor.type = index; + if (!isLocked()) { + sensor.type = ui->type->itemData(index).toInt(); update(); emit modified(); } @@ -533,8 +544,8 @@ void TelemetrySensorPanel::on_type_currentIndexChanged(int index) void TelemetrySensorPanel::on_formula_currentIndexChanged(int index) { - if (!lock) { - sensor.formula = index; + if (!isLocked()) { + sensor.formula = ui->formula->itemData(index).toInt(); if (sensor.formula == SensorData::TELEM_FORMULA_CELL) { sensor.prec = 2; sensor.unit = SensorData::UNIT_VOLTS; @@ -553,8 +564,8 @@ void TelemetrySensorPanel::on_formula_currentIndexChanged(int index) void TelemetrySensorPanel::on_unit_currentIndexChanged(int index) { - if (!lock) { - sensor.unit = index; + if (!isLocked()) { + sensor.unit = ui->unit->itemData(index).toInt(); if (sensor.unit == SensorData::UNIT_FAHRENHEIT) { sensor.prec = 0; } @@ -565,7 +576,7 @@ void TelemetrySensorPanel::on_unit_currentIndexChanged(int index) void TelemetrySensorPanel::on_prec_valueChanged() { - if (!lock) { + if (!isLocked()) { update(); } } @@ -686,15 +697,69 @@ void TelemetrySensorPanel::cmMoveDown() emit moveDownSensor(selectedIndex); } +void TelemetrySensorPanel::connectItemModelEvents(const FilteredItemModel * itemModel) +{ + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TelemetrySensorPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TelemetrySensorPanel::onItemModelUpdateComplete); +} + +void TelemetrySensorPanel::onItemModelAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void TelemetrySensorPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + // leave updating to parent + lock = false; + } +} + /******************************************************/ -TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels): +TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels): ModelPanel(parent, model, generalSettings, firmware), ui(new Ui::Telemetry), - commonItemModels(commonItemModels) + sharedItemModels(sharedItemModels), + modelsUpdateCnt(0) { ui->setupUi(this); - rawSourceFilteredModel = new RawItemFilteredModel(commonItemModels->rawSourceItemModel(), this); + + panelItemModels = new CompoundItemModelFactory(&generalSettings, &model); + panelFilteredItemModels = new FilteredItemModelFactory(); + int id; + + id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_RawSource)), + FIM_RAWSOURCE); + connectItemModelEvents(id); + + id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_TeleSource)), + FIM_TELEALLSRC); + connectItemModelEvents(id); + + id = panelFilteredItemModels->registerItemModel(new FilteredItemModel(sharedItemModels->getItemModel(AbstractItemModel::IMID_TeleSource), + FilteredItemModel::PositiveFilter), + FIM_TELEPOSSRC); + connectItemModelEvents(id); + + id = panelItemModels->registerItemModel(SensorData::typeItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORTYPE); + + id = panelItemModels->registerItemModel(SensorData::formulaItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORFORMULA); + + id = panelItemModels->registerItemModel(SensorData::cellIndexItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORCELLINDEX); + + id = panelItemModels->registerItemModel(SensorData::unitItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORUNIT); + + id = panelItemModels->registerItemModel(SensorData::precisionItemModel()); + panelFilteredItemModels->registerItemModel(new FilteredItemModel(panelItemModels->getItemModel(id)), FIM_SENSORPRECISION); sensorCapability = firmware->getCapability(Sensors); if (sensorCapability > CPN_MAX_SENSORS) // TODO should be role of getCapability @@ -704,13 +769,15 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin model.frsky.usrProto = 1; } + ui->varioSource->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->varioSource->setField(model.frsky.varioSource, this); ui->varioCenterSilent->setField(model.frsky.varioCenterSilent, this); ui->A1GB->hide(); ui->A2GB->hide(); for (int i = 0; i < sensorCapability; ++i) { - TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, firmware); + TelemetrySensorPanel * panel = new TelemetrySensorPanel(this, model.sensorData[i], i, sensorCapability, model, generalSettings, + firmware, lock, panelFilteredItemModels); ui->sensorsLayout->addWidget(panel); sensorPanels[i] = panel; connect(panel, SIGNAL(dataModified()), this, SLOT(on_dataModifiedSensor())); @@ -723,7 +790,9 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin } if (IS_TARANIS_X9(firmware->getBoard())) { + ui->voltsSource->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->voltsSource->setField(model.frsky.voltsSource, this); + ui->altitudeSource->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->altitudeSource->setField(model.frsky.altitudeSource, this); } else { @@ -731,7 +800,8 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin } for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { - TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, rawSourceFilteredModel); + TelemetryCustomScreen * tab = new TelemetryCustomScreen(this, model, model.frsky.screens[i], generalSettings, firmware, lock, + panelFilteredItemModels); ui->customScreens->addTab(tab, tr("Telemetry screen %1").arg(i + 1)); telemetryCustomScreens[i] = tab; connect(tab, &TelemetryCustomScreen::modified, this, &TelemetryPanel::onModified); @@ -745,10 +815,14 @@ TelemetryPanel::TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettin TelemetryPanel::~TelemetryPanel() { delete ui; + delete panelFilteredItemModels; + delete panelItemModels; } void TelemetryPanel::update() { + lock = true; + if (IS_HORUS_OR_TARANIS(firmware->getBoard())) { if (model->moduleData[0].protocol == PULSES_OFF && model->moduleData[1].protocol == PULSES_PPM) { ui->telemetryProtocol->setEnabled(true); @@ -758,10 +832,10 @@ void TelemetryPanel::update() ui->telemetryProtocol->setCurrentIndex(0); } - populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); - populateTelemetrySourcesComboBox(ui->voltsSource, model, false); - populateTelemetrySourcesComboBox(ui->altitudeSource, model, false); - populateTelemetrySourcesComboBox(ui->varioSource, model, false); + ui->rssiSourceCB->updateValue(); + ui->voltsSource->updateValue(); + ui->altitudeSource->updateValue(); + ui->varioSource->updateValue(); } for (int i = 0; i < sensorCapability; ++i) { @@ -771,6 +845,8 @@ void TelemetryPanel::update() for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) { telemetryCustomScreens[i]->update(); } + + lock = false; } void TelemetryPanel::setup() @@ -792,9 +868,9 @@ void TelemetryPanel::setup() ui->rssiSourceLabel->show(); ui->rssiSourceLabel->setText(tr("Source")); + ui->rssiSourceCB->setModel(panelFilteredItemModels->getItemModel(FIM_TELEPOSSRC)); ui->rssiSourceCB->setField(model->rssiSource, this); ui->rssiSourceCB->show(); - populateTelemetrySourcesComboBox(ui->rssiSourceCB, model, false); ui->rssiAlarmWarningCB->hide(); ui->rssiAlarmCriticalCB->hide(); @@ -842,44 +918,9 @@ void TelemetryPanel::setup() lock = false; } -void TelemetryPanel::populateVarioSource() -{ - AutoComboBox * cb = ui->varioSource; - cb->setField(model->frsky.varioSource, this); - cb->addItem(tr("Alti"), TELEMETRY_VARIO_SOURCE_ALTI); - cb->addItem(tr("Alti+"), TELEMETRY_VARIO_SOURCE_ALTI_PLUS); - cb->addItem(tr("VSpeed"), TELEMETRY_VARIO_SOURCE_VSPEED); - cb->addItem(tr("A1"), TELEMETRY_VARIO_SOURCE_A1); - cb->addItem(tr("A2"), TELEMETRY_VARIO_SOURCE_A2); -} - -void TelemetryPanel::populateVoltsSource() -{ - AutoComboBox * cb = ui->frskyVoltCB; - cb->setField(model->frsky.voltsSource, this); - cb->addItem(tr("A1"), TELEMETRY_VOLTS_SOURCE_A1); - cb->addItem(tr("A2"), TELEMETRY_VOLTS_SOURCE_A2); - cb->addItem(tr("A3"), TELEMETRY_VOLTS_SOURCE_A3); - cb->addItem(tr("A4"), TELEMETRY_VOLTS_SOURCE_A4); - cb->addItem(tr("FAS"), TELEMETRY_VOLTS_SOURCE_FAS); - cb->addItem(tr("Cells"), TELEMETRY_VOLTS_SOURCE_CELLS); -} - -void TelemetryPanel::populateCurrentSource() -{ - AutoComboBox * cb = ui->frskyCurrentCB; - cb->setField(model->frsky.currentSource, this); - cb->addItem(tr("---"), TELEMETRY_CURRENT_SOURCE_NONE); - cb->addItem(tr("A1"), TELEMETRY_CURRENT_SOURCE_A1); - cb->addItem(tr("A2"), TELEMETRY_CURRENT_SOURCE_A2); - cb->addItem(tr("A3"), TELEMETRY_CURRENT_SOURCE_A3); - cb->addItem(tr("A4"), TELEMETRY_CURRENT_SOURCE_A4); - cb->addItem(tr("FAS"), TELEMETRY_CURRENT_SOURCE_FAS); -} - void TelemetryPanel::on_telemetryProtocol_currentIndexChanged(int index) { - if (!lock) { + if (!isLocked()) { model->telemetryProtocol = index; emit modified(); } @@ -892,7 +933,7 @@ void TelemetryPanel::onModified() void TelemetryPanel::on_bladesCount_editingFinished() { - if (!lock) { + if (!isLocked()) { model->frsky.blades = ui->bladesCount->value(); emit modified(); } @@ -900,7 +941,7 @@ void TelemetryPanel::on_bladesCount_editingFinished() void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index) { - if (!lock) { + if (!isLocked()) { model->frsky.usrProto = index; for (int i = 0; i < firmware->getCapability(TelemetryCustomScreens); i++) telemetryCustomScreens[i]->update(); @@ -910,31 +951,39 @@ void TelemetryPanel::on_frskyProtoCB_currentIndexChanged(int index) void TelemetryPanel::on_rssiAlarmWarningSB_editingFinished() { - model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value(); - emit modified(); + if (!isLocked()) { + model->rssiAlarms.warning= ui->rssiAlarmWarningSB->value(); + emit modified(); + } } void TelemetryPanel::on_rssiAlarmCriticalSB_editingFinished() { - model->rssiAlarms.critical = ui->rssiAlarmCriticalSB->value(); - emit modified(); + if (!isLocked()) { + model->rssiAlarms.critical = ui->rssiAlarmCriticalSB->value(); + emit modified(); + } } void TelemetryPanel::on_varioLimitMin_DSB_editingFinished() { - model->frsky.varioMin = round(ui->varioLimitMin_DSB->value() + 10); - emit modified(); + if (!isLocked()) { + model->frsky.varioMin = round(ui->varioLimitMin_DSB->value() + 10); + emit modified(); + } } void TelemetryPanel::on_varioLimitMax_DSB_editingFinished() { - model->frsky.varioMax = round(ui->varioLimitMax_DSB->value() - 10); - emit modified(); + if (!isLocked()) { + model->frsky.varioMax = round(ui->varioLimitMax_DSB->value() - 10); + emit modified(); + } } void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() { - if (!lock) { + if (!isLocked()) { if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) { ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value()); } @@ -945,7 +994,7 @@ void TelemetryPanel::on_varioLimitCenterMin_DSB_editingFinished() void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished() { - if (!lock) { + if (!isLocked()) { if (ui->varioLimitCenterMin_DSB->value() > ui->varioLimitCenterMax_DSB->value()) { ui->varioLimitCenterMax_DSB->setValue(ui->varioLimitCenterMin_DSB->value()); } @@ -956,21 +1005,27 @@ void TelemetryPanel::on_varioLimitCenterMax_DSB_editingFinished() void TelemetryPanel::on_fasOffset_DSB_editingFinished() { - model->frsky.fasOffset = ui->fasOffset_DSB->value() * 10; - emit modified(); + if (!isLocked()) { + model->frsky.fasOffset = ui->fasOffset_DSB->value() * 10; + emit modified(); + } } void TelemetryPanel::on_mahCount_SB_editingFinished() { - model->frsky.storedMah = ui->mahCount_SB->value(); - emit modified(); + if (!isLocked()) { + model->frsky.storedMah = ui->mahCount_SB->value(); + emit modified(); + } } void TelemetryPanel::on_mahCount_ChkB_toggled(bool checked) { - model->frsky.mAhPersistent = checked; - ui->mahCount_SB->setDisabled(!checked); - emit modified(); + if (!isLocked()) { + model->frsky.mAhPersistent = checked; + ui->mahCount_SB->setDisabled(!checked); + emit modified(); + } } void TelemetryPanel::on_clearAllSensors() @@ -980,9 +1035,7 @@ void TelemetryPanel::on_clearAllSensors() model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_CLEAR, i); } - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } void TelemetryPanel::on_insertSensor(int selectedIndex) @@ -990,10 +1043,7 @@ void TelemetryPanel::on_insertSensor(int selectedIndex) memmove(&model->sensorData[selectedIndex + 1], &model->sensorData[selectedIndex], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData)); model->sensorData[selectedIndex].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, 1); - - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } void TelemetryPanel::on_deleteSensor(int selectedIndex) @@ -1004,10 +1054,7 @@ void TelemetryPanel::on_deleteSensor(int selectedIndex) memmove(&model->sensorData[selectedIndex], &model->sensorData[selectedIndex + 1], (CPN_MAX_SENSORS - (selectedIndex + 1)) * sizeof(SensorData)); model->sensorData[CPN_MAX_SENSORS - 1].clear(); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SHIFT, selectedIndex, 0, -1); - - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } void TelemetryPanel::on_moveUpSensor(int selectedIndex) @@ -1029,20 +1076,34 @@ void TelemetryPanel::swapData(int idx1, int idx2) memcpy(sd2, sd1, sizeof(SensorData)); memcpy(sd1, &sdtmp, sizeof(SensorData)); model->updateAllReferences(ModelData::REF_UPD_TYPE_SENSOR, ModelData::REF_UPD_ACT_SWAP, idx1, idx2); - updateItemModels(); - update(); - emit modified(); + on_dataModifiedSensor(); } } void TelemetryPanel::on_dataModifiedSensor() { - updateItemModels(); - update(); + sharedItemModels->update(AbstractItemModel::IMUE_TeleSensors); emit modified(); } -void TelemetryPanel::updateItemModels() +void TelemetryPanel::connectItemModelEvents(const int id) { - commonItemModels->update(CommonItemModels::RMO_TELEMETRY_SENSORS); + FilteredItemModel * itemModel = panelFilteredItemModels->getItemModel(id); + connect(itemModel, &FilteredItemModel::aboutToBeUpdated, this, &TelemetryPanel::onItemModelAboutToBeUpdated); + connect(itemModel, &FilteredItemModel::updateComplete, this, &TelemetryPanel::onItemModelUpdateComplete); +} + +void TelemetryPanel::onItemModelAboutToBeUpdated() +{ + lock = true; + modelsUpdateCnt++; +} + +void TelemetryPanel::onItemModelUpdateComplete() +{ + modelsUpdateCnt--; + if (modelsUpdateCnt < 1) { + update(); + lock = false; + } } diff --git a/companion/src/modeledit/telemetry.h b/companion/src/modeledit/telemetry.h index 9719c7df6..224f88020 100644 --- a/companion/src/modeledit/telemetry.h +++ b/companion/src/modeledit/telemetry.h @@ -23,12 +23,11 @@ #include "modeledit.h" #include "eeprominterface.h" +#include "filtereditemmodels.h" -constexpr char MIMETYPE_TELE_SENSOR[] = "application/x-companion-tele-sensor"; +constexpr char MIMETYPE_TELE_SENSOR[] {"application/x-companion-tele-sensor"}; class AutoComboBox; -class CommonItemModels; -class RawItemFilteredModel; class TimerEdit; namespace Ui { @@ -42,7 +41,8 @@ class TelemetryCustomScreen: public ModelPanel Q_OBJECT public: - TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, RawItemFilteredModel * rawSourceModel); + TelemetryCustomScreen(QWidget *parent, ModelData & model, FrSkyScreenData & screen, GeneralSettings & generalSettings, Firmware * firmware, + const bool & parentLock, FilteredItemModelFactory * panelFilteredItemModels); ~TelemetryCustomScreen(); void update(); @@ -54,8 +54,8 @@ class TelemetryCustomScreen: public ModelPanel void barMinChanged(double value); void barMaxChanged(double value); void barTimeChanged(); - void onModelDataAboutToBeUpdated(); - void onModelDataUpdateComplete(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: void updateBar(int line); @@ -67,6 +67,11 @@ class TelemetryCustomScreen: public ModelPanel QDoubleSpinBox * maxSB[4]; TimerEdit * minTime[4]; TimerEdit * maxTime[4]; + int modelsUpdateCnt; + const bool &parentLock; + + inline bool isLocked() { return lock | parentLock; } + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class TelemetrySensorPanel: public ModelPanel @@ -74,7 +79,9 @@ class TelemetrySensorPanel: public ModelPanel Q_OBJECT public: - TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware); + TelemetrySensorPanel(QWidget *parent, SensorData & sensor, int sensorIndex, int sensorCapability, ModelData & model, + GeneralSettings & generalSettings, Firmware * firmware, const bool & parentLock, + FilteredItemModelFactory * panelFilteredItemModels); ~TelemetrySensorPanel(); void update(); @@ -86,7 +93,6 @@ class TelemetrySensorPanel: public ModelPanel void moveUpSensor(int index); void moveDownSensor(int index); - protected slots: void on_name_editingFinished(); void on_type_currentIndexChanged(int index); @@ -104,20 +110,23 @@ class TelemetrySensorPanel: public ModelPanel void cmDelete(); void cmMoveUp(); void cmMoveDown(); - - protected: - void updateSourcesComboBox(AutoComboBox * cb, bool negative); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::TelemetrySensor * ui; SensorData & sensor; - bool lock = false; int sensorIndex = 0; int selectedIndex = 0; int sensorCapability; bool insertAllowed() const; bool moveDownAllowed() const; bool moveUpAllowed() const; + int modelsUpdateCnt; + const bool &parentLock; + + inline bool isLocked() { return lock | parentLock; } + void connectItemModelEvents(const FilteredItemModel * itemModel); }; class TelemetryPanel : public ModelPanel @@ -125,7 +134,8 @@ class TelemetryPanel : public ModelPanel Q_OBJECT public: - TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, CommonItemModels * commonItemModels); + TelemetryPanel(QWidget *parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware, + CompoundItemModelFactory * sharedItemModels); virtual ~TelemetryPanel(); virtual void update(); @@ -152,22 +162,24 @@ class TelemetryPanel : public ModelPanel void on_moveUpSensor(int index); void on_moveDownSensor(int index); void on_dataModifiedSensor(); + void onItemModelAboutToBeUpdated(); + void onItemModelUpdateComplete(); private: Ui::Telemetry *ui; - TelemetryCustomScreen * telemetryCustomScreens[4]; - TelemetrySensorPanel * sensorPanels[CPN_MAX_SENSORS]; + TelemetryCustomScreen *telemetryCustomScreens[4]; + TelemetrySensorPanel *sensorPanels[CPN_MAX_SENSORS]; int sensorCapability; - CommonItemModels * commonItemModels; - RawItemFilteredModel * rawSourceFilteredModel; + CompoundItemModelFactory *sharedItemModels; + CompoundItemModelFactory *panelItemModels; + FilteredItemModelFactory *panelFilteredItemModels; + int modelsUpdateCnt; void setup(); void telBarUpdate(); - void populateVoltsSource(); - void populateCurrentSource(); - void populateVarioSource(); void swapData(int idx1, int idx2); - void updateItemModels(); + void connectItemModelEvents(const int id); + inline bool isLocked() { return lock; } }; #endif // _TELEMETRY_H_ diff --git a/companion/src/shared/autocombobox.h b/companion/src/shared/autocombobox.h index fcb1845ac..158352f97 100644 --- a/companion/src/shared/autocombobox.h +++ b/companion/src/shared/autocombobox.h @@ -37,30 +37,37 @@ class AutoComboBox: public QComboBox void clear() { - lock = true; - QComboBox::clear(); - next = 0; - lock = false; + if (!hasModel) { + lock = true; + QComboBox::clear(); + next = 0; + lock = false; + } } virtual void insertItems(int index, const QStringList & items) { - foreach(QString item, items) { - addItem(item); + if (!hasModel) { + foreach(QString item, items) { + addItem(item); + } } } virtual void addItem(const QString & item) { - addItem(item, next++); + if (!hasModel) + addItem(item, next++); } virtual void addItem(const QString & item, int value) { - lock = true; - QComboBox::addItem(item, value); - lock = false; - updateValue(); + if (!hasModel) { + lock = true; + QComboBox::addItem(item, value); + lock = false; + updateValue(); + } } void setField(unsigned int & field, GenericPanel * panel=nullptr) @@ -77,11 +84,22 @@ class AutoComboBox: public QComboBox updateValue(); } + void setModel(QAbstractItemModel * model) + { + lock = true; + QComboBox::setModel(model); + lock = false; + hasModel = true; + updateValue(); + } + void setAutoIndexes() { - for (int i=0; imodified(); + if (panel && panel->lock) + return; + if (index > -1) { + const int val = itemData(index).toInt(); + if (field && !lock) { + *field = val; + if (panel) + emit panel->modified(); + } + emit currentDataChanged(val); } - emit currentDataChanged(val); } protected: @@ -113,6 +135,7 @@ class AutoComboBox: public QComboBox GenericPanel * panel = nullptr; int next = 0; bool lock = false; + bool hasModel = false; }; #endif // _AUTOCOMBOBOX_H_ diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index 0bcefce62..d3c39d4fe 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -17,6 +17,7 @@ set(simulation_SRCS simulateduiwidgetJumperT16.cpp simulateduiwidgetJumperT18.cpp simulateduiwidgetTX12.cpp + simulateduiwidgetT8.cpp simulateduiwidgetTX16S.cpp simulatorinterface.cpp simulatormainwindow.cpp @@ -45,6 +46,7 @@ set(simulation_UIS simulateduiwidgetJumperT16.ui simulateduiwidgetJumperT18.ui simulateduiwidgetTX12.ui + simulateduiwidgetT8.ui simulateduiwidgetTX16S.ui simulatormainwindow.ui simulatorstartupdialog.ui diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h index 159de1352..aee2c5f87 100644 --- a/companion/src/simulation/simulateduiwidget.h +++ b/companion/src/simulation/simulateduiwidget.h @@ -117,6 +117,7 @@ namespace Ui { class SimulatedUIWidgetJumperT18; class SimulatedUIWidgetTX16S; class SimulatedUIWidgetTX12; + class SimulatedUIWidgetT8; } class SimulatedUIWidget9X: public SimulatedUIWidget @@ -291,6 +292,17 @@ class SimulatedUIWidgetTX12: public SimulatedUIWidget Ui::SimulatedUIWidgetTX12 * ui; }; +class SimulatedUIWidgetT8: public SimulatedUIWidget +{ +Q_OBJECT + +public: + explicit SimulatedUIWidgetT8(SimulatorInterface * simulator, QWidget * parent = nullptr); + virtual ~SimulatedUIWidgetT8(); + +private: + Ui::SimulatedUIWidgetT8 * ui; +}; class SimulatedUIWidgetTX16S: public SimulatedUIWidget { diff --git a/companion/src/simulation/simulateduiwidgetT8.cpp b/companion/src/simulation/simulateduiwidgetT8.cpp new file mode 100644 index 000000000..ed86889d7 --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetT8.cpp @@ -0,0 +1,67 @@ +#include "simulateduiwidget.h" +#include "ui_simulateduiwidgetT8.h" + +// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h + +SimulatedUIWidgetT8::SimulatedUIWidgetT8(SimulatorInterface *simulator, QWidget * parent): + SimulatedUIWidget(simulator, parent), + ui(new Ui::SimulatedUIWidgetT8) +{ + RadioUiAction * act; + + ui->setupUi(this); + + // add actions in order of appearance on the help menu + + act = new RadioUiAction(5, QList() << Qt::Key_Up, SIMU_STR_HLP_KEY_UP, SIMU_STR_HLP_ACT_MDL); + addRadioWidget(ui->rightbuttons->addArea(QRect(25, 40, 35, 20), "T8/right-mdl.png", act)); + + act = new RadioUiAction(6, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_UP); + addRadioWidget(ui->rightbuttons->addArea(QRect(25, 90, 35, 20), "T8/right-up.png", act)); + + act = new RadioUiAction(7, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_DN); + addRadioWidget(ui->rightbuttons->addArea(QRect(25, 135, 35, 20), "T8/right-dn.png", act)); + + act = new RadioUiAction(1, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ENT); + addRadioWidget(ui->rightbuttons->addArea(QRect(25, 180, 35, 20), "T8/right-ent.png", act)); + + act = new RadioUiAction(4, QList() << Qt::Key_Left, SIMU_STR_HLP_KEY_LFT, SIMU_STR_HLP_ACT_SYS); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 45, 35, 20), "T8/left-sys.png", act)); + + act = new RadioUiAction(0, QList() << Qt::Key_Down << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 85, 35, 20), "T8/left-rtn.png", act)); + + act = new RadioUiAction(3, QList() << Qt::Key_PageDown, SIMU_STR_HLP_KEY_PGDN, SIMU_STR_HLP_ACT_PGDN); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 135, 35, 20), "T8/left-pagedn.png", act)); + + act = new RadioUiAction(2, QList() << Qt::Key_PageUp, SIMU_STR_HLP_KEY_PGUP, SIMU_STR_HLP_ACT_PGUP); + addRadioWidget(ui->leftbuttons->addArea(QRect(60, 180, 35, 20), "T8/left-pageup.png", act)); + + + m_backlightColors << QColor(215, 243, 255); // X7 Blue + m_backlightColors << QColor(166,247,159); + m_backlightColors << QColor(247,159,166); + m_backlightColors << QColor(255,195,151); + m_backlightColors << QColor(247,242,159); + + setLcd(ui->lcd); + + QString css = "#radioUiWidget {" + "background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1," + "stop:0 rgba(255, 255, 255, 255)," + "stop:0.757062 rgba(241, 238, 238, 255)," + "stop:1 rgba(247, 245, 245, 255));" + "}"; + + QTimer * tim = new QTimer(this); + tim->setSingleShot(true); + connect(tim, &QTimer::timeout, [this, css]() { + emit customStyleRequest(css); + }); + tim->start(100); +} + +SimulatedUIWidgetT8::~SimulatedUIWidgetT8() +{ + delete ui; +} diff --git a/companion/src/simulation/simulateduiwidgetT8.ui b/companion/src/simulation/simulateduiwidgetT8.ui new file mode 100644 index 000000000..6370888ea --- /dev/null +++ b/companion/src/simulation/simulateduiwidgetT8.ui @@ -0,0 +1,258 @@ + + + SimulatedUIWidgetT8 + + + + 0 + 0 + 480 + 300 + + + + + 0 + 0 + + + + + 480 + 300 + + + + + 480 + 300 + + + + Radiomaster T8 Simulator + + + background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(255, 255, 255, 255), stop:0.757062 rgba(241, 238, 238, 255), stop:1 rgba(247, 245, 245, 255)); + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 113 + 280 + + + + + 113 + 280 + + + + background:url(:/images/simulator/T8/left.png); + + + + + + + + 0 + 0 + + + + + 254 + 158 + + + + + 254 + 158 + + + + background-color: rgb(215, 243, 255); + + + + + + + + 0 + 0 + + + + + 113 + 280 + + + + + 113 + 280 + + + + background:url(:/images/simulator/T8/right.png) + + + + + + + + 0 + 0 + + + + + 254 + 35 + + + + + 254 + 35 + + + + background:url(:/images/simulator/T8/top.png) + + + + + + + + 0 + 0 + + + + + 254 + 113 + + + + + 254 + 113 + + + + background:url(:/images/simulator/T8/bottom.png) + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 16777215 + 12 + + + + + 0 + 12 + + + + background-color: rgb(255, 255, 255); + + + + + + + + + + + 0 + 0 + + + + + 0 + 10 + + + + + 16777215 + 10 + + + + background-color: rgb(247, 245, 245); + + + + + + + + + + + LcdWidget + QWidget +
lcdwidget.h
+ 1 +
+ + ButtonsWidget + QWidget +
buttonswidget.h
+ 1 +
+
+ + +
diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp index 6692b0ebb..b4160a579 100644 --- a/companion/src/simulation/simulatorwidget.cpp +++ b/companion/src/simulation/simulatorwidget.cpp @@ -103,6 +103,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato case Board::BOARD_RADIOMASTER_TX12: radioUiWidget = new SimulatedUIWidgetTX12(simulator, this); break; + case Board::BOARD_RADIOMASTER_T8: + radioUiWidget = new SimulatedUIWidgetT8(simulator, this); + break; case Board::BOARD_RADIOMASTER_TX16S: radioUiWidget = new SimulatedUIWidgetTX16S(simulator, this); break; diff --git a/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua b/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua index 0f9b1a20f..b19bb5ee2 100644 --- a/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua +++ b/radio/sdcard/horus/SCRIPTS/TOOLS/crossfire.lua @@ -30,6 +30,11 @@ local function run(event) return 2 end + if crossfireTelemetryPush() == nil then + error("Crossfire not available!") + return 2 + end + chdir("/SCRIPTS/TOOLS/CROSSFIRE") return "crossfire.lua" end diff --git a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua index debf9056d..3e8a6930a 100644 --- a/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua +++ b/radio/sdcard/taranis-x7/SCRIPTS/TOOLS/crossfire.lua @@ -30,6 +30,11 @@ local function run(event) return 2 end + if crossfireTelemetryPush() == nil then + error("Crossfire not available!") + return 2 + end + chdir("/SCRIPTS/TOOLS/CROSSFIRE") return "crossfire.lua" end diff --git a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua index 0f9b1a20f..b19bb5ee2 100644 --- a/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua +++ b/radio/sdcard/taranis-x9/SCRIPTS/TOOLS/crossfire.lua @@ -30,6 +30,11 @@ local function run(event) return 2 end + if crossfireTelemetryPush() == nil then + error("Crossfire not available!") + return 2 + end + chdir("/SCRIPTS/TOOLS/CROSSFIRE") return "crossfire.lua" end diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index 47a1fed2a..b3a8c1fdb 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -345,6 +345,10 @@ if(RADIOMASTER_RELEASE) add_definitions(-DRADIOMASTER_RELEASE) endif() +if(RADIOMASTER_RTF_RELEASE) + add_definitions(-DRADIOMASTER_RTF_RELEASE) +endif() + if(TBS_RELEASE) add_definitions(-DTBS_RELEASE) endif() diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index dcdd6e5c8..005fbec56 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -208,7 +208,11 @@ enum TrainerMode { }; #endif -#if defined(RADIO_T16) && !defined(INTERNAL_MODULE_MULTI) +#define TRAINER_MODE_MIN() TRAINER_MODE_MASTER_TRAINER_JACK + +#if !defined(HARDWARE_EXTERNAL_MODULE) + #define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE +#elif defined(RADIO_T16) && !defined(INTERNAL_MODULE_MULTI) #if defined(BLUETOOTH) #define TRAINER_MODE_MAX() TRAINER_MODE_SLAVE_BLUETOOTH #else diff --git a/radio/src/gui/128x64/lcd.h b/radio/src/gui/128x64/lcd.h index c6b32dd3d..3a94f2365 100644 --- a/radio/src/gui/128x64/lcd.h +++ b/radio/src/gui/128x64/lcd.h @@ -181,8 +181,9 @@ uint8_t * lcdLoadBitmap(uint8_t * dest, const char * filename, uint8_t width, ui #if defined(BOOT) #define BLINK_ON_PHASE (0) #else - #define BLINK_ON_PHASE (g_blinkTmr10ms & (1<<6)) #define SLOW_BLINK_ON_PHASE (g_blinkTmr10ms & (1<<7)) + #define BLINK_ON_PHASE (g_blinkTmr10ms & (1<<6)) + #define FAST_BLINK_ON_PHASE (g_blinkTmr10ms & (1<<4)) #endif inline display_t getPixel(uint8_t x, uint8_t y) diff --git a/radio/src/gui/128x64/model_curve_edit.cpp b/radio/src/gui/128x64/model_curve_edit.cpp index 66f153b4d..c2168ed02 100644 --- a/radio/src/gui/128x64/model_curve_edit.cpp +++ b/radio/src/gui/128x64/model_curve_edit.cpp @@ -165,7 +165,7 @@ void menuModelCurveOne(event_t event) } break; -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_MDL) case EVT_KEY_FIRST(KEY_MODEL): pushMenu(menuChannelsView); killEvents(event); diff --git a/radio/src/gui/128x64/model_input_edit.cpp b/radio/src/gui/128x64/model_input_edit.cpp index 840e41a82..ce76e0a89 100644 --- a/radio/src/gui/128x64/model_input_edit.cpp +++ b/radio/src/gui/128x64/model_input_edit.cpp @@ -49,7 +49,7 @@ enum ExposFields { void menuModelExpoOne(event_t event) { -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_MDL) if (event == EVT_KEY_FIRST(KEY_MODEL)) { pushMenu(menuChannelsView); killEvents(event); diff --git a/radio/src/gui/128x64/model_mix_edit.cpp b/radio/src/gui/128x64/model_mix_edit.cpp index 92e10ee69..281256f46 100644 --- a/radio/src/gui/128x64/model_mix_edit.cpp +++ b/radio/src/gui/128x64/model_mix_edit.cpp @@ -85,7 +85,7 @@ void drawOffsetBar(uint8_t x, uint8_t y, MixData * md) void menuModelMixOne(event_t event) { -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_MDL) if (event == EVT_KEY_FIRST(KEY_MODEL)) { pushMenu(menuChannelsView); killEvents(event); diff --git a/radio/src/gui/128x64/model_select.cpp b/radio/src/gui/128x64/model_select.cpp index cf6410d63..bcf04117d 100644 --- a/radio/src/gui/128x64/model_select.cpp +++ b/radio/src/gui/128x64/model_select.cpp @@ -203,7 +203,7 @@ void menuModelSelect(event_t event) } break; -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEDN) case EVT_KEY_FIRST(KEY_PAGEUP): chainMenu(menuTabModel[DIM(menuTabModel)-1]); killEvents(event); @@ -212,7 +212,7 @@ void menuModelSelect(event_t event) case EVT_KEY_FIRST(KEY_PAGEDN): chainMenu(menuModelSetup); break; -#elif defined(NAVIGATION_X7) +#elif defined(KEYS_GPIO_REG_PAGE) case EVT_KEY_LONG(KEY_PAGE): chainMenu(menuTabModel[DIM(menuTabModel)-1]); killEvents(event); @@ -244,7 +244,7 @@ void menuModelSelect(event_t event) #endif #endif -#if defined(NAVIGATION_X7) +#if defined(ROTARY_ENCODER) && defined(NAVIGATION_X7) case EVT_ROTARY_LEFT: case EVT_ROTARY_RIGHT: #endif diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 41af5720f..468597b29 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -111,7 +111,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_2, ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_3, #endif - +#if defined(HARDWARE_EXTERNAL_MODULE) ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL, ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE, #if defined(MULTIMODULE) @@ -156,6 +156,7 @@ enum MenuModelSetupItems { ITEM_MODEL_SETUP_EXTRA_MODULE_CHANNELS, ITEM_MODEL_SETUP_EXTRA_MODULE_BIND, #endif +#endif #if defined(PCBTARANIS) ITEM_MODEL_SETUP_TRAINER_LABEL, @@ -183,13 +184,16 @@ enum MenuModelSetupItems { #define REGISTRATION_ID_ROWS #endif -#if defined(HARDWARE_INTERNAL_MODULE) +#if defined(HARDWARE_INTERNAL_MODULE) && defined(HARDWARE_EXTERNAL_MODULE) #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE) #define CURRENT_RECEIVER_EDITED(k) (k - (k >= ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL ? ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_1 : ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1)) #elif defined(PCBSKY9X) - #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_SETUP_EXTRA_MODULE_LABEL ? EXTRA_MODULE : EXTERNAL_MODULE) + #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_SETUP_EXTRA_MODULE_LABEL ? EXTRA_MODULE : EXTERNAL_MODULE) +#elif defined(HARDWARE_INTERNAL_MODULE) + #define CURRENT_MODULE_EDITED(k) (INTERNAL_MODULE) + #define CURRENT_RECEIVER_EDITED(k) (k - ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_RECEIVER_1) #else - #define CURRENT_MODULE_EDITED(k) (EXTERNAL_MODULE) + #define CURRENT_MODULE_EDITED(k) (EXTERNAL_MODULE) #define CURRENT_RECEIVER_EDITED(k) (k - ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_RECEIVER_1) #endif @@ -335,6 +339,32 @@ void onBluetoothConnectMenu(const char * result) #define INTERNAL_MODULE_ROWS #endif +#if defined(HARDWARE_EXTERNAL_MODULE) + #define EXTERNAL_MODULE_ROWS \ + LABEL(ExternalModule), \ + MODULE_TYPE_ROWS(EXTERNAL_MODULE), \ + MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE) /* PROTOCOL */ \ + MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) /* SUBTYPE */ \ + MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) \ + AFHDS3_PROTOCOL_ROW(EXTERNAL_MODULE) \ + AFHDS3_MODE_ROWS(EXTERNAL_MODULE) \ + MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), \ + IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), /* line reused for PPM: PPM settings */ \ + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), /* RxNum */ \ + AFHDS3_MODULE_ROWS(EXTERNAL_MODULE) \ + MODULE_POWER_ROW(EXTERNAL_MODULE), \ + IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), \ + MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) \ + FAILSAFE_ROWS(EXTERNAL_MODULE), /* ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE */ \ + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), /* Range check and Register buttons */ \ + IF_PXX2_MODULE(EXTERNAL_MODULE, 0), /* Module options */ \ + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), /* Receiver 1 */ \ + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), /* Receiver 2 */ \ + IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), /* Receiver 3 */ +#else + #define EXTERNAL_MODULE_ROWS +#endif + void menuModelSetup(event_t event) { int8_t old_editMode = s_editMode; @@ -370,26 +400,7 @@ void menuModelSetup(event_t event) INTERNAL_MODULE_ROWS - LABEL(ExternalModule), - MODULE_TYPE_ROWS(EXTERNAL_MODULE), - MULTIMODULE_TYPE_ROWS(EXTERNAL_MODULE) // PROTOCOL - MULTIMODULE_SUBTYPE_ROWS(EXTERNAL_MODULE) // SUBTYPE - MULTIMODULE_STATUS_ROWS(EXTERNAL_MODULE) - AFHDS3_PROTOCOL_ROW(EXTERNAL_MODULE) - AFHDS3_MODE_ROWS(EXTERNAL_MODULE) - MODULE_CHANNELS_ROWS(EXTERNAL_MODULE), - IF_NOT_ACCESS_MODULE_RF(EXTERNAL_MODULE, MODULE_BIND_ROWS(EXTERNAL_MODULE)), // line reused for PPM: PPM settings - IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // RxNum - AFHDS3_MODULE_ROWS(EXTERNAL_MODULE) - MODULE_POWER_ROW(EXTERNAL_MODULE), - IF_NOT_PXX2_MODULE(EXTERNAL_MODULE, MODULE_OPTION_ROW(EXTERNAL_MODULE)), - MULTIMODULE_MODULE_ROWS(EXTERNAL_MODULE) - FAILSAFE_ROWS(EXTERNAL_MODULE), //ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE - IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 1), // Range check and Register buttons - IF_PXX2_MODULE(EXTERNAL_MODULE, 0), // Module options - IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 1 - IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 2 - IF_ACCESS_MODULE_RF(EXTERNAL_MODULE, 0), // Receiver 3 + EXTERNAL_MODULE_ROWS TRAINER_ROWS }); @@ -857,7 +868,7 @@ void menuModelSetup(event_t event) #if !defined(INTERNAL_MODULE_MULTI) case ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE: { - lcdDrawTextAlignedLeft(y, INDENT TR_MODE); + lcdDrawText(INDENT_WIDTH, y, STR_MODE); #if defined(INTERNAL_MODULE_PXX1) lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_INTERNAL_MODULE_PROTOCOLS, g_model.moduleData[INTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0); if (isModuleXJT(INTERNAL_MODULE)) @@ -912,14 +923,18 @@ void menuModelSetup(event_t event) break; #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_LABEL: lcdDrawTextAlignedLeft(y, STR_EXTERNALRF); break; +#endif #if defined(INTERNAL_MODULE_MULTI) case ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_TYPE: +#endif lcdDrawTextAlignedLeft(y, INDENT TR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_EXTERNAL_MODULE_PROTOCOLS, moduleIdx == EXTERNAL_MODULE ? reusableBuffer.moduleSetup.newType : g_model.moduleData[moduleIdx].type, menuHorizontalPosition==0 ? attr : 0); if (isModuleXJT(moduleIdx)) @@ -1013,7 +1028,9 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_PROTOCOL: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PROTOCOL: +#endif { lcdDrawTextAlignedLeft(y, TR_TYPE); int multi_rfProto = g_model.moduleData[moduleIdx].getMultiProtocol(); @@ -1052,7 +1069,9 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_SUBTYPE: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SUBTYPE: +#endif { lcdDrawTextAlignedLeft(y, STR_SUBTYPE); lcdDrawMultiSubProtocolString(MODEL_SETUP_2ND_COLUMN, y, moduleIdx, g_model.moduleData[moduleIdx].subType, attr); @@ -1073,7 +1092,7 @@ void menuModelSetup(event_t event) #if defined(AFHDS3) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AFHDS_PROTOCOL: - lcdDrawTextAlignedLeft(y, TR_PROTO); + lcdDrawText(INDENT_WIDTH, y, STR_PROTOCOL); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_AFHDS3_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].subType, attr); if (attr && s_editMode > 0 && menuHorizontalPosition == 0) { CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].subType, AFHDS_SUBTYPE_FIRST, AFHDS_SUBTYPE_LAST); @@ -1095,7 +1114,7 @@ void menuModelSetup(event_t event) lcdDrawTextAlignedLeft(y, INDENT TR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr); if (attr) { - g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable); + g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, TRAINER_MODE_MIN(), TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable); #if defined(BLUETOOTH) if (checkIncDec_Ret) { bluetooth.state = BLUETOOTH_STATE_OFF; @@ -1182,7 +1201,9 @@ void menuModelSetup(event_t event) #if defined(PCBSKY9X) case ITEM_MODEL_SETUP_EXTRA_MODULE_CHANNELS: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_CHANNELS: +#endif { ModuleData & moduleData = g_model.moduleData[moduleIdx]; lcdDrawTextAlignedLeft(y, STR_CHANNELRANGE); @@ -1308,7 +1329,9 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE: +#endif { ModuleData & moduleData = g_model.moduleData[moduleIdx]; if (isModulePPM(moduleIdx)) { @@ -1462,7 +1485,9 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_FAILSAFE: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_FAILSAFE: +#endif { ModuleData &moduleData = g_model.moduleData[moduleIdx]; lcdDrawTextAlignedLeft(y, STR_FAILSAFE); @@ -1523,7 +1548,9 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_OPTIONS: +#endif { #if defined(MULTIMODULE) if (MULTIMODULE_PROTOCOL_KNOWN(moduleIdx)) { @@ -1602,7 +1629,9 @@ void menuModelSetup(event_t event) #if defined(INTERNAL_MODULE_MULTI) case ITEM_MODEL_SETUP_INTERNAL_MODULE_POWER: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_POWER: +#endif { auto & module = g_model.moduleData[moduleIdx]; // Lite FCC / Lite FLEX / Lite Pro Flex @@ -1687,7 +1716,9 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_AUTOBIND: +#endif if (g_model.moduleData[moduleIdx].getMultiProtocol() == MODULE_SUBTYPE_MULTI_DSM2) { int8_t value = (g_model.moduleData[moduleIdx].multi.optionValue & 0x02) >> 1; lcdDrawText(INDENT_WIDTH, y, STR_MULTI_SERVOFREQ); @@ -1708,13 +1739,17 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_TELEM: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_TELEM: +#endif g_model.moduleData[moduleIdx].multi.disableTelemetry = editCheckBox(g_model.moduleData[moduleIdx].multi.disableTelemetry, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_TELEM, attr, event); break; #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_DISABLE_MAPPING: #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_DISABLE_MAPPING: +#endif g_model.moduleData[moduleIdx].multi.disableMapping = editCheckBox(g_model.moduleData[moduleIdx].multi.disableMapping, MODEL_SETUP_2ND_COLUMN, y, INDENT TR_DISABLE_CH_MAP, attr, event); break; #endif @@ -1739,7 +1774,10 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS: #endif - case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: { +#if defined(HARDWARE_EXTERNAL_MODULE) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_STATUS: +#endif + { lcdDrawTextAlignedLeft(y, STR_MODULE_STATUS); char statusText[64]; @@ -1750,7 +1788,10 @@ void menuModelSetup(event_t event) #if defined(HARDWARE_INTERNAL_MODULE) case ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS: #endif - case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: { +#if defined(HARDWARE_EXTERNAL_MODULE) + case ITEM_MODEL_SETUP_EXTERNAL_MODULE_SYNCSTATUS: +#endif + { lcdDrawTextAlignedLeft(y, STR_MODULE_SYNC); char statusText[64]; getModuleSyncStatusString(moduleIdx, statusText); @@ -1848,11 +1889,13 @@ void menuModelSetup(event_t event) checkModelIdUnique(g_eeGeneral.currModel, EXTRA_MODULE); break; #endif +#if defined(HARDWARE_EXTERNAL_MODULE) case ITEM_MODEL_SETUP_EXTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE: case ITEM_MODEL_SETUP_EXTERNAL_MODULE_PXX2_MODEL_NUM: if (menuHorizontalPosition == 0) checkModelIdUnique(g_eeGeneral.currModel, EXTERNAL_MODULE); break; +#endif } } } diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp index a3d058c3e..803ff7eb7 100644 --- a/radio/src/gui/128x64/radio_diagkeys.cpp +++ b/radio/src/gui/128x64/radio_diagkeys.cpp @@ -49,10 +49,15 @@ void menuRadioDiagKeys(event_t event) displayKeyState(i&1? 20*FW : 18*FW, y, TRM_BASE+i); } - if (i <= KEY_MAX) { - y = MENU_HEADER_HEIGHT + 1 + FH*i; + if (i == 7) { + y = MENU_HEADER_HEIGHT + 1 + FH * 6; + lcdDrawTextAtIndex(8, y, STR_VKEYS, i, 0); + displayKeyState(lcdNextPos + 10, y, i); + } + else if (i <= KEY_MAX) { + y = MENU_HEADER_HEIGHT + 1 + FH * i; lcdDrawTextAtIndex(0, y, STR_VKEYS, i, 0); - displayKeyState(5*FW+2, y, i); + displayKeyState(5 * FW + 2, y, i); } #if defined(PCBSKY9X) diff --git a/radio/src/gui/128x64/radio_setup.cpp b/radio/src/gui/128x64/radio_setup.cpp index 6579f1523..26b80cb0f 100644 --- a/radio/src/gui/128x64/radio_setup.cpp +++ b/radio/src/gui/128x64/radio_setup.cpp @@ -79,13 +79,13 @@ enum { ITEM_RADIO_SETUP_MEMORY_WARNING, ITEM_RADIO_SETUP_ALARM_WARNING, ITEM_RADIO_SETUP_RSSI_POWEROFF_ALARM, - ITEM_RADIO_SETUP_BACKLIGHT_LABEL, - ITEM_RADIO_SETUP_BACKLIGHT_MODE, - ITEM_RADIO_SETUP_BACKLIGHT_DELAY, - ITEM_RADIO_SETUP_BRIGHTNESS, + CASE_BACKLIGHT(ITEM_RADIO_SETUP_BACKLIGHT_LABEL) + CASE_BACKLIGHT(ITEM_RADIO_SETUP_BACKLIGHT_MODE) + CASE_BACKLIGHT(ITEM_RADIO_SETUP_BACKLIGHT_DELAY) + CASE_BACKLIGHT(ITEM_RADIO_SETUP_BRIGHTNESS) CASE_PWM_BACKLIGHT(ITEM_RADIO_SETUP_BACKLIGHT_BRIGHTNESS_OFF) CASE_PWM_BACKLIGHT(ITEM_RADIO_SETUP_BACKLIGHT_BRIGHTNESS_ON) - ITEM_RADIO_SETUP_FLASH_BEEP, + CASE_BACKLIGHT(ITEM_RADIO_SETUP_FLASH_BEEP) CASE_SPLASH_PARAM(ITEM_RADIO_SETUP_DISABLE_SPLASH) CASE_PWR_BUTTON_PRESS(ITEM_RADIO_SETUP_PWR_ON_SPEED) CASE_PWR_BUTTON_PRESS(ITEM_RADIO_SETUP_PWR_OFF_SPEED) @@ -152,10 +152,14 @@ void menuRadioSetup(event_t event) CASE_GYRO(0) CASE_GYRO(0) 0, LABEL(ALARMS), 0, CASE_CAPACITY(0) - 0, 0, 0, 0, - LABEL(BACKLIGHT), 0, 0, 0, CASE_PWM_BACKLIGHT(0) + 0, 0, 0, 0, /* ITEM_RADIO_SETUP_INACTIVITY_ALARM ITEM_RADIO_SETUP_MEMORY_WARNING ITEM_RADIO_SETUP_ALARM_WARNING ITEM_RADIO_SETUP_RSSI_POWEROFF_ALARM */ + CASE_BACKLIGHT(LABEL(BACKLIGHT)) + CASE_BACKLIGHT(0) + CASE_BACKLIGHT(0) + CASE_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) - 0, + CASE_PWM_BACKLIGHT(0) + CASE_BACKLIGHT(0) CASE_SPLASH_PARAM(0) CASE_PWR_BUTTON_PRESS(0) CASE_PWR_BUTTON_PRESS(0) @@ -450,6 +454,7 @@ void menuRadioSetup(event_t event) if(attr) g_eeGeneral.inactivityTimer = checkIncDec(event, g_eeGeneral.inactivityTimer, 0, 250, EE_GENERAL); //0..250minutes break; +#if defined(BACKLIGHT_GPIO) case ITEM_RADIO_SETUP_BACKLIGHT_LABEL: lcdDrawTextAlignedLeft(y, STR_BACKLIGHT_LABEL); break; @@ -478,6 +483,7 @@ void menuRadioSetup(event_t event) g_eeGeneral.backlightBright = 100 - b; } break; +#endif #if defined(PWM_BACKLIGHT) case ITEM_RADIO_SETUP_BACKLIGHT_BRIGHTNESS_OFF: diff --git a/radio/src/gui/128x64/view_about.cpp b/radio/src/gui/128x64/view_about.cpp index 02e8e4508..b168f91fb 100644 --- a/radio/src/gui/128x64/view_about.cpp +++ b/radio/src/gui/128x64/view_about.cpp @@ -42,7 +42,7 @@ enum AboutScreens { #define ABOUT_X 2 #define ABOUT_INDENT 4 -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEDN) #define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_PAGEUP) #define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_PAGEDN) #elif defined(NAVIGATION_X7) diff --git a/radio/src/gui/128x64/view_channels.cpp b/radio/src/gui/128x64/view_channels.cpp index f71d833c1..ffb4d9b33 100644 --- a/radio/src/gui/128x64/view_channels.cpp +++ b/radio/src/gui/128x64/view_channels.cpp @@ -26,7 +26,12 @@ constexpr coord_t CHANNEL_GAUGE_OFFSET = CHANNEL_VALUE_OFFSET; constexpr coord_t CHANNEL_BAR_WIDTH = 70; constexpr coord_t CHANNEL_PROPERTIES_OFFSET = CHANNEL_GAUGE_OFFSET + CHANNEL_BAR_WIDTH + 2; -#if defined(NAVIGATION_X7_TX12) +#if defined(RADIO_T8) +#define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_PAGEUP) +#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_PAGEDN) +#define EVT_KEY_NEXT_PAGE EVT_KEY_BREAK(KEY_PLUS) +#define EVT_KEY_PREVIOUS_PAGE EVT_KEY_BREAK(KEY_MINUS) +#elif defined(NAVIGATION_X7_TX12) #define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_PAGEUP) #define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_PAGEDN) #define EVT_KEY_NEXT_PAGE EVT_ROTARY_RIGHT diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp index ee486269b..b3cea8de7 100644 --- a/radio/src/gui/128x64/view_main.cpp +++ b/radio/src/gui/128x64/view_main.cpp @@ -93,8 +93,9 @@ void doMainScreenGraphics() if (g_model.throttleReversed && CONVERT_MODE(2) == THR_STICK) calibStickVert = -calibStickVert; drawStick(RBOX_CENTERX, calibratedAnalogs[CONVERT_MODE(3)], calibStickVert); - +#if defined(HARDWARE_POT1) drawPotsBars(); +#endif } void displayTrims(uint8_t phase) @@ -213,7 +214,16 @@ void displayVoltageOrAlarm() #define displayVoltageOrAlarm() displayBattVoltage() #endif -#if defined(NAVIGATION_X7_TX12) +#if defined(RADIO_T8) +#define EVT_KEY_CONTEXT_MENU EVT_KEY_LONG(KEY_ENTER) +#define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_PAGEUP) +#define EVT_KEY_NEXT_VIEW EVT_KEY_FIRST(KEY_PAGEDN) +#define EVT_KEY_NEXT_PAGE EVT_KEY_FIRST(KEY_PLUS) +#define EVT_KEY_PREVIOUS_PAGE EVT_KEY_FIRST(KEY_MINUS) +#define EVT_KEY_MODEL_MENU EVT_KEY_LONG(KEY_MODEL) +#define EVT_KEY_GENERAL_MENU EVT_KEY_LONG(KEY_SYS) +#define EVT_KEY_TELEMETRY EVT_KEY_LONG(KEY_PAGEUP) +#elif defined(NAVIGATION_X7_TX12) #define EVT_KEY_CONTEXT_MENU EVT_KEY_LONG(KEY_ENTER) #define EVT_KEY_PREVIOUS_VIEW EVT_KEY_FIRST(KEY_PAGEUP) #define EVT_KEY_NEXT_VIEW EVT_KEY_FIRST(KEY_PAGEDN) @@ -410,6 +420,7 @@ void menuMainView(event_t event) killEvents(event); break; + case EVT_KEY_FIRST(KEY_EXIT): #if defined(GVARS) if (gvarDisplayTimer > 0) { diff --git a/radio/src/gui/128x64/view_statistics.cpp b/radio/src/gui/128x64/view_statistics.cpp index 2b46be36e..0765cf9b6 100644 --- a/radio/src/gui/128x64/view_statistics.cpp +++ b/radio/src/gui/128x64/view_statistics.cpp @@ -31,7 +31,7 @@ void menuStatisticsView(event_t event) switch (event) { case EVT_KEY_FIRST(KEY_UP): -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEDN) case EVT_KEY_BREAK(KEY_PAGEDN): #elif defined(NAVIGATION_X7) case EVT_KEY_BREAK(KEY_PAGE): @@ -41,7 +41,7 @@ void menuStatisticsView(event_t event) break; case EVT_KEY_FIRST(KEY_DOWN): -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEUP) case EVT_KEY_BREAK(KEY_PAGEUP): killEvents(event); chainMenu(menuStatisticsDebug2); @@ -140,7 +140,7 @@ void menuStatisticsDebug(event_t event) break; case EVT_KEY_FIRST(KEY_UP): -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEDN) case EVT_KEY_BREAK(KEY_PAGEDN): disableVBatBridge(); chainMenu(menuStatisticsDebug2); @@ -153,7 +153,7 @@ void menuStatisticsDebug(event_t event) #endif case EVT_KEY_FIRST(KEY_DOWN): -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEUP) case EVT_KEY_BREAK(KEY_PAGEUP): #elif defined(NAVIGATION_X7) case EVT_KEY_LONG(KEY_PAGE): @@ -278,7 +278,7 @@ void menuStatisticsDebug2(event_t event) break; case EVT_KEY_FIRST(KEY_UP): -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEDN) case EVT_KEY_BREAK(KEY_PAGEDN): #elif defined(NAVIGATION_X7) case EVT_KEY_BREAK(KEY_PAGE): @@ -287,7 +287,7 @@ void menuStatisticsDebug2(event_t event) return; case EVT_KEY_FIRST(KEY_DOWN): -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEUP) case EVT_KEY_BREAK(KEY_PAGEUP): #elif defined(NAVIGATION_X7) case EVT_KEY_LONG(KEY_PAGE): diff --git a/radio/src/gui/480x272/model_receiver_options.cpp b/radio/src/gui/480x272/model_receiver_options.cpp index 38e46728c..0a2e2e4e6 100644 --- a/radio/src/gui/480x272/model_receiver_options.cpp +++ b/radio/src/gui/480x272/model_receiver_options.cpp @@ -47,8 +47,7 @@ enum { ITEM_RECEIVER_SETTINGS_PWM_RATE, ITEM_RECEIVER_SETTINGS_TELEMETRY, ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW, - ITEM_RECEIVER_SETTINGS_SPORT_FPORT, - ITEM_RECEIVER_SETTINGS_FPORT2, + ITEM_RECEIVER_SETTINGS_SPORT_MODE, ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1, ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2, ITEM_RECEIVER_SETTINGS_PINMAP_FIRST @@ -60,6 +59,15 @@ enum { #define CH_ENABLE_SPORT 4 #define CH_ENABLE_SBUS 5 +bool isSPortModeAvailable(int mode) +{ + uint8_t receiverId = reusableBuffer.hardwareAndSettings.receiverSettings.receiverId; + if (mode == 2 && !IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT2)) { + return false; + } + return true; +} + bool menuModelReceiverOptions(event_t event) { const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2; @@ -82,8 +90,7 @@ bool menuModelReceiverOptions(event_t event) 0, // PWM rate isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // Telemetry IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0), - IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT, 0), - IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT2, 0), + uint8_t((IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT) || IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT2)) ? 0 : HIDDEN_ROW), uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), 0 // channels ... @@ -171,21 +178,19 @@ bool menuModelReceiverOptions(event_t event) } break; - case ITEM_RECEIVER_SETTINGS_SPORT_FPORT: - lcdDrawText(MENUS_MARGIN_LEFT, y, "F.Port"); - reusableBuffer.hardwareAndSettings.receiverSettings.fport = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport, RECEIVER_OPTIONS_2ND_COLUMN, y, attr, event); - if (attr && checkIncDec_Ret) { - reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY; - } - break; - - case ITEM_RECEIVER_SETTINGS_FPORT2: - lcdDrawText(MENUS_MARGIN_LEFT, y, "F.Port2"); - reusableBuffer.hardwareAndSettings.receiverSettings.fport2 = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport2, RECEIVER_OPTIONS_2ND_COLUMN, y, attr, event); - if (attr && checkIncDec_Ret) { + case ITEM_RECEIVER_SETTINGS_SPORT_MODE: + { + lcdDrawText(0, y, STR_PROTOCOL); + uint8_t portType = reusableBuffer.hardwareAndSettings.receiverSettings.fport | (reusableBuffer.hardwareAndSettings.receiverSettings.fport2 << 1); + lcdDrawTextAtIndex(LCD_W/2, y, STR_SPORT_MODES, portType, attr); + portType = checkIncDec(event, portType, 0, 2, EE_MODEL, isSPortModeAvailable); + if (checkIncDec_Ret) { + reusableBuffer.hardwareAndSettings.receiverSettings.fport = portType & 0x01; + reusableBuffer.hardwareAndSettings.receiverSettings.fport2 = (portType & 0x02) >> 1; reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY; } break; + } case ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1: lcdDrawText(LCD_W/2, y+1, STR_MORE_OPTIONS_AVAILABLE, SMLSIZE|CENTERED); diff --git a/radio/src/gui/480x272/model_select.cpp b/radio/src/gui/480x272/model_select.cpp index 661edd814..cd0122ed4 100644 --- a/radio/src/gui/480x272/model_select.cpp +++ b/radio/src/gui/480x272/model_select.cpp @@ -246,6 +246,7 @@ void onModelSelectMenu(const char * result) if (!confirmModelChange()) return; } + // we store the latest changes if any storageFlushCurrentModel(); storageCheck(true); diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp index a620b5685..cd9974ac5 100644 --- a/radio/src/gui/480x272/model_setup.cpp +++ b/radio/src/gui/480x272/model_setup.cpp @@ -577,7 +577,7 @@ void onModelAntennaSwitchConfirm(const char * result) MODULE_TYPE_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_TYPE*/ \ MULTIMODULE_STATUS_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_STATUS, ITEM_MODEL_SETUP_INTERNAL_MODULE_SYNCSTATUS */ \ MODULE_CHANNELS_ROWS(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_CHANNELS*/ \ - IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(IF_INTERNAL_MODULE_ON(isModuleRxNumAvailable(INTERNAL_MODULE) ? (uint8_t)2 : (uint8_t)1))), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\ + IF_NOT_ACCESS_MODULE_RF(INTERNAL_MODULE, MODULE_BIND_ROWS(INTERNAL_MODULE)), /* *ITEM_MODEL_SETUP_INTERNAL_MODULE_NOT_ACCESS_RXNUM_BIND_RANGE */\ IF_ACCESS_MODULE_RF(INTERNAL_MODULE, 0), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_PXX2_MODEL_NUM*/ \ MODULE_OPTION_ROW(INTERNAL_MODULE), /* ITEM_MODEL_SETUP_INTERNAL_MODULE_OPTIONS */ \ MULTIMODULE_MODULE_ROWS(INTERNAL_MODULE) /* ITEM_MODEL_SETUP_INTERNAL_MODULE_AUTOBIND */ \ @@ -1549,6 +1549,7 @@ bool menuModelSetup(event_t event) lcdDrawText(MENUS_MARGIN_LEFT + INDENT_WIDTH, y, STR_RECEIVER); int l_posHorz = menuHorizontalPosition; coord_t bindButtonPos = MODEL_SETUP_2ND_COLUMN; + // RXNUM if (isModuleRxNumAvailable(moduleIdx)) { lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0 | LEFT, 2); bindButtonPos += 40; @@ -1572,12 +1573,13 @@ bool menuModelSetup(event_t event) else if (attr) { l_posHorz += 1; } + // BIND - RANGE if (isModuleBindRangeAvailable(moduleIdx)) { drawButton(bindButtonPos, y, STR_MODULE_BIND, (moduleState[moduleIdx].mode == MODULE_MODE_BIND ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==1 ? attr : 0)); if (isModuleRangeAvailable(moduleIdx)) { drawButton(bindButtonPos + 80, y, STR_MODULE_RANGE, (moduleState[moduleIdx].mode == MODULE_MODE_RANGECHECK ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==2 ? attr : 0)); } - uint8_t newFlag = 0; + uint8_t newFlag = MODULE_MODE_NORMAL; #if defined(MULTIMODULE) if (getMultiBindStatus(moduleIdx) == MULTI_BIND_FINISHED) { setMultiBindStatus(moduleIdx, MULTI_NORMAL_OPERATION); diff --git a/radio/src/gui/480x272/topbar.cpp b/radio/src/gui/480x272/topbar.cpp index f78174aa8..e8027d047 100644 --- a/radio/src/gui/480x272/topbar.cpp +++ b/radio/src/gui/480x272/topbar.cpp @@ -61,6 +61,11 @@ void drawTopBar() lcdDrawBitmapPattern(LCD_W-98, 8, LBM_TOPMENU_USB, MENU_TITLE_COLOR); } + // Logs + if (isFunctionActive(FUNCTION_LOGS) && !usbPlugged() && BLINK_ON_PHASE) { + lcdDrawBitmapPattern(LCD_W-98, 6, LBM_DOT, MENU_TITLE_COLOR); + } + // RSSI const uint8_t rssiBarsValue[] = {30, 40, 50, 60, 80}; const uint8_t rssiBarsHeight[] = {5, 10, 15, 21, 31}; diff --git a/radio/src/gui/common/stdlcd/model_receiver_options.cpp b/radio/src/gui/common/stdlcd/model_receiver_options.cpp index de3547b75..fe5affb15 100644 --- a/radio/src/gui/common/stdlcd/model_receiver_options.cpp +++ b/radio/src/gui/common/stdlcd/model_receiver_options.cpp @@ -47,8 +47,7 @@ enum { ITEM_RECEIVER_SETTINGS_PWM_RATE, ITEM_RECEIVER_SETTINGS_TELEMETRY, ITEM_RECEIVER_SETTINGS_TELEMETRY_25MW, - ITEM_RECEIVER_SETTINGS_SPORT_FPORT, - ITEM_RECEIVER_SETTINGS_FPORT2, + ITEM_RECEIVER_SETTINGS_SPORT_MODE, ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1, ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED2, ITEM_RECEIVER_SETTINGS_PINMAP_FIRST @@ -60,6 +59,15 @@ enum { #define CH_ENABLE_SPORT 4 #define CH_ENABLE_SBUS 5 +bool isSPortModeAvailable(int mode) +{ + uint8_t receiverId = reusableBuffer.hardwareAndSettings.receiverSettings.receiverId; + if (mode == 2 && !IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT2)) { + return false; + } + return true; +} + void menuModelReceiverOptions(event_t event) { const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2; @@ -82,8 +90,7 @@ void menuModelReceiverOptions(event_t event) 0, // PWM rate isModuleR9MAccess(g_moduleIdx) && receiverVariant == PXX2_VARIANT_EU && reusableBuffer.hardwareAndSettings.moduleSettings.txPower > 14 /*25mW*/ ? READONLY_ROW : (uint8_t)0, // Telemetry IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_TELEMETRY_25MW, 0), - IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT, 0), - IF_RECEIVER_CAPABILITY(RECEIVER_CAPABILITY_FPORT2, 0), + uint8_t((IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT) || IS_RECEIVER_CAPABILITY_ENABLED(RECEIVER_CAPABILITY_FPORT2)) ? 0 : HIDDEN_ROW), uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), uint8_t(reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].receivers[receiverId].information.capabilityNotSupported ? READONLY_ROW : HIDDEN_ROW), 0 // channels ... @@ -166,19 +173,19 @@ void menuModelReceiverOptions(event_t event) } break; - case ITEM_RECEIVER_SETTINGS_SPORT_FPORT: - reusableBuffer.hardwareAndSettings.receiverSettings.fport = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport, RECEIVER_OPTIONS_2ND_COLUMN, y, "F.Port", attr, event); - if (attr && checkIncDec_Ret) { - reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY; - } - break; - - case ITEM_RECEIVER_SETTINGS_FPORT2: - reusableBuffer.hardwareAndSettings.receiverSettings.fport2 = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.fport2, RECEIVER_OPTIONS_2ND_COLUMN, y, "F.Port2", attr, event); - if (attr && checkIncDec_Ret) { + case ITEM_RECEIVER_SETTINGS_SPORT_MODE: + { + lcdDrawText(0, y, STR_PROTOCOL); + uint8_t portType = reusableBuffer.hardwareAndSettings.receiverSettings.fport | (reusableBuffer.hardwareAndSettings.receiverSettings.fport2 << 1); + lcdDrawTextAtIndex(LCD_W/2, y, STR_SPORT_MODES, portType, attr); + portType = checkIncDec(event, portType, 0, 2, EE_MODEL, isSPortModeAvailable); + if (checkIncDec_Ret) { + reusableBuffer.hardwareAndSettings.receiverSettings.fport = portType & 0x01; + reusableBuffer.hardwareAndSettings.receiverSettings.fport2 = (portType & 0x02) >> 1; reusableBuffer.hardwareAndSettings.receiverSettings.dirty = RECEIVER_SETTINGS_DIRTY; } break; + } case ITEM_RECEIVER_SETTINGS_CAPABILITY_NOT_SUPPORTED1: lcdDrawText(LCD_W/2, y+1, STR_MORE_OPTIONS_AVAILABLE, SMLSIZE|CENTERED); diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index 9cd46a377..09d839676 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -248,9 +248,9 @@ enum { #endif #if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) -#define EXTERNAL_ANTENNA_ROW 0, -void onHardwareAntennaSwitchConfirm(const char * result) -{ + #define EXTERNAL_ANTENNA_ROW 0, + void onHardwareAntennaSwitchConfirm(const char * result) + { if (result == STR_OK) { // Switch to external antenna confirmation g_eeGeneral.antennaMode = reusableBuffer.radioHardware.antennaMode; @@ -259,9 +259,9 @@ void onHardwareAntennaSwitchConfirm(const char * result) else { reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode; } -} + } #else -#define EXTERNAL_ANTENNA_ROW + #define EXTERNAL_ANTENNA_ROW #endif #if defined(PCBX9LITE) @@ -272,7 +272,7 @@ void onHardwareAntennaSwitchConfirm(const char * result) #define SWITCH_TYPE_MAX(sw) (SWITCH_3POS) #elif defined(PCBX9E) #define SWITCH_TYPE_MAX(sw) ((MIXSRC_SF - MIXSRC_FIRST_SWITCH == sw || MIXSRC_SH - MIXSRC_FIRST_SWITCH == sw) ? SWITCH_2POS : SWITCH_3POS) -#elif defined(RADIO_TX12) +#elif defined(RADIO_TX12) || defined(RADIO_T8) #define SWITCH_TYPE_MAX(sw) ((MIXSRC_SA - MIXSRC_FIRST_SWITCH == sw || MIXSRC_SD - MIXSRC_FIRST_SWITCH == sw) ? SWITCH_2POS : SWITCH_3POS) #else #define SWITCH_TYPE_MAX(sw) ((MIXSRC_SF - MIXSRC_FIRST_SWITCH == sw || MIXSRC_SH - MIXSRC_FIRST_SWITCH <= sw) ? SWITCH_2POS : SWITCH_3POS) @@ -340,27 +340,19 @@ void menuRadioHardware(event_t event) POTS_ROWS, LABEL(Switches), SWITCHES_ROWS, - 0 /* battery calib */, RTC_ROW TX_CAPACITY_MEASUREMENT_ROWS - MAX_BAUD_ROWS - BLUETOOTH_ROWS - EXTERNAL_ANTENNA_ROW - AUX_SERIAL_ROWS - 0 /* ADC filter */, READONLY_ROW /* RAS */, SPORT_POWER_ROWS 1 /* debugs */, - - 0, - - 0 + 0 /* EEPROM backup */, + 0 /* Factory reset */ }); uint8_t sub = menuVerticalPosition - HEADER_LINE; diff --git a/radio/src/gui/common/stdlcd/view_telemetry.cpp b/radio/src/gui/common/stdlcd/view_telemetry.cpp index ecdb96aa9..07a31442c 100644 --- a/radio/src/gui/common/stdlcd/view_telemetry.cpp +++ b/radio/src/gui/common/stdlcd/view_telemetry.cpp @@ -34,7 +34,7 @@ enum NavigationDirection { #if defined(NAVIGATION_XLITE) #define EVT_KEY_PREVIOUS_VIEW(evt) (evt == EVT_KEY_LONG(KEY_LEFT) && IS_SHIFT_PRESSED()) #define EVT_KEY_NEXT_VIEW(evt) (evt == EVT_KEY_LONG(KEY_RIGHT) && IS_SHIFT_PRESSED()) -#elif defined(NAVIGATION_X7_TX12) +#elif defined(KEYS_GPIO_REG_PAGEDN) #define EVT_KEY_PREVIOUS_VIEW(evt) (evt == EVT_KEY_FIRST(KEY_PAGEUP)) #define EVT_KEY_NEXT_VIEW(evt) (evt == EVT_KEY_FIRST(KEY_PAGEDN)) #elif defined(NAVIGATION_X7) || defined(NAVIGATION_X9D) diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 1d856b6f7..368aac163 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -554,7 +554,7 @@ bool isPxx2IsrmChannelsCountAllowed(int channels) bool isTrainerUsingModuleBay() { #if defined(PCBTARANIS) - if (TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE <= g_model.trainerData.mode && g_model.trainerData.mode <= TRAINER_MODE_MASTER_BATTERY_COMPARTMENT) + if (TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE <= g_model.trainerData.mode && g_model.trainerData.mode <= TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE) return true; #endif return false; @@ -979,10 +979,10 @@ const char STR_SUBTYPE_FRSKYL[] = "\010""LR12\0 ""LR12 6ch"; const char STR_SUBTYPE_ESKY150V2[] = "\006""150 V2"; const char STR_SUBTYPE_JJRC345[] = "\007""Std\0 ""SkyTmbr"; const char STR_SUBTYPE_KYOSHO[] = "\004""FHSS""Hype"; -const char STR_SUBTYPE_RLINK[] = "\007""Surface""Air\0 "; +const char STR_SUBTYPE_RLINK[] = "\007""Surface""Air\0 ""DumboRC"; const char STR_SUBTYPE_ELRS[] = "\007""N/A WIP"; const char STR_SUBTYPE_REALACC[] = "\003""R11"; -const char STR_SUBTYPE_WFLYRF[] = "\005""RF20x"; +const char STR_SUBTYPE_WFLY2[] = "\005""RF20x"; const char* mm_options_strings::options[] = { nullptr, @@ -1045,7 +1045,7 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_FRSKYX_RX, 1, false, false, STR_SUBTYPE_FRSKYX_RX, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_HOTT, 1, true, false, STR_SUBTYPE_HOTT, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_FX816, 0, false, false, STR_SUBTYPE_FX816, nullptr}, - {MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, false, STR_SUBTYPE_PELIKAN, nullptr}, + {MODULE_SUBTYPE_MULTI_PELIKAN, 1, false, true, STR_SUBTYPE_PELIKAN, nullptr}, {MODULE_SUBTYPE_MULTI_XK, 1, false, false, STR_SUBTYPE_XK, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_XN297DUMP, 4, false, false, STR_SUBTYPE_XN297DUMP, STR_MULTI_RFCHAN}, {MODULE_SUBTYPE_MULTI_FRSKYX2, 5, true, false, STR_SUBTYPE_FRSKYX2, STR_MULTI_RFTUNE}, @@ -1057,11 +1057,12 @@ const mm_protocol_definition multi_protocols[] = { {MODULE_SUBTYPE_MULTI_JJRC345, 1, false, false, STR_SUBTYPE_JJRC345, nullptr}, {MODULE_SUBTYPE_MULTI_Q90C, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_KYOSHO, 1, false, true, STR_SUBTYPE_KYOSHO, nullptr}, - {MODULE_SUBTYPE_MULTI_RLINK, 1, false, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE}, + {MODULE_SUBTYPE_MULTI_RLINK, 2, false, false, STR_SUBTYPE_RLINK, STR_MULTI_RFTUNE}, {MODULE_SUBTYPE_MULTI_ELRS, 0, false, false, STR_SUBTYPE_ELRS, nullptr}, {MODULE_SUBTYPE_MULTI_REALACC, 0, false, false, STR_SUBTYPE_REALACC, nullptr}, {MODULE_SUBTYPE_MULTI_OMP, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, - {MODULE_SUBTYPE_MULTI_WFLYRF, 0, false, false, STR_SUBTYPE_WFLYRF, nullptr}, + {MODULE_SUBTYPE_MULTI_WFLY2, 0, false, false, STR_SUBTYPE_WFLY2, STR_MULTI_OPTION}, + {MODULE_SUBTYPE_MULTI_E016HV2, 0, false, false, NO_SUBTYPE, STR_MULTI_RFTUNE}, {MM_RF_CUSTOM_SELECTED, 7, true, true, NO_SUBTYPE, STR_MULTI_OPTION}, // Sentinel and default for protocols not listed above (MM_RF_CUSTOM is 0xff) diff --git a/radio/src/gui/navigation/navigation_x7.cpp b/radio/src/gui/navigation/navigation_x7.cpp index ac4a4bbdd..7e4255dac 100644 --- a/radio/src/gui/navigation/navigation_x7.cpp +++ b/radio/src/gui/navigation/navigation_x7.cpp @@ -56,8 +56,11 @@ void onSwitchLongEnterPress(const char * result) int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops) { int newval = val; - +#if defined(ROTARY_ENCODER_NAVIGATION) if (s_editMode>0 && event==EVT_ROTARY_RIGHT) { +#else + if (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_PLUS) || event==EVT_KEY_REPT(KEY_PLUS))) { +#endif newval += min(rotencSpeed, i_max-val); while (isValueAvailable && !isValueAvailable(newval) && newval<=i_max) { newval++; @@ -67,7 +70,11 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla AUDIO_KEY_ERROR(); } } +#if defined(ROTARY_ENCODER_NAVIGATION) else if (s_editMode>0 && event==EVT_ROTARY_LEFT) { +#else + if (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_MINUS) || event==EVT_KEY_REPT(KEY_MINUS))) { +#endif newval -= min(rotencSpeed, val-i_min); while (isValueAvailable && !isValueAvailable(newval) && newval>=i_min) { newval--; @@ -217,7 +224,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t if (menuTab) { int cc = curr; switch (event) { -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEUP) case EVT_KEY_FIRST(KEY_PAGEUP): #else case EVT_KEY_LONG(KEY_PAGE): @@ -232,7 +239,7 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t killEvents(event); break; -#if defined(NAVIGATION_X7_TX12) +#if defined(KEYS_GPIO_REG_PAGEDN) case EVT_KEY_FIRST(KEY_PAGEDN): #else case EVT_KEY_BREAK(KEY_PAGE): @@ -310,12 +317,14 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t } } break; - +#if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_RIGHT: - case EVT_KEY_FIRST(KEY_RIGHT): AUDIO_KEY_PRESS(); // no break - case EVT_KEY_REPT(KEY_RIGHT): +#else + case EVT_KEY_FIRST(KEY_DOWN): + case EVT_KEY_REPT(KEY_DOWN): +#endif if (s_editMode > 0) break; // TODO it was != if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { if (l_posHorz >= 0) { @@ -341,12 +350,14 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t l_posHorz = POS_HORZ_INIT(l_posVert); break; - +#if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_LEFT: - case EVT_KEY_FIRST(KEY_LEFT): AUDIO_KEY_PRESS(); // no break - case EVT_KEY_REPT(KEY_LEFT): +#else + case EVT_KEY_FIRST(KEY_UP): + case EVT_KEY_REPT(KEY_UP): +#endif if (s_editMode > 0) break; // TODO it was != if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) { if (l_posHorz >= 0) { diff --git a/radio/src/keys.h b/radio/src/keys.h index 44c1e53fe..0d4bc37dc 100644 --- a/radio/src/keys.h +++ b/radio/src/keys.h @@ -82,6 +82,11 @@ inline bool IS_KEY_EVT(event_t evt, uint8_t key) #define EVT_ROTARY_RIGHT 0xDE00 #define IS_NEXT_EVENT(event) (event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)) #define IS_PREVIOUS_EVENT(event) (event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)) +#elif defined(RADIO_T8) + #define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER) + #define EVT_ROTARY_LONG EVT_KEY_LONG(KEY_ENTER) + #define IS_NEXT_EVENT(event) (event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)) + #define IS_PREVIOUS_EVENT(event) (event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)) #elif (defined(PCBHORUS) || defined(PCBTARANIS)) && defined(ROTARY_ENCODER_NAVIGATION) #define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER) #define EVT_ROTARY_LONG EVT_KEY_LONG(KEY_ENTER) diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt index 79b4b95fc..138c8b60a 100644 --- a/radio/src/lua/CMakeLists.txt +++ b/radio/src/lua/CMakeLists.txt @@ -30,5 +30,6 @@ if(PYTHONINTERP_FOUND) add_lua_export_target(t12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T12) add_lua_export_target(tlite ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TLITE) add_lua_export_target(tx12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TX12) + add_lua_export_target(t8 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T8) add_lua_export_target(t16 ${LUA_INCLUDES} -DPCBHORUS -DPCBX10 -DRADIO_T16) endif() diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 29af9ec02..63abd4098 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -44,6 +44,8 @@ #include "lua/lua_exports_tlite.inc" #elif defined(RADIO_TX12) #include "lua/lua_exports_tx12.inc" +#elif defined(RADIO_T8) + #include "lua/lua_exports_t8.inc" #elif defined(PCBX9LITES) #include "lua/lua_exports_x9lites.inc" #elif defined(PCBX9LITE) @@ -1781,11 +1783,11 @@ const luaR_value_entry opentxConstants[] = { { "MIXSRC_SE", MIXSRC_SE }, { "MIXSRC_SG", MIXSRC_SG }, #endif -#if !defined(PCBXLITE) && !defined(PCBX9LITE) +#if defined(HARDWARE_SWITCH_F) { "MIXSRC_SF", MIXSRC_SF }, -#if !defined(RADIO_TX12) - { "MIXSRC_SH", MIXSRC_SH }, #endif +#if defined(HARDWARE_SWITCH_H) + { "MIXSRC_SH", MIXSRC_SH }, #endif { "MIXSRC_CH1", MIXSRC_CH1 }, { "SWSRC_LAST", SWSRC_LAST_LOGICAL_SWITCH }, @@ -1847,7 +1849,7 @@ const luaR_value_entry opentxConstants[] = { { "ROTENC_LOWSPEED", ROTENC_LOWSPEED }, { "ROTENC_MIDSPEED", ROTENC_MIDSPEED }, { "ROTENC_HIGHSPEED", ROTENC_HIGHSPEED }, -#elif defined(PCBX9D) || defined(PCBX9DP) // key reverted between field nav and value change +#elif defined(PCBX9D) || defined(PCBX9DP) || defined(RADIO_T8) // key reverted between field nav and value change { "EVT_VIRTUAL_PREV", EVT_KEY_FIRST(KEY_PLUS) }, { "EVT_VIRTUAL_PREV_REPT", EVT_KEY_REPT(KEY_PLUS) }, { "EVT_VIRTUAL_NEXT", EVT_KEY_FIRST(KEY_MINUS) }, @@ -1884,7 +1886,7 @@ const luaR_value_entry opentxConstants[] = { { "EVT_VIRTUAL_ENTER_LONG", EVT_KEY_LONG(KEY_ENTER) }, { "EVT_VIRTUAL_EXIT", EVT_KEY_BREAK(KEY_EXIT) }, #elif defined(NAVIGATION_X7) || defined(NAVIGATION_X9D) -#if defined(RADIO_TX12) +#if defined(RADIO_TX12) || defined(RADIO_T8) { "EVT_VIRTUAL_PREV_PAGE", EVT_KEY_BREAK(KEY_PAGEUP) }, { "EVT_VIRTUAL_NEXT_PAGE", EVT_KEY_BREAK(KEY_PAGEDN) }, { "EVT_VIRTUAL_MENU", EVT_KEY_BREAK(KEY_MODEL) }, diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index a0cef2c1d..81ac4472a 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -745,11 +745,23 @@ void displayLuaError(const char * title) if (lua_warning_info[0]) { char * split = strstr(lua_warning_info, ": "); if (split) { - lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+FH+3, lua_warning_info, split-lua_warning_info, SMLSIZE); - lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+2*FH+2, split+2, lua_warning_info+LUA_WARNING_INFO_LEN-split, SMLSIZE); +#if LCD_W == 128 + if (strlen(split + 2) <= 20) { + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + FH + 3, lua_warning_info, split - lua_warning_info, SMLSIZE); + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + 2 * FH + 2, split + 2, strlen(split + 2), SMLSIZE); + } + else { + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + FH, lua_warning_info, split - lua_warning_info, SMLSIZE); + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + 2 * FH, split + 2, 20, SMLSIZE); + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + 3 * FH, split + 22, strlen(split + 22), SMLSIZE); + } +#else + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + FH + 3, lua_warning_info, split - lua_warning_info, SMLSIZE); + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + 2 * FH + 2, split + 2, lua_warning_info + LUA_WARNING_INFO_LEN - split, SMLSIZE); +#endif } else { - lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+FH+3, lua_warning_info, 40, SMLSIZE); + lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y + FH + 3, lua_warning_info, 40, SMLSIZE); } } } @@ -787,7 +799,11 @@ void luaError(lua_State * L, uint8_t error, bool acknowledge) #if defined(SIMU) if (!strncmp(msg, ".", 2)) msg += 1; #endif +#if LCD_W == 128 + msg = strrchr(msg, '/') + 1; +#else if (!strncmp(msg, "/SCRIPTS/", 9)) msg += 9; +#endif strncpy(lua_warning_info, msg, LUA_WARNING_INFO_LEN); lua_warning_info[LUA_WARNING_INFO_LEN] = '\0'; } diff --git a/radio/src/main.cpp b/radio/src/main.cpp index db12ee20f..8ff9cd736 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -531,6 +531,10 @@ void perMain() } #endif +#if defined(KEYS_GPIO_REG_BIND) && defined(BIND_KEY) + bindButtonHandler(evt); +#endif + #if defined(GUI) DEBUG_TIMER_START(debugTimerGuiMain); guiMain(evt); diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 73b39c407..4e31efacb 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -334,6 +334,14 @@ void generalDefault() setDefaultOwnerId(); #endif +#if defined(RADIOMASTER_RTF_RELEASE) + // Those settings are for headless radio + g_eeGeneral.USBMode = USB_JOYSTICK_MODE; + g_eeGeneral.disableRtcWarning = 1; + g_eeGeneral.splashMode = 3; // Disable splash + g_eeGeneral.pwrOnSpeed = 1; // 1 second +#endif + g_eeGeneral.chkSum = 0xFFFF; } @@ -523,6 +531,15 @@ void modelDefault(uint8_t id) g_model.switchWarningState |= (1 << (3*i)); } #endif + +#if defined(RADIOMASTER_RTF_RELEASE) + // Those settings are for headless radio + g_model.trainerData.mode = TRAINER_MODE_SLAVE; + g_model.moduleData[INTERNAL_MODULE].type = MODULE_TYPE_MULTIMODULE; + g_model.moduleData[INTERNAL_MODULE].setMultiProtocol(MODULE_SUBTYPE_MULTI_FRSKY); + g_model.moduleData[INTERNAL_MODULE].subType = MM_RF_FRSKY_SUBTYPE_D8; + g_model.moduleData[INTERNAL_MODULE].failsafeMode = FAILSAFE_NOPULSES; +#endif } bool isInputRecursive(int index) @@ -917,7 +934,7 @@ void checkAll() checkFailsafe(); checkRSSIAlarmsDisabled(); -#if defined(SDCARD) +#if defined(SDCARD) && !defined(RADIOMASTER_RTF_RELEASE) checkSDVersion(); #endif @@ -2183,6 +2200,7 @@ uint32_t pwrCheck() #endif event_t evt = getEvent(false); DISPLAY_WARNING(evt); + LED_ERROR_BEGIN(); lcdRefresh(); if (warningResult) { @@ -2192,6 +2210,7 @@ uint32_t pwrCheck() else if (!warningText) { // shutdown has been cancelled pwr_check_state = PWR_CHECK_PAUSED; + LED_ERROR_END(); return e_power_on; } } diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 52a51719b..bb756305b 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -69,6 +69,12 @@ #define CASE_GYRO(x) #endif +#if defined(BACKLIGHT_GPIO) +#define CASE_BACKLIGHT(x) x, +#else +#define CASE_BACKLIGHT(x) +#endif + #if defined(LUA) #define CASE_LUA(x) x, #else @@ -382,6 +388,8 @@ inline bool SPLASH_NEEDED() #define ROTENC_HIGHSPEED 50 #define ROTENC_DELAY_MIDSPEED 32 #define ROTENC_DELAY_HIGHSPEED 16 +#elif defined(RADIO_T8) + constexpr uint8_t rotencSpeed = 1; #endif constexpr uint8_t HEART_TIMER_10MS = 0x01; @@ -437,6 +445,10 @@ extern uint8_t potsPos[NUM_XPOTS]; bool trimDown(uint8_t idx); void readKeysAndTrims(); +#if defined(KEYS_GPIO_REG_BIND) +void bindButtonHandler(event_t event); +#endif + uint16_t evalChkSum(); void alert(const char * title, const char * msg, uint8_t sound); @@ -998,7 +1010,13 @@ constexpr uint8_t OPENTX_START_NO_CHECKS = 0x04; #if defined(STATUS_LEDS) #define LED_ERROR_BEGIN() ledRed() +#if defined(RADIO_T8) + // Because of green backlit logo, green is preferred on this radio + #define LED_ERROR_END() ledGreen() + #define LED_BIND() ledBlue() +#else #define LED_ERROR_END() ledBlue() +#endif #else #define LED_ERROR_BEGIN() #define LED_ERROR_END() diff --git a/radio/src/options.h b/radio/src/options.h index acadfd129..4f1a1a077 100644 --- a/radio/src/options.h +++ b/radio/src/options.h @@ -97,6 +97,9 @@ static const char * const options[] = { #endif #if defined(HARDWARE_EXTERNAL_ACCESS_MOD) "externalaccessmod", +#endif +#if defined(BIND_KEY) + "bindkey", #endif nullptr //sentinel }; diff --git a/radio/src/pulses/modules_constants.h b/radio/src/pulses/modules_constants.h index 8ff0ea756..6fbec157e 100644 --- a/radio/src/pulses/modules_constants.h +++ b/radio/src/pulses/modules_constants.h @@ -178,8 +178,9 @@ enum ModuleSubtypeMulti { MODULE_SUBTYPE_MULTI_REALACC, MODULE_SUBTYPE_MULTI_OMP, MODULE_SUBTYPE_MULTI_MLINK, //75 - MODULE_SUBTYPE_MULTI_WFLYRF, - MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_WFLYRF + MODULE_SUBTYPE_MULTI_WFLY2, + MODULE_SUBTYPE_MULTI_E016HV2, + MODULE_SUBTYPE_MULTI_LAST = MODULE_SUBTYPE_MULTI_E016HV2 }; #define MODULE_SUBTYPE_MULTI_XN297DP 63-3 @@ -202,6 +203,14 @@ enum MMRFrskySubtypes { MM_RF_FRSKY_SUBTYPE_D16_CLONED }; +enum MMRFrskyX2Subtypes { + MM_RF_FRSKYX2_SUBTYPE_D16, + MM_RF_FRSKYX2_SUBTYPE_D8, + MM_RF_FRSKYX2_SUBTYPE_D16_LBT, + MM_RF_FRSKYX2_SUBTYPE_D16_LBT_8CH, + MM_RF_FRSKYX2_SUBTYPE_D16_CLONED +}; + enum ModuleSubtypeDSM2 { DSM2_PROTO_LP45, DSM2_PROTO_DSM2, diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index 82fa61727..48e7e05e0 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -147,6 +147,8 @@ const char * getBasename(const char * path); #define OTX_FOURCC 0x4278746F // otx for Jumper TLite #elif defined(RADIO_TX12) #define OTX_FOURCC 0x4178746F // otx for Radiomaster TX12 +#elif defined(RADIO_T8) + #define OTX_FOURCC 0x4378746F // otx for Radiomaster T8 #elif defined(PCBX7) #define OTX_FOURCC 0x3678746F // otx for Taranis X7 / X7S / X7 Express / X7S Express #elif defined(PCBX9LITES) diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index 7bf6c59f1..afbd95e96 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -273,6 +273,15 @@ void OpenTxSim::updateKeysAndSwitches(bool start) KEY_Down, KEY_EXIT, KEY_Right, KEY_TELE, KEY_Left, KEY_SYS, +#elif defined(RADIO_T8) + KEY_Page_Up, KEY_PAGEUP, + KEY_Page_Down, KEY_PAGEDN, + KEY_Return, KEY_ENTER, + KEY_Right, KEY_MODEL, + KEY_BackSpace, KEY_EXIT, + KEY_Left, KEY_SYS, + KEY_Up, KEY_PLUS, + KEY_Down, KEY_MINUS, #elif defined(PCBTARANIS) KEY_Page_Up, KEY_MENU, #if defined(KEYS_GPIO_REG_PAGE) diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index da86cebe8..40bac6a67 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -53,6 +53,13 @@ void preModelLoad() } pauseMixerCalculations(); +#if defined(INTMODULE_PWR_GPIO) + INTERNAL_MODULE_OFF(); +#endif +#if defined(EXTMODULE_PWR_GPIO) + EXTERNAL_MODULE_OFF(); +#endif + stopTrainer(); } diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index bf230850d..727b05096 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -663,6 +663,9 @@ void checkSwitches() } int x = SWITCH_WARNING_LIST_X; int y = SWITCH_WARNING_LIST_Y; +#if defined(COLORLCD) + lcdNextPos = SWITCH_WARNING_LIST_X; +#endif int numWarnings = 0; for (int i=0; iSQR2 = (ADC_CHANNEL_BATT << 0) + (ADC_Channel_Vbat << 5); ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15) + (ADC_CHANNEL_POT1 << 20) + (ADC_CHANNEL_POT2 << 25); } -#elif defined(RADIO_TLITE) +#elif defined(RADIO_T8) || defined(RADIO_TLITE) ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT << 0) + (ADC_Channel_Vbat << 5); ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH << 0) + (ADC_CHANNEL_STICK_LV << 5) + (ADC_CHANNEL_STICK_RV << 10) + (ADC_CHANNEL_STICK_RH << 15); #elif defined(PCBX7) diff --git a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp index d88c32610..b2c528dc0 100644 --- a/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/aux_serial_driver.cpp @@ -128,7 +128,7 @@ void auxSerialInit(unsigned int mode, unsigned int protocol) break; case UART_MODE_SBUS_TRAINER: - auxSerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b + auxSerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b AUX_SERIAL_POWER_ON(); break; @@ -213,10 +213,6 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void) #if defined(LUA) & !defined(CLI) if (luaRxFifo && auxSerialMode == UART_MODE_LUA) luaRxFifo->push(data); -#endif -#if !defined(BOOT) - if (auxSerialMode == UART_MODE_SBUS_TRAINER) - trainerSbusFifo.push(data); #endif } status = AUX_SERIAL_USART->SR; @@ -328,7 +324,7 @@ void aux2SerialInit(unsigned int mode, unsigned int protocol) break; case UART_MODE_SBUS_TRAINER: - aux2SerialSetup(SBUS_BAUDRATE, false, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b + aux2SerialSetup(SBUS_BAUDRATE, true, USART_WordLength_9b, USART_Parity_Even, USART_StopBits_2); // 2 stop bits requires USART_WordLength_9b AUX2_SERIAL_POWER_ON(); break; @@ -415,11 +411,6 @@ extern "C" void AUX2_SERIAL_USART_IRQHandler(void) if (luaRxFifo && aux2SerialMode == UART_MODE_LUA) { luaRxFifo->push(data); } -#endif -#if !defined(BOOT) - if (aux2SerialMode == UART_MODE_SBUS_TRAINER) { - trainerSbusFifo.push(data); - } #endif } status = AUX2_SERIAL_USART->SR; diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index b849fa8a2..e94ae4756 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -218,8 +218,13 @@ int main() } } +#if defined(RADIO_T8) && !defined(RADIOMASTER_RELEASE) + // Bind button not pressed + if ((~KEYS_GPIO_REG_BIND & KEYS_GPIO_PIN_BIND) == false) { +#else // LHR & RHL trims not pressed simultanously if (readTrims() != BOOTLOADER_KEYS) { +#endif // Start main application jumpTo(APP_START_ADDRESS); } diff --git a/radio/src/targets/common/arm/stm32/pwr_driver.cpp b/radio/src/targets/common/arm/stm32/pwr_driver.cpp index 220b5fdfd..32ff59195 100644 --- a/radio/src/targets/common/arm/stm32/pwr_driver.cpp +++ b/radio/src/targets/common/arm/stm32/pwr_driver.cpp @@ -80,7 +80,7 @@ void pwrInit() GPIO_Init(SD_PRESENT_GPIO, &GPIO_InitStructure); #endif -#if defined(INTMODULE_USART) && defined(TRAINER_MODULE_CPPM_GPIO_PIN) +#if defined(INTMODULE_USART) && defined(TRAINER_MODULE_CPPM) GPIO_SetBits(TRAINER_MODULE_CPPM_GPIO, TRAINER_MODULE_CPPM_GPIO_PIN); GPIO_InitStructure.GPIO_Pin = TRAINER_MODULE_CPPM_GPIO_PIN; GPIO_Init(TRAINER_MODULE_CPPM_GPIO, &GPIO_InitStructure); diff --git a/radio/src/targets/common/arm/stm32/usbd_desc.c b/radio/src/targets/common/arm/stm32/usbd_desc.c index 198c78a80..c43359c8a 100644 --- a/radio/src/targets/common/arm/stm32/usbd_desc.c +++ b/radio/src/targets/common/arm/stm32/usbd_desc.c @@ -54,30 +54,32 @@ * @{ */ -#define USBD_VID 0x0483 +#define USBD_VID_STM 0x0483 // STM Vendor ID +#define USBD_VID_PID_CODES 0x1209 // https://pid.codes #define USBD_LANGID_STRING 0x409 #define USBD_MANUFACTURER_STRING "OpenTX" #define USBD_SERIALNUMBER_FS_STRING "00000000001B" - #if defined(BOOT) #define USBD_MSC_PRODUCT_FS_STRING USB_NAME " Bootloader" #else #define USBD_MSC_PRODUCT_FS_STRING USB_NAME " Mass Storage" #endif +#define USBD_MSC_VID USBD_VID_STM #define USBD_MSC_PID 0x5720 #define USBD_MSC_CONFIGURATION_FS_STRING "MSC Config" #define USBD_MSC_INTERFACE_FS_STRING "MSC Interface" -#define USBD_HID_VID 0x1209 // https://pid.codes +#define USBD_HID_VID USBD_VID_PID_CODES #define USBD_HID_PID 0x4F54 // OpenTX assigned PID #define USBD_HID_PRODUCT_FS_STRING USB_NAME " Joystick" #define USBD_HID_CONFIGURATION_FS_STRING "HID Config" #define USBD_HID_INTERFACE_FS_STRING "HID Interface" -#define USBD_CDC_PID 0x5740 // do not change, this ID is used by the ST USB driver for Windows +#define USBD_CDC_VID USBD_VID_STM +#define USBD_CDC_PID 0x5740 // do not change, this ID is used by the ST USB driver for Windows #define USBD_CDC_PRODUCT_FS_STRING USB_NAME " Serial Port" #define USBD_CDC_CONFIGURATION_FS_STRING "VSP Config" #define USBD_CDC_INTERFACE_FS_STRING "VSP Interface" @@ -127,22 +129,29 @@ __ALIGN_BEGIN uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ] __ALIGN_END ; // modifi * @param length : pointer to data length variable * @retval pointer to descriptor buffer */ -uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length) +uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length) { - int pid=0; - int vid= USBD_VID; + int vid, pid; switch (getSelectedUsbMode()) { case USB_JOYSTICK_MODE: - pid = USBD_HID_PID; vid = USBD_HID_VID; + pid = USBD_HID_PID; break; + case USB_SERIAL_MODE: + vid = USBD_CDC_VID; pid = USBD_CDC_PID; break; + case USB_MASS_STORAGE_MODE: + vid = USBD_MSC_VID; pid = USBD_MSC_PID; break; + + default: + vid = 0; + pid = 0; } /* USB Standard Device Descriptor */ diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 38daec33c..cffc553dc 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -713,6 +713,7 @@ void bluetoothDisable(); extern DMAFifo<512> telemetryFifo; typedef DMAFifo<32> AuxSerialRxFifo; extern AuxSerialRxFifo auxSerialRxFifo; +extern AuxSerialRxFifo aux2SerialRxFifo; extern volatile uint32_t externalModulePort; #endif diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp index a4f0c7b6b..ce649c688 100644 --- a/radio/src/targets/horus/trainer_driver.cpp +++ b/radio/src/targets/horus/trainer_driver.cpp @@ -160,9 +160,16 @@ extern "C" void TRAINER_TIMER_IRQHandler() int sbusGetByte(uint8_t * byte) { switch (currentTrainerMode) { -#if defined(AUX_SERIAL) +#if defined(AUX_SERIAL) || defined(AUX2_SERIAL) case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: - return trainerSbusFifo.pop(*byte); +#if defined(AUX_SERIAL) + if (auxSerialMode == UART_MODE_SBUS_TRAINER) + return auxSerialRxFifo.pop(*byte); +#endif +#if defined(AUX2_SERIAL) + if (aux2SerialMode == UART_MODE_SBUS_TRAINER) + return aux2SerialRxFifo.pop(*byte); +#endif #endif default: return false; diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index fa0122175..8376d786c 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -42,6 +42,8 @@ char * main_thread_error = nullptr; bool simu_shutdown = false; bool simu_running = false; +uint32_t telemetryErrors = 0; + #if defined(STM32) GPIO_TypeDef gpioa, gpiob, gpioc, gpiod, gpioe, gpiof, gpiog, gpioh, gpioi, gpioj; TIM_TypeDef tim1, tim2, tim3, tim4, tim5, tim6, tim7, tim8, tim9, tim10; @@ -441,6 +443,47 @@ void sportUpdatePowerInit() { } +void telemetryPortSetDirectionInput() +{ +} + +void telemetryPortSetDirectionOutput() +{ +} + +void rxPdcUsart( void (*pChProcess)(uint8_t x) ) +{ +} + +void telemetryPortInit(uint32_t baudrate, uint8_t mode) +{ +} + +bool telemetryGetByte(uint8_t * byte) +{ + return false; +} + +void telemetryClearFifo() +{ +} + +void telemetryPortInvertedInit(uint32_t baudrate) +{ +} + +void sportSendByte(uint8_t byte) +{ +} + +void sportSendBuffer(const uint8_t * buffer, uint32_t count) +{ +} + +void check_telemetry_exti() +{ +} + void boardInit() { } diff --git a/radio/src/targets/sky9x/CMakeLists.txt b/radio/src/targets/sky9x/CMakeLists.txt index 181b5ab85..d09906965 100644 --- a/radio/src/targets/sky9x/CMakeLists.txt +++ b/radio/src/targets/sky9x/CMakeLists.txt @@ -12,6 +12,7 @@ set(PPM_LIMITS_SYMETRICAL YES) set(PXX1 YES) set(AFHDS3 NO) set(GHOST NO) +add_definitions(-DHARDWARE_EXTERNAL_MODULE) add_definitions(-DDISABLE_MULTI_UPDATE) if(PCB STREQUAL 9XRPRO) @@ -122,9 +123,13 @@ set(FIRMWARE_TARGET_SRC MEDSdcard.c ) +set(FIRMWARE_TARGET_SRC + ${FIRMWARE_TARGET_SRC} + telemetry_driver.cpp + ) + set(TARGET_SRC ${TARGET_SRC} - telemetry_driver.cpp adc_driver.cpp pulses_driver.cpp audio_driver.cpp diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h index 0a6aef20d..ca7e23acd 100644 --- a/radio/src/targets/sky9x/board.h +++ b/radio/src/targets/sky9x/board.h @@ -395,13 +395,8 @@ void debugPutc(const char c); // Telemetry driver void telemetryPortInit(uint32_t baudrate, uint8_t mode); -inline void telemetryPortSetDirectionOutput() -{ -} -inline void telemetryPortSetDirectionInput() -{ -} -uint32_t telemetryTransmitPending(); +void telemetryPortSetDirectionOutput(); +void telemetryPortSetDirectionInput(); void telemetryTransmitBuffer(const uint8_t * buffer, uint32_t size); void rxPdcUsart( void (*pChProcess)(uint8_t x) ); void sportSendBuffer(const uint8_t * buffer, uint32_t size); diff --git a/radio/src/targets/sky9x/telemetry_driver.cpp b/radio/src/targets/sky9x/telemetry_driver.cpp index 4875c5d35..8efa83951 100644 --- a/radio/src/targets/sky9x/telemetry_driver.cpp +++ b/radio/src/targets/sky9x/telemetry_driver.cpp @@ -93,10 +93,8 @@ void startPdcUsartReceive() { Usart *pUsart = SECOND_USART; TelemetryInBuffer.outPtr = TelemetryInBuffer.fifo ; -#ifndef SIMU pUsart->US_RPR = (uint32_t)TelemetryInBuffer.fifo ; pUsart->US_RNPR = (uint32_t)TelemetryInBuffer.fifo ; -#endif pUsart->US_RCR = RX_UART_BUFFER_SIZE ; pUsart->US_RNCR = RX_UART_BUFFER_SIZE ; pUsart->US_PTCR = US_PTCR_RXTEN ; @@ -104,7 +102,6 @@ void startPdcUsartReceive() void rxPdcUsart( void (*pChProcess)(uint8_t x) ) { -#if !defined(SIMU) Usart *pUsart = SECOND_USART; uint8_t *ptr ; uint8_t *endPtr ; @@ -132,7 +129,6 @@ void rxPdcUsart( void (*pChProcess)(uint8_t x) ) pUsart->US_RNPR = (uint32_t)TelemetryInBuffer.fifo ; pUsart->US_RNCR = RX_UART_BUFFER_SIZE ; } -#endif } uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size) @@ -140,9 +136,7 @@ uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size) Usart * pUsart = SECOND_USART; if (pUsart->US_TNCR == 0) { -#ifndef SIMU pUsart->US_TNPR = (uint32_t)buffer ; -#endif pUsart->US_TNCR = size ; pUsart->US_PTCR = US_PTCR_TXTEN ; return 1 ; @@ -150,6 +144,7 @@ uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size) return 0 ; } +/* uint32_t telemetryTransmitPending() { Usart *pUsart = SECOND_USART; @@ -164,13 +159,20 @@ uint32_t telemetryTransmitPending() return x ; } +*/ + +void telemetryPortSetDirectionOutput() +{ +} + +void telemetryPortSetDirectionInput() +{ +} void telemetryPortInit(uint32_t baudrate, uint8_t mode) { -#if !defined(SIMU) UART2_Configure(baudrate, Master_frequency, mode); startPdcUsartReceive(); -#endif } void sportSendBuffer(const uint8_t * buffer, uint32_t size) diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index e32f8c72c..54779f137 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -6,6 +6,9 @@ option(AFHDS3 "AFHDS3 TX Module" ON) option(GHOST "Ghost TX Module" ON) option(INTERNAL_MODULE_PPM "Support for PPM internal module" OFF) option(AUTOUPDATE "Auto update internal chips from SD" OFF) +option(BIND_KEY "Enable bind button" OFF) + +set(EXTERNAL_MODULE YES) if(PCB STREQUAL X9E) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" ON) @@ -157,6 +160,24 @@ elseif(PCB STREQUAL X7) add_definitions(-DRADIO_TX12) add_definitions(-DEEPROM_VARIANT=0x4002) add_definitions(-DMANUFACTURER_RADIOMASTER) + elseif(PCBREV STREQUAL T8) + option(INTERNAL_MODULE_MULTI "Support for MULTI internal module" ON) + set(EXTERNAL_MODULE NO) + set(AFHDS3 NO) + set(FLAVOUR t8) + set(NAVIGATION_TYPE x7) + set(CPU_TYPE STM32F2) + set(CPU_TYPE_FULL STM32F205xE) # for size report + set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld) + set(ROTARY_ENCODER NO) + set(LUA_EXPORT lua_export_t8) + set(BLUETOOTH NO) + if(RADIOMASTER_RELEASE) + set(BIND_KEY YES) + endif() + add_definitions(-DRADIO_T8) + add_definitions(-DEEPROM_VARIANT=0x4004) + add_definitions(-DMANUFACTURER_RADIOMASTER) elseif(PCBREV STREQUAL ACCESS) option(INTERNAL_MODULE_PXX1 "Support for PXX1 internal module" OFF) option(INTERNAL_MODULE_PXX2 "Support for PXX2 internal module" ON) @@ -347,6 +368,14 @@ if(ROTARY_ENCODER) ) endif() +if(BIND_KEY) + set(TARGET_SRC + ${TARGET_SRC} + bind_button_driver.cpp + ) + add_definitions(-DBIND_KEY) +endif() + if(USB_CHARGER) set(TARGET_SRC ${TARGET_SRC} usb_charger_driver.cpp) add_definitions(-DUSB_CHARGER) @@ -467,4 +496,8 @@ if(INTERNAL_MODULE_PPM) add_definitions(-DINTERNAL_MODULE_PPM) endif() +if(EXTERNAL_MODULE) + add_definitions(-DHARDWARE_EXTERNAL_MODULE) +endif() + set(RADIO_DEPENDENCIES ${RADIO_DEPENDENCIES} ${BITMAPS_TARGET}) diff --git a/radio/src/targets/taranis/backlight_driver.cpp b/radio/src/targets/taranis/backlight_driver.cpp index 63a5bfd1a..7c758f818 100644 --- a/radio/src/targets/taranis/backlight_driver.cpp +++ b/radio/src/targets/taranis/backlight_driver.cpp @@ -20,7 +20,13 @@ #include "opentx.h" -#if defined(PCBX9E) +#if !defined(BACKLIGHT_GPIO) + // no backlight + void backlightInit() {} + void backlightEnable(uint8_t level) {} + void backlightDisable() {} + uint8_t isBacklightEnabled() {return false;} +#elif defined(PCBX9E) void backlightInit() { GPIO_InitTypeDef GPIO_InitStructure; diff --git a/radio/src/targets/taranis/bind_button_driver.cpp b/radio/src/targets/taranis/bind_button_driver.cpp new file mode 100644 index 000000000..2d3ca63fc --- /dev/null +++ b/radio/src/targets/taranis/bind_button_driver.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "opentx.h" + + +bool setBindProtocolSelection() +{ + int16_t xPos = calibratedAnalogs[CONVERT_MODE(0)]; + int16_t yPos = calibratedAnalogs[CONVERT_MODE(1)]; + + // Center: D8 + if (abs(xPos < 50 && abs(yPos) < 50)) { + g_model.moduleData[INTERNAL_MODULE].setMultiProtocol(MODULE_SUBTYPE_MULTI_FRSKY); + g_model.moduleData[INTERNAL_MODULE].subType = MM_RF_FRSKY_SUBTYPE_D8; + storageDirty(EE_MODEL); + return true; + } + + // Top left: D16 FCC + if (xPos < -512 && yPos > 512) { + g_model.moduleData[INTERNAL_MODULE].setMultiProtocol(MODULE_SUBTYPE_MULTI_FRSKY); + g_model.moduleData[INTERNAL_MODULE].subType = MM_RF_FRSKY_SUBTYPE_D16; + g_model.moduleData[INTERNAL_MODULE].failsafeMode = FAILSAFE_NOPULSES; + storageDirty(EE_MODEL); + return true; + } + + // Top right: D16 LBT + if (xPos > 512 && yPos > 512) { + g_model.moduleData[INTERNAL_MODULE].setMultiProtocol(MODULE_SUBTYPE_MULTI_FRSKY); + g_model.moduleData[INTERNAL_MODULE].subType = MM_RF_FRSKY_SUBTYPE_D16_LBT; + g_model.moduleData[INTERNAL_MODULE].failsafeMode = FAILSAFE_NOPULSES; + storageDirty(EE_MODEL); + return true; + } + + // Bottom left: V2.1 D16 FCC + if (xPos < -512 && yPos < -512) { + g_model.moduleData[INTERNAL_MODULE].setMultiProtocol(MODULE_SUBTYPE_MULTI_FRSKYX2); + g_model.moduleData[INTERNAL_MODULE].subType = MM_RF_FRSKYX2_SUBTYPE_D16; + g_model.moduleData[INTERNAL_MODULE].failsafeMode = FAILSAFE_NOPULSES; + storageDirty(EE_MODEL); + return true; + } + + // Bottom right: V2.1 D16 LBT + if (xPos > 512 && yPos < -512) { + g_model.moduleData[INTERNAL_MODULE].setMultiProtocol(MODULE_SUBTYPE_MULTI_FRSKYX2); + g_model.moduleData[INTERNAL_MODULE].subType = MM_RF_FRSKYX2_SUBTYPE_D16_LBT; + g_model.moduleData[INTERNAL_MODULE].failsafeMode = FAILSAFE_NOPULSES; + storageDirty(EE_MODEL); + return true; + } + + return false; +} + +void bindButtonHandler(event_t event) +{ + if( !isModuleMultimodule(INTERNAL_MODULE)) + return; + + if (event == EVT_KEY_LONG(KEY_BIND) && getMultiBindStatus(INTERNAL_MODULE) == MULTI_NORMAL_OPERATION) { + if (setBindProtocolSelection()) { + setMultiBindStatus(INTERNAL_MODULE, MULTI_BIND_INITIATED); + moduleState[INTERNAL_MODULE].mode = MODULE_MODE_BIND; + } + } + + if (getMultiBindStatus(INTERNAL_MODULE) == MULTI_BIND_INITIATED) { + if (FAST_BLINK_ON_PHASE) + LED_BIND(); + else + ledOff(); + } + + if (getMultiBindStatus(INTERNAL_MODULE) == MULTI_BIND_FINISHED) { + setMultiBindStatus(INTERNAL_MODULE, MULTI_NORMAL_OPERATION); + moduleState[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL; + LED_ERROR_END(); + } +} diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index d86a82f2d..bec585b25 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -272,6 +272,8 @@ void boardOff() #if defined (RADIO_TX12) #define BATTERY_DIVIDER 22830 +#elif defined (RADIO_T8) + #define BATTERY_DIVIDER 50000 #else #define BATTERY_DIVIDER 26214 #endif diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index ca2acc903..24b709b3f 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -27,7 +27,7 @@ #include "board_common.h" #include "hal.h" -#if defined(RADIO_TX12) +#if defined(RADIO_TX12) || defined(RADIO_TX12) #define NAVIGATION_X7_TX12 #endif @@ -152,7 +152,7 @@ void extmoduleSendInvertedByte(uint8_t byte); // Trainer driver #define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE) -#if defined(PCBX9D) || (defined(PCBX9DP) && PCBREV < 2019) +#if defined(TRAINER_DETECT_GPIO) // Trainer detect is a switch on the jack #define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET) #elif defined(PCBXLITES) @@ -270,6 +270,10 @@ enum EnumKeys KEY_COUNT, KEY_MAX = KEY_COUNT - 1, +#if defined(KEYS_GPIO_REG_BIND) + KEY_BIND, +#endif + #if defined(ROTARY_ENCODER_NAVIGATION) KEY_PLUS, KEY_MINUS, @@ -355,7 +359,7 @@ enum EnumSwitchesPositions SW_SE1, SW_SE2, #endif -#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || defined(PCBX7) || defined(PCBXLITES) || defined(PCBX9LITES) +#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || defined(PCBX7) || defined(PCBXLITES) || defined(PCBX9LITES) || defined(RADIO_T8) SW_SF0, SW_SF1, SW_SF2, @@ -365,7 +369,7 @@ enum EnumSwitchesPositions SW_SG1, SW_SG2, #endif -#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || (defined(PCBX7) && !defined(RADIO_TX12)) +#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || (defined(PCBX7) && !defined(RADIO_TX12)) || defined(RADIO_T8) SW_SH0, SW_SH1, SW_SH2, @@ -447,6 +451,11 @@ enum EnumSwitchesPositions #define STORAGE_NUM_SWITCHES NUM_SWITCHES #define DEFAULT_SWITCH_CONFIG (SWITCH_3POS << 10) + (SWITCH_3POS << 8) + (SWITCH_TOGGLE << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_TOGGLE << 0) #define DEFAULT_POTS_CONFIG (POT_WITH_DETENT << 0) + (POT_WITH_DETENT << 2); +#elif defined(RADIO_T8) + #define NUM_SWITCHES 4 + #define STORAGE_NUM_SWITCHES 8 + #define DEFAULT_SWITCH_CONFIG (SWITCH_2POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_2POS << 0); + #define DEFAULT_POTS_CONFIG (0) #elif defined(PCBX7ACCESS) #define NUM_SWITCHES 7 #define STORAGE_NUM_SWITCHES 8 @@ -549,7 +558,7 @@ enum Analogs { #define NUM_SLIDERS 0 #define STORAGE_NUM_POTS 1 #define STORAGE_NUM_SLIDERS 0 -#elif defined(RADIO_TLITE) +#elif defined(RADIO_T8) || defined(RADIO_TLITE) #define NUM_POTS 0 #define NUM_SLIDERS 0 #define STORAGE_NUM_POTS 2 @@ -654,7 +663,7 @@ extern uint16_t adcValues[NUM_ANALOGS]; #define BATTERY_WARN 66 // 6.6V #define BATTERY_MIN 67 // 6.7V #define BATTERY_MAX 83 // 8.3V -#elif defined(RADIO_TLITE) +#elif defined(RADIO_T8) || defined(RADIO_TLITE) // 1S Li-ion / Lipo #define BATTERY_WARN 33 // 3.3V #define BATTERY_MIN 32 // 3.2V @@ -725,6 +734,10 @@ uint8_t isBacklightEnabled(); #define USB_NAME "Radiomaster TX12" #define USB_MANUFACTURER 'R', 'M', '_', 'T', 'X', ' ', ' ', ' ' /* 8 bytes */ #define USB_PRODUCT 'R', 'M', ' ', 'T', 'X', '1', '2', ' ' /* 8 Bytes */ +#elif defined(RADIO_T8) + #define USB_NAME "Radiomaster T8" + #define USB_MANUFACTURER 'R', 'M', '_', 'T', 'X', ' ', ' ', ' ' /* 8 bytes */ + #define USB_PRODUCT 'R', 'M', ' ', 'T', '8', ' ', ' ', ' ' /* 8 Bytes */ #elif defined(RADIO_TLITE) #define USB_NAME "Jumper TLite" #define USB_MANUFACTURER 'J', 'U', 'M', 'P', 'E', 'R', ' ', ' ' /* 8 bytes */ @@ -883,8 +896,10 @@ void bluetoothDisable(); #endif // USB Charger +#if defined(USB_CHARGER) void usbChargerInit(); bool usbChargerLed(); +#endif // LED driver void ledInit(); diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 5cf8513fe..d2fba5d07 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -74,6 +74,25 @@ #define KEYS_GPIO_PIN_MDL GPIO_Pin_11 // PE.11 #define KEYS_GPIO_REG_TELE GPIOD->IDR #define KEYS_GPIO_PIN_TELE GPIO_Pin_2 // PD.02 +#elif defined(RADIO_T8) + #define KEYS_GPIO_REG_PAGEUP GPIOD->IDR + #define KEYS_GPIO_PIN_PAGEUP GPIO_Pin_3 // PD.03 + #define KEYS_GPIO_REG_PAGEDN GPIOD->IDR + #define KEYS_GPIO_PIN_PAGEDN GPIO_Pin_7 // PD.07 + #define KEYS_GPIO_REG_EXIT GPIOB->IDR + #define KEYS_GPIO_PIN_EXIT GPIO_Pin_3 // PB.03 + #define KEYS_GPIO_REG_ENTER GPIOA->IDR + #define KEYS_GPIO_PIN_ENTER GPIO_Pin_13 // PA.13 + #define KEYS_GPIO_REG_SYS GPIOB->IDR + #define KEYS_GPIO_PIN_SYS GPIO_Pin_4 // PB.04 + #define KEYS_GPIO_REG_MDL GPIOE->IDR + #define KEYS_GPIO_PIN_MDL GPIO_Pin_11 // PE.11 + #define KEYS_GPIO_REG_PLUS GPIOE->IDR + #define KEYS_GPIO_PIN_PLUS GPIO_Pin_9 // PE.09 + #define KEYS_GPIO_REG_MINUS GPIOE->IDR + #define KEYS_GPIO_PIN_MINUS GPIO_Pin_10 // PE.10 + #define KEYS_GPIO_REG_BIND GPIOA->IDR + #define KEYS_GPIO_PIN_BIND GPIO_Pin_10 // PA.10 #elif defined(PCBX7) #define KEYS_GPIO_REG_PAGE GPIOD->IDR #define KEYS_GPIO_PIN_PAGE GPIO_Pin_3 // PD.03 @@ -332,6 +351,11 @@ #define HARDWARE_SWITCH_A #define SWITCHES_GPIO_REG_A GPIOC->IDR #define SWITCHES_GPIO_PIN_A GPIO_Pin_13 // PC.13 +#elif defined(RADIO_T8) + #define STORAGE_SWITCH_A + #define HARDWARE_SWITCH_A + #define SWITCHES_GPIO_REG_A GPIOE->IDR + #define SWITCHES_GPIO_PIN_A GPIO_Pin_14 // PE.14 #elif defined(PCBX7) #define STORAGE_SWITCH_A #define HARDWARE_SWITCH_A @@ -362,6 +386,13 @@ #define SWITCHES_GPIO_PIN_B_L GPIO_Pin_6 // PA.06 #define SWITCHES_GPIO_REG_B_H GPIOA->IDR #define SWITCHES_GPIO_PIN_B_H GPIO_Pin_5 // PA.05 +#elif defined(RADIO_T8) + #define STORAGE_SWITCH_B + #define HARDWARE_SWITCH_B + #define SWITCHES_GPIO_REG_B_L GPIOE->IDR + #define SWITCHES_GPIO_PIN_B_L GPIO_Pin_7 // PE.07 + #define SWITCHES_GPIO_REG_B_H GPIOE->IDR + #define SWITCHES_GPIO_PIN_B_H GPIO_Pin_13 // PE.13 #elif defined(RADIO_TLITE) #define STORAGE_SWITCH_B #define HARDWARE_SWITCH_B @@ -413,6 +444,13 @@ #define SWITCHES_GPIO_PIN_C_L GPIO_Pin_11 // PD.11 #define SWITCHES_GPIO_REG_C_H GPIOE->IDR #define SWITCHES_GPIO_PIN_C_H GPIO_Pin_0 // PE.00 +#elif defined(RADIO_T8) + #define STORAGE_SWITCH_C + #define HARDWARE_SWITCH_C + #define SWITCHES_GPIO_REG_C_L GPIOE->IDR + #define SWITCHES_GPIO_PIN_C_L GPIO_Pin_2 // PE.02 + #define SWITCHES_GPIO_REG_C_H GPIOE->IDR + #define SWITCHES_GPIO_PIN_C_H GPIO_Pin_1 // PE.01 #elif defined(RADIO_TLITE) #define STORAGE_SWITCH_C #define HARDWARE_SWITCH_C @@ -460,6 +498,11 @@ #define SWITCHES_GPIO_PIN_D_L GPIO_Pin_4 // PB.04 #define SWITCHES_GPIO_REG_D_H GPIOB->IDR #define SWITCHES_GPIO_PIN_D_H GPIO_Pin_5 // PB.05 +#elif defined(RADIO_T8) + #define STORAGE_SWITCH_D + #define HARDWARE_SWITCH_D + #define SWITCHES_GPIO_REG_D GPIOD->IDR + #define SWITCHES_GPIO_PIN_D GPIO_Pin_14 // PD.14 #elif defined(RADIO_TX12) #define STORAGE_SWITCH_D #define HARDWARE_SWITCH_D @@ -556,7 +599,7 @@ #define SWITCHES_GPIO_PIN_F_L GPIO_Pin_1 // PE.01 #define SWITCHES_GPIO_REG_F_H GPIOE->IDR #define SWITCHES_GPIO_PIN_F_H GPIO_Pin_2 // PE.02 -#elif defined(RADIO_TLITE) +#elif defined(RADIO_T8) || defined(RADIO_TLITE) // no SWF #define STORAGE_SWITCH_F #elif defined(PCBX7) @@ -583,7 +626,7 @@ #define HARDWARE_SWITCH_G #define SWITCHES_GPIO_REG_G GPIOC->IDR #define SWITCHES_GPIO_PIN_G GPIO_Pin_2 // PC.02 -#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) +#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_T8) // no SWG #else #define STORAGE_SWITCH_G @@ -606,6 +649,9 @@ #define SWITCHES_GPIO_PIN_H GPIO_Pin_14 // PD.14 #elif defined(PCBXLITE) || defined(PCBX9LITE) // no SWH +#elif defined(RADIO_T8) + #define STORAGE_SWITCH_H + // no SWH #elif defined(RADIO_TX12) #elif defined(RADIO_TLITE) // no SWH @@ -638,6 +684,10 @@ #define SWITCHES_GPIO_REG_I GPIOC->IDR #define SWITCHES_GPIO_PIN_I GPIO_Pin_13 // PC.13 #define STORAGE_SWITCH_J +#elif defined(RADIO_T8) + #define STORAGE_SWITCH_I + #define STORAGE_SWITCH_J + // no SWI/J #elif defined(RADIO_TX12) #define STORAGE_SWITCH_I #define HARDWARE_SWITCH_I @@ -774,6 +824,13 @@ #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3|GPIO_Pin_13) #define KEYS_GPIOD_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_11 | GPIO_Pin_14 | GPIO_Pin_15) #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 |GPIO_Pin_8| GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15) +#elif defined(RADIO_T8) + #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) + #define KEYS_GPIOA_PINS (KEYS_GPIO_PIN_ENTER | KEYS_GPIO_PIN_BIND) + #define KEYS_GPIOB_PINS (KEYS_GPIO_PIN_EXIT | KEYS_GPIO_PIN_SYS) + #define KEYS_GPIOC_PINS (TRIMS_GPIO_PIN_LHR | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_RVD) + #define KEYS_GPIOD_PINS (KEYS_GPIO_PIN_PAGEUP | KEYS_GPIO_PIN_PAGEDN | SWITCHES_GPIO_PIN_D | TRIMS_GPIO_PIN_LHL) + #define KEYS_GPIOE_PINS (SWITCHES_GPIO_PIN_C_H | SWITCHES_GPIO_PIN_C_L | TRIMS_GPIO_PIN_RHL | TRIMS_GPIO_PIN_RHR | TRIMS_GPIO_PIN_LVU | TRIMS_GPIO_PIN_LVD | SWITCHES_GPIO_PIN_B_L | KEYS_GPIO_PIN_PLUS | KEYS_GPIO_PIN_MINUS | KEYS_GPIO_PIN_MDL | SWITCHES_GPIO_PIN_B_H | SWITCHES_GPIO_PIN_A) #elif defined(RADIO_X7ACCESS) #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE) #define KEYS_GPIOA_PINS GPIO_Pin_5 @@ -933,6 +990,25 @@ #define ADC_CHANNEL_POT2 ADC_Channel_12 // ADC1_IN12 #define ADC_CHANNEL_BATT ADC_Channel_10 // ADC1_IN10 #define ADC_VREF_PREC2 330 +#elif defined(RADIO_T8) + // No pots + #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2) + #define ADC_RCC_APB1Periph 0 + #define ADC_RCC_APB2Periph RCC_APB2Periph_ADC1 + #define ADC_GPIO_PIN_STICK_RV GPIO_Pin_0 // PA.00 + #define ADC_GPIO_PIN_STICK_RH GPIO_Pin_1 // PA.01 + #define ADC_GPIO_PIN_STICK_LV GPIO_Pin_2 // PA.02 + #define ADC_GPIO_PIN_STICK_LH GPIO_Pin_3 // PA.03 + #define ADC_CHANNEL_STICK_RV ADC_Channel_0 // ADC1_IN0 + #define ADC_CHANNEL_STICK_RH ADC_Channel_1 // ADC1_IN1 + #define ADC_CHANNEL_STICK_LV ADC_Channel_2 // ADC1_IN2 + #define ADC_CHANNEL_STICK_LH ADC_Channel_3 // ADC1_IN3 + #define ADC_GPIO_PIN_BATT GPIO_Pin_0 // PC.00 + #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV) + #define ADC_GPIOB_PINS 0 + #define ADC_GPIOC_PINS ADC_GPIO_PIN_BATT + #define ADC_CHANNEL_BATT ADC_Channel_10 + #define ADC_VREF_PREC2 300 #elif defined(RADIO_TLITE) #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2) #define ADC_RCC_APB1Periph 0 @@ -1078,6 +1154,16 @@ #define LED_BLUE_GPIO_PIN GPIO_Pin_1 // PB.01 #define LED_RED_GPIO GPIOC #define LED_RED_GPIO_PIN GPIO_Pin_4 // PC.04 +#elif defined(RADIO_T8) + #define STATUS_LEDS + #define GPIO_LED_GPIO_ON GPIO_SetBits + #define GPIO_LED_GPIO_OFF GPIO_ResetBits + #define LED_RED_GPIO GPIOC + #define LED_RED_GPIO_PIN GPIO_Pin_4 // PC.04 + #define LED_BLUE_GPIO GPIOC + #define LED_BLUE_GPIO_PIN GPIO_Pin_5 // PC.05 + #define LED_GREEN_GPIO GPIOB + #define LED_GREEN_GPIO_PIN GPIO_Pin_1 // PB.01 #elif defined(PCBX7) #define STATUS_LEDS #define GPIO_LED_GPIO_ON GPIO_SetBits @@ -1203,7 +1289,7 @@ #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream5_IRQHandler #define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF5 #define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) -#elif defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) +#elif defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_T8) #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1) #define INTMODULE_RCC_APB1Periph (RCC_APB1Periph_USART3 | RCC_APB1Periph_TIM2) #define INTMODULE_RCC_APB2Periph 0 @@ -1452,7 +1538,7 @@ #define TELEMETRY_EXTI_IRQn EXTI9_5_IRQn #define TELEMETRY_EXTI_TRIGGER EXTI_Trigger_Rising -#if defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TX12) +#if defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TX12) || defined(RADIO_T8) #define TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER #elif defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019) #define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler @@ -1528,7 +1614,9 @@ // Heartbeat for iXJT / ISRM synchro #define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Falling -#if defined(PCBXLITE) +#if !defined(HARDWARE_EXTERNAL_MODULE) + // No heartbeat +#elif defined(PCBXLITE) #define INTMODULE_HEARTBEAT #define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define INTMODULE_HEARTBEAT_GPIO GPIOD @@ -1628,8 +1716,10 @@ #define TRAINER_MODULE_SBUS_DMA_STREAM EXTMODULE_USART_RX_DMA_STREAM #define TRAINER_MODULE_SBUS_DMA_CHANNEL EXTMODULE_USART_RX_DMA_CHANNEL #else +#if defined(HARDWARE_EXTERNAL_MODULE) #define TRAINER_MODULE_CPPM #define TRAINER_MODULE_SBUS +#endif #define TRAINER_MODULE_RCC_AHB1Periph RCC_AHB1Periph_GPIOC #define TRAINER_MODULE_RCC_APB2Periph RCC_APB2Periph_USART6 #define TRAINER_MODULE_RCC_APB1Periph RCC_APB1Periph_TIM3 @@ -1716,6 +1806,10 @@ #define BACKLIGHT_CCMR1 TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 // Channel 1, PWM #define BACKLIGHT_CCER TIM_CCER_CC1E #define BACKLIGHT_COUNTER_REGISTER BACKLIGHT_TIMER->CCR1 +#elif defined(RADIO_T8) + #define BACKLIGHT_RCC_AHB1Periph 0 + #define BACKLIGHT_RCC_APB1Periph 0 + #define BACKLIGHT_RCC_APB2Periph 0 #elif defined(PCBX7) #define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define BACKLIGHT_RCC_APB1Periph RCC_APB1Periph_TIM4 @@ -1743,7 +1837,7 @@ #define KEYS_BACKLIGHT_RCC_AHB1Periph 0 // LCD driver -#if defined(RADIO_TX12) || defined(RADIO_FAMILY_JUMPER_T12) +#if defined(RADIO_TX12) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_T8) #define LCD_VERTICAL_INVERT #endif #if defined(PCBX9E) @@ -1938,7 +2032,7 @@ #define AUDIO_SPEAKER_ENABLE_GPIO_PIN GPIO_Pin_14 // PD.14 #define HEADPHONE_TRAINER_SWITCH_GPIO GPIOD #define HEADPHONE_TRAINER_SWITCH_GPIO_PIN GPIO_Pin_9 // PD.09 -#elif defined(RADIO_TX12) || defined(RADIO_TLITE) +#elif defined(RADIO_TX12) || defined(RADIO_T8) #define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1) #define AUDIO_MUTE_GPIO GPIOE #define AUDIO_MUTE_GPIO_PIN GPIO_Pin_12 // PE.12 @@ -2068,7 +2162,7 @@ #define BT_USART_IRQn USART3_IRQn // #define BT_DMA_Stream_RX DMA1_Stream1 // #define BT_DMA_Channel_RX DMA_Channel_4 -#elif defined(PCBX9D) || defined(PCBX9DP) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) +#elif defined(PCBX9D) || defined(PCBX9DP) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_T8) #define STORAGE_BLUETOOTH #define BT_RCC_AHB1Periph 0 #define BT_RCC_APB1Periph 0 diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp index a7e7d794d..bca5e3e97 100644 --- a/radio/src/targets/taranis/keys_driver.cpp +++ b/radio/src/targets/taranis/keys_driver.cpp @@ -88,6 +88,10 @@ uint32_t readKeys() result |= 1 << KEY_SHIFT; #endif +#if defined(KEYS_GPIO_PIN_BIND) + if (~KEYS_GPIO_REG_BIND & KEYS_GPIO_PIN_BIND) + result |= 1 << KEY_BIND; +#endif // if (result != 0) TRACE("readKeys(): result=0x%02x", result); return result; @@ -200,7 +204,8 @@ uint32_t switchState(uint8_t index) uint32_t xxx = 0; switch (index) { -#if defined(RADIO_TX12) + +#if defined(RADIO_TX12) || defined(RADIO_T8) ADD_2POS_CASE(A); ADD_3POS_CASE(B, 1); ADD_3POS_CASE(C, 2); @@ -240,6 +245,8 @@ uint32_t switchState(uint8_t index) ADD_2POS_CASE(D); ADD_3POS_CASE(E, 4); ADD_3POS_CASE(F, 5); +#elif defined(RADIO_T8) + ADD_2POS_CASE(D); #elif defined(RADIO_TLITE) // Only 4 switches #elif defined(PCBX7) diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp index 556c250fb..07924671c 100644 --- a/radio/src/targets/taranis/lcd_driver_spi.cpp +++ b/radio/src/targets/taranis/lcd_driver_spi.cpp @@ -20,7 +20,7 @@ #include "opentx.h" -#if defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) +#if defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_T8) #define LCD_CONTRAST_OFFSET -10 #else #define LCD_CONTRAST_OFFSET 160 diff --git a/radio/src/targets/taranis/usb_charger_driver.cpp b/radio/src/targets/taranis/usb_charger_driver.cpp index 7e92c6dbc..78cc3d6a6 100644 --- a/radio/src/targets/taranis/usb_charger_driver.cpp +++ b/radio/src/targets/taranis/usb_charger_driver.cpp @@ -33,5 +33,9 @@ void usbChargerInit() bool usbChargerLed() { +#if defined(SIMU) + return true; +#else return (GPIO_ReadInputDataBit(USB_CHARGER_GPIO, USB_CHARGER_GPIO_PIN) == Bit_RESET && usbPlugged()); +#endif } diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index 25e335042..47b14d381 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -325,7 +325,7 @@ void telemetryInit(uint8_t protocol) } #endif -#if defined(AFHDS3) && !defined(SIMU) +#if defined(AFHDS3) else if (protocol == PROTOCOL_TELEMETRY_AFHDS3) { telemetryPortInvertedInit(AFHDS3_BAUDRATE); telemetryPortSetDirectionInput(); diff --git a/radio/src/tests/switches.cpp b/radio/src/tests/switches.cpp index 4eae3ba5c..504fae354 100644 --- a/radio/src/tests/switches.cpp +++ b/radio/src/tests/switches.cpp @@ -106,7 +106,7 @@ TEST(evalLogicalSwitches, playFile) char filename[AUDIO_FILENAME_MAXLEN+1]; #if defined(EEPROM) -#define MODELNAME "MODEL01" +#define MODELNAME TR_MODEL "01" #else #define MODELNAME "Model00" #endif diff --git a/radio/src/trainer.cpp b/radio/src/trainer.cpp index 6c6bc7b79..c4c3c0c4f 100644 --- a/radio/src/trainer.cpp +++ b/radio/src/trainer.cpp @@ -26,8 +26,8 @@ uint8_t currentTrainerMode = 0xff; void checkTrainerSignalWarning() { - enum PpmInValidState_t { - PPM_IN_IS_NOT_USED=0, + enum { + PPM_IN_IS_NOT_USED = 0, PPM_IN_IS_VALID, PPM_IN_INVALID }; @@ -137,17 +137,20 @@ void checkTrainerSettings() #if defined(TRAINER_BATTERY_COMPARTMENT) case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: #if defined(AUX_SERIAL) - if (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) + if (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER) { auxSerialSbusInit(); - else + break; + } #endif + #if defined(AUX2_SERIAL) - if (g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER) + if (g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER) { aux2SerialSbusInit(); - else + break; + } #endif - init_trainer_capture(); - break; + + // no break #endif case TRAINER_MODE_MASTER_TRAINER_JACK: diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 48d01b4bc..455d6490d 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -81,6 +81,7 @@ ISTR(POTTYPES); ISTR(SLIDERTYPES); ISTR(ANTENNA_MODES); ISTR(SPORT_UPDATE_POWER_MODES); +ISTR(SPORT_MODES); #if defined(PCBSKY9X) && defined(REVX) ISTR(VOUTPUT_TYPE); @@ -829,3 +830,4 @@ const char STR_ABOUT_PARENTS_3[] = TR_ABOUT_PARENTS_3; const char STR_ABOUT_PARENTS_4[] = TR_ABOUT_PARENTS_4; const char STR_AUTH_FAILURE[] = TR_AUTH_FAILURE; +const char STR_PROTOCOL[] = TR_PROTOCOL; diff --git a/radio/src/translations.h b/radio/src/translations.h index 73c843389..a9131d8a5 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -161,6 +161,7 @@ extern const char STR_R9M_PXX2_RF_PROTOCOLS[]; extern const char STR_DSM_PROTOCOLS[]; extern const char STR_MULTI_PROTOCOLS[]; extern const char STR_MULTI_POWER[]; +extern const char STR_SPORT_MODES[]; #if defined(AFHDS3) extern const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[]; @@ -964,6 +965,7 @@ extern const char STR_ABOUT_PARENTS_3[]; extern const char STR_ABOUT_PARENTS_4[]; extern const char STR_AUTH_FAILURE[]; +extern const char STR_PROTOCOL[]; #define CHR_HOUR TR_CHR_HOUR #define CHR_INPUT TR_CHR_INPUT diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt index 967f94c40..59eae1a46 100644 --- a/radio/src/translations/cz.h.txt +++ b/radio/src/translations/cz.h.txt @@ -294,6 +294,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Mínus" @@ -441,7 +444,7 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Výstup" #endif -#define TR_PROTO INDENT "Protokol" +#define TR_PROTOCOL "Protokol" #define TR_PPMFRAME INDENT "PPM modulace" #define TR_REFRESHRATE TR(INDENT "Obnovit", INDENT "Obn. frekv.") #define STR_WARN_BATTVOLTAGE TR(INDENT "Výstup VBAT: ", INDENT "Varování: výstupní hodnota VBAT: ") @@ -780,7 +783,7 @@ #define TR_NO_MODELS_ON_SD "žádný model" BREAKSPACE "na SD" #define TR_NO_BITMAPS_ON_SD "žádné obrázky" BREAKSPACE "na SD" #define TR_NO_SCRIPTS_ON_SD "žádný skript" BREAKSPACE "na SD" -#define TR_SCRIPT_SYNTAX_ERROR "Syntaktická chyba skriptu" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntaktická chyba", "Syntaktická chyba skriptu") #define TR_SCRIPT_PANIC "Script zmaten" #define TR_SCRIPT_KILLED "Script ukončen" #define TR_SCRIPT_ERROR "Neznámá chyba" diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt index c8d872ed0..fb36f0021 100644 --- a/radio/src/translations/de.h.txt +++ b/radio/src/translations/de.h.txt @@ -300,6 +300,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -443,8 +446,8 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO TR(INDENT "Protok.", INDENT "Protokoll") - #define TR_PPMFRAME INDENT "PPM-Frame" +#define TR_PROTOCOL TR("Protok.", "Protokoll") +#define TR_PPMFRAME INDENT "PPM-Frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") #define TR_WARN_5VOLTS "Warning: output level is 5 volts" @@ -782,7 +785,7 @@ #define TR_NO_MODELS_ON_SD "Kein Modelle" BREAKSPACE "auf SD" #define TR_NO_BITMAPS_ON_SD "Keine Bitmaps" BREAKSPACE "auf SD" #define TR_NO_SCRIPTS_ON_SD "Keine Skripte" BREAKSPACE "auf SD" -#define TR_SCRIPT_SYNTAX_ERROR "Skript Syntaxfehler" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntaxfehler", "Skript Syntaxfehler") #define TR_SCRIPT_PANIC "Skript Panik" #define TR_SCRIPT_KILLED "Skript beendet" #define TR_SCRIPT_ERROR "Unbekannter Fehler" diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index dc4ae41ce..f66e99a33 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -300,6 +300,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -442,7 +445,7 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO TR(INDENT "Proto", INDENT "Protocol") +#define TR_PROTOCOL TR("Proto", "Protocol") #define TR_PPMFRAME INDENT "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") @@ -786,7 +789,7 @@ #define TR_NO_MODELS_ON_SD "No models" BREAKSPACE "on SD" #define TR_NO_BITMAPS_ON_SD "No bitmaps" BREAKSPACE "on SD" #define TR_NO_SCRIPTS_ON_SD "No scripts" BREAKSPACE "on SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Script syntax error") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script killed" #define TR_SCRIPT_ERROR "Unknown error" diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt index 24bf15860..0e5fa3dc7 100644 --- a/radio/src/translations/es.h.txt +++ b/radio/src/translations/es.h.txt @@ -297,6 +297,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -441,7 +444,7 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO TR(INDENT"Proto",INDENT"Protocolo") +#define TR_PROTOCOL TR("Proto", "Protocolo") #define TR_PPMFRAME INDENT "Trama PPM" #define TR_REFRESHRATE TR(INDENT "Refresco", INDENT "Velocidad refresco") #define STR_WARN_BATTVOLTAGE TR(INDENT "Salida es VBAT: ", INDENT "Aviso: señal salida es VBAT: ") @@ -783,7 +786,7 @@ #define TR_NO_MODELS_ON_SD "Sin modelos en SD" #define TR_NO_BITMAPS_ON_SD "Sin imágenes en SD" #define TR_NO_SCRIPTS_ON_SD "No scripts en SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Script syntax error") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script killed" #define TR_SCRIPT_ERROR "Error desconocido" diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt index ae5d03fb8..0bd9c954f 100644 --- a/radio/src/translations/fi.h.txt +++ b/radio/src/translations/fi.h.txt @@ -318,6 +318,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -455,7 +458,7 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO TR(INDENT "Proto", INDENT "Protocol") +#define TR_PROTOCOL TR("Proto", "Protocol") #define TR_PPMFRAME TR("PPM frame", INDENT "PPM frame") #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") @@ -799,7 +802,7 @@ #define TR_NO_MODELS_ON_SD "No Models on SD" #define TR_NO_BITMAPS_ON_SD "No Bitmaps on SD" #define TR_NO_SCRIPTS_ON_SD "No Scripts on SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Script syntax error") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script killed" #define TR_SCRIPT_ERROR "Unknown error" diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt index d124583e8..fb818f7e8 100644 --- a/radio/src/translations/fr.h.txt +++ b/radio/src/translations/fr.h.txt @@ -320,6 +320,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Moins" @@ -461,8 +464,8 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Sortie" #endif -#define TR_PROTO TR(INDENT "Proto.", INDENT "Protocole") - #define TR_PPMFRAME INDENT "Trame PPM" +#define TR_PROTOCOL TR("Proto.", "Protocole") +#define TR_PPMFRAME INDENT "Trame PPM" #define TR_REFRESHRATE INDENT "Période" #define STR_WARN_BATTVOLTAGE TR(INDENT "Signal est VBAT: ", INDENT "ATTENTION: signal est à VBAT: ") #define TR_WARN_5VOLTS "Warning: output level is 5 volts" @@ -802,7 +805,7 @@ #define TR_NO_MODELS_ON_SD "Aucun modèle SD" #define TR_NO_BITMAPS_ON_SD "Aucun Bitmap SD" #define TR_NO_SCRIPTS_ON_SD "Aucun Script SD" -#define TR_SCRIPT_SYNTAX_ERROR "Erreur syntaxe script" +#define TR_SCRIPT_SYNTAX_ERROR TR("Erreur syntaxe", "Erreur syntaxe script") #define TR_SCRIPT_PANIC "Script bloqué" #define TR_SCRIPT_KILLED "Script interrompu" #define TR_SCRIPT_ERROR "Erreur inconnue" diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt index 4034b6664..9a0785a1e 100644 --- a/radio/src/translations/it.h.txt +++ b/radio/src/translations/it.h.txt @@ -321,6 +321,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -463,8 +466,8 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Uscita" #endif -#define TR_PROTO TR(INDENT "Protoc.", INDENT "Protocollo") - #define TR_PPMFRAME INDENT "Frame PPM" +#define TR_PROTOCOL TR("Protoc.", "Protocollo") +#define TR_PPMFRAME INDENT "Frame PPM" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Uscita VBAT: ", INDENT "Att.: livel. uscita VBAT: ") #define TR_WARN_5VOLTS "Attenzione: il livello d'uscita è 5 Volts" @@ -801,7 +804,7 @@ #define TR_NO_MODELS_ON_SD "No Model." BREAKSPACE "su SD" #define TR_NO_BITMAPS_ON_SD "No Immag." BREAKSPACE "su SD" #define TR_NO_SCRIPTS_ON_SD "No Scripts" BREAKSPACE "su SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script errore sintassi" +#define TR_SCRIPT_SYNTAX_ERROR TR("Errore sintassi", "Script errore sintassi") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script fermato" #define TR_SCRIPT_ERROR "Errore sconosciuto" diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt index 098a54af7..13f567589 100644 --- a/radio/src/translations/nl.h.txt +++ b/radio/src/translations/nl.h.txt @@ -298,6 +298,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -442,8 +445,8 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO TR(INDENT "Proto", INDENT "Protocol") - #define TR_PPMFRAME INDENT "PPM frame" +#define TR_PROTOCOL TR("Proto", "Protocol") +#define TR_PPMFRAME INDENT "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") #define TR_WARN_5VOLTS "Warning: output level is 5 volts" @@ -787,7 +790,7 @@ #define TR_NO_MODELS_ON_SD "Geen Modellen" BREAKSPACE "op SD" #define TR_NO_BITMAPS_ON_SD "Geen Bitmaps" BREAKSPACE "op SD" #define TR_NO_SCRIPTS_ON_SD "Geen Scripts" BREAKSPACE "op SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Script syntax error") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script killed" #define TR_SCRIPT_ERROR "Unknown error" diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt index 96ae0b342..bf59714cf 100644 --- a/radio/src/translations/pl.h.txt +++ b/radio/src/translations/pl.h.txt @@ -318,6 +318,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -462,8 +465,8 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Wyjście" #endif -#define TR_PROTO TR(INDENT "Proto", INDENT "Protokół") - #define TR_PPMFRAME INDENT "Ramka PPM" +#define TR_PROTOCOL TR("Proto", "Protokół") +#define TR_PPMFRAME INDENT "Ramka PPM" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") #define TR_WARN_5VOLTS "Warning: output level is 5 volts" @@ -800,7 +803,7 @@ #define TR_NO_MODELS_ON_SD "Brak modelu na SD" #define TR_NO_BITMAPS_ON_SD "Brak obrazków na SD" #define TR_NO_SCRIPTS_ON_SD "Brak skryptów na SD" -#define TR_SCRIPT_SYNTAX_ERROR "Skrypt:syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Skrypt:syntax error") #define TR_SCRIPT_PANIC "Skrypt:panic" #define TR_SCRIPT_KILLED "Skrypt:killed" #define TR_SCRIPT_ERROR "Nieznany błąd" @@ -1130,18 +1133,22 @@ #define TR_ABOUT_MARTIN_2 "Projekty graficzne" #if defined(MANUFACTURER_FRSKY) - #define TR_ABOUT_HARDWARE_1 "FrSky" - #define TR_ABOUT_HARDWARE_2 "Proucent/projektant Hardware" - #define TR_ABOUT_HARDWARE_3 "Współautor firmware" + #define TR_ABOUT_HARDWARE_1 "FrSky" + #define TR_ABOUT_HARDWARE_2 "Proucent/projektant Hardware" + #define TR_ABOUT_HARDWARE_3 "Współautor firmware" #elif defined(MANUFACTURER_RADIOMASTER) - #define TR_ABOUT_HARDWARE_1 "Radiomaster" - #define TR_ABOUT_HARDWARE_2 "Proucent/projektant Hardware" - #define TR_ABOUT_HARDWARE_3 "Współautor firmware" + #define TR_ABOUT_HARDWARE_1 "Radiomaster" + #define TR_ABOUT_HARDWARE_2 "Proucent/projektant Hardware" + #define TR_ABOUT_HARDWARE_3 "Współautor firmware" #elif defined(MANUFACTURER_JUMPER) - #define TR_ABOUT_HARDWARE_1 "JumperRC" - #define TR_ABOUT_HARDWARE_2 "Proucent/projektant Hardware" - #define TR_ABOUT_HARDWARE_3 "Współautor firmware" + #define TR_ABOUT_HARDWARE_1 "JumperRC" + #define TR_ABOUT_HARDWARE_2 "Proucent/projektant Hardware" + #define TR_ABOUT_HARDWARE_3 "Współautor firmware" #else + #define TR_ABOUT_HARDWARE_1 "Brent Nelson" + #define TR_ABOUT_HARDWARE_2 "Sky9x designer/výrobce" + #define TR_ABOUT_HARDWARE_3 "" +#endif #define TR_ABOUT_PARENTS_1 "Projekty macierzyste" #define TR_ABOUT_PARENTS_2 TR("Ersky9x (Mike Blandford)", "Ersky9x (Mike Blandford)") diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt index 8fbe1a59e..8c794822e 100644 --- a/radio/src/translations/pt.h.txt +++ b/radio/src/translations/pt.h.txt @@ -311,6 +311,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -459,7 +462,7 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO INDENT"Proto" +#define TR_PROTOCOL "Proto" #define TR_PPMFRAME "PPM frame" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") @@ -801,7 +804,7 @@ #define TR_NO_MODELS_ON_SD "Sem Modelo no SD" #define TR_NO_BITMAPS_ON_SD "No Bitmaps on SD" #define TR_NO_SCRIPTS_ON_SD "No Scripts on SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Script syntax error") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script killed" #define TR_SCRIPT_ERROR "Unknown error" @@ -1240,7 +1243,7 @@ #define TR_MENU_INVERT "Invert" #define TR_JITTER_FILTER "ADC Filter" #define TR_RTC_CHECK TR("Check RTC", "Check RTC voltage") -#define TR_AUTH_FAILURE "Auth-failure" +#define TR_AUTH_FAILURE "Auth-failure" #define ZSTR_VFR "VFR" #define ZSTR_RSSI "RSSI" diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt index 3b45f2655..54c081eb3 100644 --- a/radio/src/translations/se.h.txt +++ b/radio/src/translations/se.h.txt @@ -312,6 +312,9 @@ #elif defined(RADIO_TX12) #define LEN_VKEYS "\005" #define TR_VKEYS "Exit\0""Enter""Up\0 ""Down\0""SYS\0 ""MDL\0 ""TELE\0" +#elif defined(RADIO_T8) + #define LEN_VKEYS "\005" + #define TR_VKEYS "RTN\0 ""ENTER""PGUP\0""PGDN\0""SYS\0 ""MDL\0 ""UP\0 ""DOWN\0" #elif defined(PCBTARANIS) #define LEN_VKEYS "\005" #define TR_VKEYS "Menu\0""Exit\0""Enter""Page\0""Plus\0""Minus" @@ -461,8 +464,8 @@ #if defined(PCBSKY9X) && defined(REVX) #define TR_OUTPUT_TYPE INDENT "Output" #endif -#define TR_PROTO TR(INDENT "Proto", INDENT "Protokoll") - #define TR_PPMFRAME INDENT "PPM-paket" +#define TR_PROTOCOL TR("Proto", "Protokoll") +#define TR_PPMFRAME INDENT "PPM-paket" #define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate") #define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ") #define TR_WARN_5VOLTS "Warning: output level is 5 volts" @@ -800,7 +803,7 @@ #define TR_NO_MODELS_ON_SD "Ingen modell i SD" #define TR_NO_BITMAPS_ON_SD "Ikoner saknas på SD" #define TR_NO_SCRIPTS_ON_SD "Programkod saknas på SD" -#define TR_SCRIPT_SYNTAX_ERROR "Script syntax error" +#define TR_SCRIPT_SYNTAX_ERROR TR("Syntax error", "Script syntax error") #define TR_SCRIPT_PANIC "Script panic" #define TR_SCRIPT_KILLED "Script killed" #define TR_SCRIPT_ERROR "Unknown error" diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index 2702a0d69..74735bc7f 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -109,6 +109,9 @@ #define LEN_R9M_PXX2_RF_PROTOCOLS "\006" #define TR_R9M_PXX2_RF_PROTOCOLS "ACCESS""FCC\0 ""EU\0 ""Flex" +#define LEN_SPORT_MODES "\014" +#define TR_SPORT_MODES "S.PORT\0 ""F.PORT\0 ""FBUS(FPORT2)" + #define LEN_R9M_REGION "\006" #define TR_R9M_REGION "FCC\0 ""EU\0 ""868MHz""915MHz" @@ -128,7 +131,7 @@ #define TR_DSM_PROTOCOLS "LP45""DSM2""DSMX" #define LEN_MULTI_PROTOCOLS "\007" -#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""Futaba\0""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""Height\0""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 ""Kyosho\0""RadLink""ExpLRS\0""Realacc""OMP\0 ""M-Link\0""Wfly-RF" +#define TR_MULTI_PROTOCOLS "FlySky\0""Hubsan\0""FrSky\0 ""Hisky\0 ""V2x2\0 ""DSM\0 ""Devo\0 ""YD717\0 ""KN\0 ""SymaX\0 ""SLT\0 ""CX10\0 ""CG023\0 ""Bayang\0""ESky\0 ""MT99XX\0""MJXq\0 ""Shenqi\0""FY326\0 ""Futaba\0""J6 Pro\0""FQ777\0 ""Assan\0 ""Hontai\0""OpenLrs""FlSky2A""Q2x2\0 ""Walkera""Q303\0 ""GW008\0 ""DM002\0 ""Cabell\0""Esky150""H8 3D\0 ""Corona\0""CFlie\0 ""Hitec\0 ""WFly\0 ""Bugs\0 ""BugMini""Traxxas""NCC1701""E01X\0 ""V911S\0 ""GD00X\0 ""V761\0 ""KF606\0 ""Redpine""Potensi""ZSX\0 ""Height\0""Scanner""FrSkyRX""FS2A_RX""HoTT\0 ""FX816\0 ""BayanRX""Pelikan""Tiger\0 ""XK\0 ""XN297DU""FrSkyX2""FrSkyR9""Propel\0""FrSkyL\0""Skyartc""ESky-v2""DSM RX\0""JJRC345""Q90C\0 ""Kyosho\0""RadLink""ExpLRS\0""Realacc""OMP\0 ""M-Link\0""Wfly 2\0""E016Hv2" #define LEN_MULTI_POWER "\005" #define TR_MULTI_POWER "10mW\0""25mW\0""50mW\0""100mW""200mW""300mW""500mW""1W\0 ""2W\0 " diff --git a/radio/util/build-firmware.py b/radio/util/build-firmware.py index 66d9f053d..b7132d510 100755 --- a/radio/util/build-firmware.py +++ b/radio/util/build-firmware.py @@ -148,6 +148,11 @@ def main(): cmake_options["PCBREV"] = "TX12" firmware_options = options_radiomaster_tx12 maxsize = 65536 * 8 + elif board_name == "t8": + cmake_options["PCB"] = "X7" + cmake_options["PCBREV"] = "T8" + firmware_options = options_radiomaster_t8 + maxsize = 65536 * 8 elif board_name == "t16": cmake_options["PCB"] = "X10" cmake_options["PCBREV"] = "T16" diff --git a/radio/util/fwoptions.py b/radio/util/fwoptions.py index f4438db44..7b2a01edd 100755 --- a/radio/util/fwoptions.py +++ b/radio/util/fwoptions.py @@ -258,6 +258,17 @@ options_radiomaster_tx12 = { "afhds3": ("AFHDS3", "YES", "NO") } +options_radiomaster_t8 = { + "noheli": ("HELI", "NO", "YES"), + "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), + "lua": ("LUA", "YES", "NO_MODEL_SCRIPTS"), + "nogvars": ("GVARS", "NO", "YES"), + "faimode": ("FAI", "YES", None), + "faichoice": ("FAI", "CHOICE", None), + "nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"), + "bindkey": ("BIND_KEY", "NO", "YES"), +} + options_radiomaster_tx16s = { "noheli": ("HELI", "NO", "YES"), "ppmus": ("PPM_UNIT", "US", "PERCENT_PREC1"), diff --git a/tools/build-radiomaster.py b/tools/build-radiomaster.py index 985bc705a..564463537 100755 --- a/tools/build-radiomaster.py +++ b/tools/build-radiomaster.py @@ -28,6 +28,18 @@ boards = { "PCB": "X7", "PCBREV": "TX12", "DEFAULT_MODE": "2", + }, + "T8_1": { + "PCB": "X7", + "PCBREV": "T8", + "DEFAULT_MODE": "1", + "RADIOMASTER_RTF_RELEASE": "YES", + }, + "T8_2": { + "PCB": "X7", + "PCBREV": "T8", + "DEFAULT_MODE": "2", + "RADIOMASTER_RTF_RELEASE": "YES", } } diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh index 4e2ca83ea..be5940308 100755 --- a/tools/commit-tests.sh +++ b/tools/commit-tests.sh @@ -88,7 +88,7 @@ fi if [[ " X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITE rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X9LITE -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X9LITE -DHELI=YES -DGVARS=YES -DTRANSLATIONS=CZ "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -97,7 +97,7 @@ fi if [[ " X9LITES X9LITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9LITES rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES -DMULTIMODULE=NO "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X9LITES -DHELI=YES -DGVARS=YES -DMULTIMODULE=NO -DTRANSLATIONS=DE "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -106,7 +106,7 @@ fi if [[ " X7 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X7 rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DHELI=YES -DGVARS=YES -DTRANSLATIONS=ES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -115,7 +115,7 @@ fi if [[ " X7ACCESS X7 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X7 ACCESS rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=ACCESS -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=ACCESS -DHELI=YES -DGVARS=YES -DTRANSLATIONS=FR "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -124,7 +124,7 @@ fi if [[ " T12 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on T12 rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=T12 -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=T12 -DHELI=YES -DGVARS=YES -DTRANSLATIONS=IT "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -133,6 +133,15 @@ fi if [[ " TX12 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on TX12 rm -rf ./* + cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=TX12 -DHELI=YES -DGVARS=YES -DTRANSLATIONS=PT "${SRCDIR}" + make -j"${CORES}" ${FIRMARE_TARGET} + make -j"${CORES}" libsimulator + make -j"${CORES}" tests-radio +fi + +if [[ " T8 X7 ALL " =~ \ ${FLAVOR}\ ]] ; then + # OpenTX on T8 + rm -rf ./* cmake "${COMMON_OPTIONS}" -DPCB=X7 -DPCBREV=TX12 -DHELI=YES -DGVARS=YES "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator @@ -160,7 +169,7 @@ fi if [[ " XLITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X-Lite rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=XLITE -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=XLITE -DHELI=YES -DGVARS=YES -DTRANSLATIONS=SK "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -169,7 +178,7 @@ fi if [[ " XLITES XLITE ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X-Lites rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=XLITES -DHELI=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=XLITES -DHELI=YES -DGVARS=YES -DTRANSLATIONS=SE "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -178,7 +187,7 @@ fi if [[ " X9D X9 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9D rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X9D -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X9D -DHELI=YES -DLUA=YES -DGVARS=YES -DTRANSLATIONS=PL "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -187,7 +196,7 @@ fi if [[ " X9D+ X9 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9D+ rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X9D+ -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X9D+ -DHELI=YES -DLUA=YES -DGVARS=YES -DTRANSLATIONS=HU "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio @@ -196,7 +205,7 @@ fi if [[ " X9D+2019 X9 ALL " =~ \ ${FLAVOR}\ ]] ; then # OpenTX on X9D+ 2019 rm -rf ./* - cmake "${COMMON_OPTIONS}" -DPCB=X9D+ -DPCBREV=2019 -DHELI=YES -DLUA=YES -DGVARS=YES "${SRCDIR}" + cmake "${COMMON_OPTIONS}" -DPCB=X9D+ -DPCBREV=2019 -DHELI=YES -DLUA=YES -DGVARS=YES -DTRANSLATIONS=NL "${SRCDIR}" make -j"${CORES}" ${FIRMARE_TARGET} make -j"${CORES}" libsimulator make -j"${CORES}" tests-radio