diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml
index 4968fe33c..0100a0175 100644
--- a/.github/workflows/actions.yml
+++ b/.github/workflows/actions.yml
@@ -78,7 +78,7 @@ jobs:
- t16
- t18
- t8;zorro
- - tlite
+ - tlite;tpro
- tx12
- tx16s
- x10;x10-access
diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt
index 6914f667c..9c98e519d 100644
--- a/companion/src/CMakeLists.txt
+++ b/companion/src/CMakeLists.txt
@@ -323,6 +323,8 @@ elseif(PCB STREQUAL X7 AND PCBREV STREQUAL T12)
set(FLAVOUR t12)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TLITE)
set(FLAVOUR tlite)
+elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TPRO)
+ set(FLAVOUR tpro)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL TX12)
set(FLAVOUR tx12)
elseif(PCB STREQUAL X7 AND PCBREV STREQUAL ZORRO)
diff --git a/companion/src/companion.qrc b/companion/src/companion.qrc
index c34fcd295..9bdbdee8b 100644
--- a/companion/src/companion.qrc
+++ b/companion/src/companion.qrc
@@ -188,6 +188,10 @@
images/simulator/JumperTLITE/right_top.png
images/simulator/JumperTLITE/right_bottom.png
images/simulator/JumperTLITE/top.png
+ images/simulator/JumperTPRO/bottom.png
+ images/simulator/JumperTPRO/left.png
+ images/simulator/JumperTPRO/right.png
+ images/simulator/JumperTPRO/top.png
images/simulator/TX12/left.png
images/simulator/TX12/left-pageup.png
images/simulator/TX12/left-pagedn.png
diff --git a/companion/src/constants.h b/companion/src/constants.h
index 63ba0a9b1..b06792a91 100644
--- a/companion/src/constants.h
+++ b/companion/src/constants.h
@@ -43,6 +43,7 @@
#define CPN_MAX_POTS (CPN_MAX_KNOBS + CPN_MAX_SLIDERS)
#define CPN_MAX_CYC 3
#define CPN_MAX_SWITCHES 32
+#define CPN_MAX_FUNCTION_SWITCHES 6
#define CPN_MAX_MOUSE_ANALOGS 2
#define CPN_MAX_GYRO_ANALOGS 2
#define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_MOUSE_ANALOGS + CPN_MAX_GYRO_ANALOGS)
diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp
index 18605ea10..af164355c 100644
--- a/companion/src/firmwares/boards.cpp
+++ b/companion/src/firmwares/boards.cpp
@@ -82,6 +82,8 @@ uint32_t Boards::getFourCC(Type board)
return 0x3D78746F;
case BOARD_JUMPER_TLITE:
return 0x4278746F;
+ case BOARD_JUMPER_TPRO:
+ return 0x4678746F;
case BOARD_JUMPER_T16:
return 0x3F78746F;
case BOARD_JUMPER_T18:
@@ -121,6 +123,7 @@ int Boards::getEEpromSize(Board::Type board)
case BOARD_TARANIS_X9E:
case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
+ case BOARD_JUMPER_TPRO:
case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_T8:
case BOARD_RADIOMASTER_ZORRO:
@@ -160,6 +163,7 @@ int Boards::getFlashSize(Type board)
case BOARD_TARANIS_X9E:
case BOARD_JUMPER_T12:
case BOARD_JUMPER_TLITE:
+ case BOARD_JUMPER_TPRO:
case BOARD_RADIOMASTER_TX12:
case BOARD_RADIOMASTER_ZORRO:
case BOARD_RADIOMASTER_T8:
@@ -196,7 +200,7 @@ SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
- else if (IS_TARANIS_XLITE(board) || IS_JUMPER_TLITE(board)) {
+ else if (IS_TARANIS_XLITE(board) || IS_JUMPER_TLITE(board) || IS_JUMPER_TPRO(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@@ -365,7 +369,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 1;
else if (IS_JUMPER_TLITE(board))
return 0;
- else if (IS_TARANIS_SMALL(board))
+ else if (IS_TARANIS_SMALL(board) || IS_JUMPER_TPRO(board))
return 2;
else if (IS_TARANIS_X9E(board))
return 4;
@@ -427,7 +431,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
return 7;
else if (board == BOARD_TARANIS_X7)
return 8;
- else if (board == BOARD_JUMPER_TLITE)
+ else if (board == BOARD_JUMPER_TLITE || board == BOARD_JUMPER_TPRO)
return 4;
else if (board == BOARD_FLYSKY_NV14)
return 8;
@@ -447,7 +451,7 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case FactoryInstalledSwitches:
if (IS_TARANIS_X9E(board))
return 8;
- else if (IS_JUMPER_TLITE(board))
+ else if (IS_JUMPER_TLITE(board) || IS_JUMPER_TPRO(board))
return 4;
else if(IS_RADIOMASTER_ZORRO(board))
return 8;
@@ -479,6 +483,9 @@ int Boards::getCapability(Board::Type board, Board::Capability capability)
case HasColorLcd:
return IS_FAMILY_HORUS_OR_T16(board);
+ case NumFunctionSwitches:
+ return IS_JUMPER_TPRO(board) ? 6 : 0;
+
default:
return 0;
}
@@ -645,6 +652,8 @@ QString Boards::getBoardName(Board::Type board)
return "Jumper T12";
case BOARD_JUMPER_TLITE:
return "Jumper T-Lite";
+ case BOARD_JUMPER_TPRO:
+ return "Jumper T-Pro";
case BOARD_JUMPER_T16:
return "Jumper T16";
case BOARD_JUMPER_T18:
diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h
index 2bc37a458..ea0476bda 100644
--- a/companion/src/firmwares/boards.h
+++ b/companion/src/firmwares/boards.h
@@ -63,6 +63,7 @@ namespace Board {
BOARD_JUMPER_TLITE,
BOARD_FLYSKY_NV14,
BOARD_RADIOMASTER_ZORRO,
+ BOARD_JUMPER_TPRO,
BOARD_TYPE_COUNT,
BOARD_TYPE_MAX = BOARD_TYPE_COUNT - 1
};
@@ -143,7 +144,8 @@ namespace Board {
NumTrims,
NumTrimSwitches,
HasRTC,
- HasColorLcd
+ HasColorLcd,
+ NumFunctionSwitches
};
struct SwitchInfo
@@ -237,6 +239,11 @@ inline bool IS_JUMPER_TLITE(Board::Type board)
return board == Board::BOARD_JUMPER_TLITE;
}
+inline bool IS_JUMPER_TPRO(Board::Type board)
+{
+ return board == Board::BOARD_JUMPER_TPRO;
+}
+
inline bool IS_JUMPER_T16(Board::Type board)
{
return board == Board::BOARD_JUMPER_T16;
@@ -335,7 +342,7 @@ inline bool IS_TARANIS_X9E(Board::Type board)
inline bool IS_TARANIS_SMALL(Board::Type board)
{
- return IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_FAMILY_T12(board);
+ return IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_X9LITE(board) || IS_FAMILY_T12(board) || IS_JUMPER_TPRO(board);
}
inline bool IS_TARANIS(Board::Type board)
diff --git a/companion/src/firmwares/eepromimportexport.h b/companion/src/firmwares/eepromimportexport.h
index 965810731..bcb66ab65 100644
--- a/companion/src/firmwares/eepromimportexport.h
+++ b/companion/src/firmwares/eepromimportexport.h
@@ -568,7 +568,7 @@ class TransformedField: public DataField {
virtual void afterImport() = 0;
- int dump(int level, int offset) override
+ int dump(int level=0, int offset=0) override
{
beforeExport();
return field.dump(level, offset);
diff --git a/companion/src/firmwares/eeprominterface.h b/companion/src/firmwares/eeprominterface.h
index 02ab4884d..099501c9d 100644
--- a/companion/src/firmwares/eeprominterface.h
+++ b/companion/src/firmwares/eeprominterface.h
@@ -162,7 +162,8 @@ enum Capability {
HasAntennaChoice,
HasADCJitterFilter,
HasTelemetryBaudrate,
- TopBarZones
+ TopBarZones,
+ FunctionSwitches
};
class EEPROMInterface
diff --git a/companion/src/firmwares/modeldata.cpp b/companion/src/firmwares/modeldata.cpp
index e6b12ca5e..64e8879d6 100644
--- a/companion/src/firmwares/modeldata.cpp
+++ b/companion/src/firmwares/modeldata.cpp
@@ -212,6 +212,17 @@ void ModelData::setDefaultMixes(const GeneralSettings & settings)
}
}
+void ModelData::setDefaultFunctionSwitches(int functionSwitchCount)
+{
+ if (functionSwitchCount == 0)
+ return;
+
+ for (int i = 0; i < functionSwitchCount; i++) {
+ functionSwitchConfig |= (Board::SWITCH_2POS << 2 * i);
+ functionSwitchGroup |= (1 << 2 * i);
+ }
+}
+
void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settings)
{
clear();
@@ -221,6 +232,7 @@ void ModelData::setDefaultValues(unsigned int id, const GeneralSettings & settin
moduleData[i].modelId = id + 1;
}
setDefaultMixes(settings);
+ setDefaultFunctionSwitches(getCurrentFirmware()->getCapability(FunctionSwitches));
}
int ModelData::getTrimValue(int phaseIdx, int trimIdx)
@@ -1641,3 +1653,77 @@ AbstractStaticItemModel * ModelData::trainerModeItemModel(const GeneralSettings
mdl->loadItemList();
return mdl;
}
+
+QString ModelData::funcSwitchConfigToString(const int index) const
+{
+ if (index < CPN_MAX_FUNCTION_SWITCHES)
+ return funcSwitchConfigToString(index, (int)(functionSwitchConfig >> (2 * index)) & 0x03);
+ else
+ return CPN_STR_UNKNOWN_ITEM;
+}
+
+// static
+QString ModelData::funcSwitchConfigToString(const int index, const int value)
+{
+ switch (value) {
+ case FUNC_SWITCH_CONFIG_NONE:
+ return tr("NONE");
+ case FUNC_SWITCH_CONFIG_TOGGLE:
+ return tr("TOGGLE");
+ case FUNC_SWITCH_CONFIG_2POS:
+ return tr("2POS");
+ default:
+ return CPN_STR_UNKNOWN_ITEM;
+ }
+}
+
+// static
+AbstractStaticItemModel * ModelData::funcSwitchConfigItemModel()
+{
+ AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
+ mdl->setName(AIM_MODELDATA_FUNCSWITCHCONFIG);
+
+ for (int i = FUNC_SWITCH_CONFIG_FIRST; i <= FUNC_SWITCH_CONFIG_LAST; i++) {
+ mdl->appendToItemList(funcSwitchConfigToString(0, i), i);
+ }
+
+ mdl->loadItemList();
+ return mdl;
+}
+
+QString ModelData::funcSwitchStartToString(const int index) const
+{
+ if (index < CPN_MAX_FUNCTION_SWITCHES)
+ return funcSwitchStartToString(index, (int)(functionSwitchStartConfig >> (2 * index)) & 0x03);
+ else
+ return CPN_STR_UNKNOWN_ITEM;
+}
+
+// static
+QString ModelData::funcSwitchStartToString(const int index, const int value)
+{
+ switch (value) {
+ case FUNC_SWITCH_START_INACTIVE:
+ return CPN_STR_SW_INDICATOR_UP;
+ case FUNC_SWITCH_START_ACTIVE:
+ return CPN_STR_SW_INDICATOR_DN;
+ case FUNC_SWITCH_START_PREVIOUS:
+ return "=";
+ default:
+ return CPN_STR_UNKNOWN_ITEM;
+ }
+}
+
+// static
+AbstractStaticItemModel * ModelData::funcSwitchStartItemModel()
+{
+ AbstractStaticItemModel * mdl = new AbstractStaticItemModel();
+ mdl->setName(AIM_MODELDATA_FUNCSWITCHSTART);
+
+ for (int i = FUNC_SWITCH_START_FIRST; i <= FUNC_SWITCH_START_LAST; i++) {
+ mdl->appendToItemList(funcSwitchStartToString(0, i), i);
+ }
+
+ mdl->loadItemList();
+ return mdl;
+}
diff --git a/companion/src/firmwares/modeldata.h b/companion/src/firmwares/modeldata.h
index fbdd8f9c7..6a1443c12 100644
--- a/companion/src/firmwares/modeldata.h
+++ b/companion/src/firmwares/modeldata.h
@@ -35,6 +35,7 @@
#include "telem_data.h"
#include "timerdata.h"
#include "customisation_data.h"
+#include "generalsettings.h"
#include
@@ -43,6 +44,8 @@ class RadioDataConversionState;
class AbstractStaticItemModel;
constexpr char AIM_MODELDATA_TRAINERMODE[] {"modeldata.trainermode"};
+constexpr char AIM_MODELDATA_FUNCSWITCHCONFIG[] {"modeldata.funcswitchconfig"};
+constexpr char AIM_MODELDATA_FUNCSWITCHSTART[] {"modeldata.funcswitchstart"};
#define CHAR_FOR_NAMES " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-."
#define CHAR_FOR_NAMES_REGEX "[ A-Za-z0-9_.-,]*"
@@ -145,6 +148,7 @@ class ModelData {
bool potsWarnEnabled[CPN_MAX_POTS];
int potsWarnPosition[CPN_MAX_POTS];
bool displayChecklist;
+
GVarData gvarData[CPN_MAX_GVARS];
MavlinkData mavlink;
unsigned int telemetryProtocol;
@@ -170,10 +174,34 @@ class ModelData {
char registrationId[8+1];
+ enum FunctionSwitchConfig {
+ FUNC_SWITCH_CONFIG_NONE,
+ FUNC_SWITCH_CONFIG_FIRST = FUNC_SWITCH_CONFIG_NONE,
+ FUNC_SWITCH_CONFIG_TOGGLE,
+ FUNC_SWITCH_CONFIG_2POS,
+ FUNC_SWITCH_CONFIG_LAST = FUNC_SWITCH_CONFIG_2POS
+ };
+
+ enum FunctionSwitchStart {
+ FUNC_SWITCH_START_INACTIVE,
+ FUNC_SWITCH_START_FIRST = FUNC_SWITCH_START_INACTIVE,
+ FUNC_SWITCH_START_ACTIVE,
+ FUNC_SWITCH_START_PREVIOUS,
+ FUNC_SWITCH_START_LAST = FUNC_SWITCH_START_PREVIOUS
+ };
+
+ // Function switches
+ unsigned int functionSwitchConfig;
+ unsigned int functionSwitchGroup;
+ unsigned int functionSwitchStartConfig;
+ unsigned int functionSwitchLogicalState;
+ char functionSwitchNames[CPN_MAX_FUNCTION_SWITCHES][HARDWARE_NAME_LEN + 1];
+
void clear();
bool isEmpty() const;
void setDefaultInputs(const GeneralSettings & settings);
void setDefaultMixes(const GeneralSettings & settings);
+ void setDefaultFunctionSwitches(int functionSwitchCount);
void setDefaultValues(unsigned int id, const GeneralSettings & settings);
int getTrimValue(int phaseIdx, int trimIdx);
@@ -258,6 +286,12 @@ class ModelData {
static QString trainerModeToString(const int value);
static bool isTrainerModeAvailable(const GeneralSettings & generalSettings, const Firmware * firmware, const int value);
static AbstractStaticItemModel * trainerModeItemModel(const GeneralSettings & generalSettings, const Firmware * firmware);
+ QString funcSwitchConfigToString(const int index) const;
+ static QString funcSwitchConfigToString(const int index, const int value);
+ static AbstractStaticItemModel * funcSwitchConfigItemModel();
+ QString funcSwitchStartToString(const int index) const;
+ static QString funcSwitchStartToString(const int index, const int value);
+ static AbstractStaticItemModel * funcSwitchStartItemModel();
protected:
void removeGlobalVar(int & var);
diff --git a/companion/src/firmwares/opentx/opentxeeprom.cpp b/companion/src/firmwares/opentx/opentxeeprom.cpp
index df8b9263a..421138999 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.cpp
+++ b/companion/src/firmwares/opentx/opentxeeprom.cpp
@@ -51,6 +51,9 @@ inline int MAX_SWITCHES(Board::Type board, int version)
if (IS_TARANIS_X7(board))
return 8;
+ if (IS_JUMPER_TPRO(board))
+ return 10;
+
return Boards::getCapability(board, Board::Switches);
}
@@ -81,6 +84,13 @@ inline int MAX_POTS(Board::Type board, int version)
return Boards::getCapability(board, Board::Pots);
}
+inline int MAX_FUNCTION_SWITCHES(Board::Type board, int version)
+{
+ if (IS_JUMPER_TPRO(board))
+ return 6;
+ return 0;
+}
+
inline int MAX_POTS_STORAGE(Board::Type board, int version)
{
if (version <= 218 && IS_FAMILY_HORUS_OR_T16(board))
@@ -2630,17 +2640,17 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
internalField.Append(new LimitField(this, modelData.limitData[i], board, version));
for (int i=0; i(this, modelData.thrTraceSrc, "Throttle Source"));
@@ -2836,6 +2846,16 @@ OpenTxModelData::OpenTxModelData(ModelData & modelData, Board::Type board, unsig
else if (version >= 219) {
internalField.Append(new ZCharField<8>(this, modelData.registrationId, "ACCESS Registration ID"));
}
+
+ if (IS_JUMPER_TPRO(board)) {
+ internalField.Append(new UnsignedField<16>(this, modelData.functionSwitchConfig));
+ internalField.Append(new UnsignedField<16>(this, modelData.functionSwitchGroup));
+ internalField.Append(new UnsignedField<16>(this, modelData.functionSwitchStartConfig));
+ internalField.Append(new UnsignedField<8>(this, modelData.functionSwitchLogicalState));
+ for (int i=0; i < MAX_FUNCTION_SWITCHES(board, version); ++i) {
+ internalField.Append(new ZCharField<3>(this, modelData.functionSwitchNames[i], "Function switch name"));
+ }
+ }
}
void OpenTxModelData::beforeExport()
diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h
index c3f188eea..5ad907871 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.h
+++ b/companion/src/firmwares/opentx/opentxeeprom.h
@@ -40,6 +40,7 @@
#define JUMPER_TLITE_VARIANT 0x4003
#define RADIOMASTER_T8_VARIANT 0x4004
#define RADIOMASTER_ZORRO_VARIANT 0x4006
+#define JUMPER_TPRO_VARIANT 0x4005
class OpenTxGeneralData: public TransformedField {
public:
diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp
index 59c6bab33..940d57456 100644
--- a/companion/src/firmwares/opentx/opentxinterface.cpp
+++ b/companion/src/firmwares/opentx/opentxinterface.cpp
@@ -62,6 +62,8 @@ const char * OpenTxEepromInterface::getName()
return "OpenTX for Jumper T12";
case BOARD_JUMPER_TLITE:
return "OpenTX for Jumper T-Lite";
+ case BOARD_JUMPER_TPRO:
+ return "OpenTX for Jumper T-Pro";
case BOARD_JUMPER_T16:
return "OpenTX for Jumper T16";
case BOARD_JUMPER_T18:
@@ -347,6 +349,9 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
else if (IS_JUMPER_TLITE(board)) {
variant |= JUMPER_TLITE_VARIANT;
}
+ else if (IS_JUMPER_TPRO(board)) {
+ variant |= JUMPER_TPRO_VARIANT;
+ }
else if (IS_RADIOMASTER_TX12(board)) {
variant |= RADIOMASTER_TX12_VARIANT;
}
@@ -752,6 +757,9 @@ int OpenTxFirmware::getCapability(::Capability capability)
return IS_HORUS_OR_TARANIS(board) ? true : false;
case TopBarZones:
return getCapability(LcdWidth) > getCapability(LcdHeight) ? 4 : 2;
+ case FunctionSwitches:
+ return IS_JUMPER_TPRO(board) ? 6 : 0;
+
default:
return 0;
}
@@ -1025,6 +1033,11 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
variantError = true;
}
}
+ else if (IS_JUMPER_TPRO(board)) {
+ if (variant != JUMPER_TPRO_VARIANT) {
+ variantError = true;
+ }
+ }
else if (IS_RADIOMASTER_TX12(board)) {
if (variant != RADIOMASTER_TX12_VARIANT) {
variantError = true;
@@ -1371,6 +1384,16 @@ void registerOpenTxFirmwares()
registerOpenTxFirmware(firmware);
addOpenTxRfOptions(firmware, FLEX);
+ /* Jumper T-Pro board */
+ firmware = new OpenTxFirmware("opentx-tpro", QCoreApplication::translate("Firmware", "Jumper T-Pro"), BOARD_JUMPER_TPRO);
+ 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, FLEX);
+
/* Jumper T16 board */
firmware = new OpenTxFirmware("opentx-t16", Firmware::tr("Jumper T16 / T16+ / T16 Pro"), BOARD_JUMPER_T16);
addOpenTxFrskyOptions(firmware);
diff --git a/companion/src/images/simulator/JumperTPRO/bottom.png b/companion/src/images/simulator/JumperTPRO/bottom.png
new file mode 100644
index 000000000..185b5ac36
Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/bottom.png differ
diff --git a/companion/src/images/simulator/JumperTPRO/left.png b/companion/src/images/simulator/JumperTPRO/left.png
new file mode 100644
index 000000000..efcfb5e98
Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/left.png differ
diff --git a/companion/src/images/simulator/JumperTPRO/right.png b/companion/src/images/simulator/JumperTPRO/right.png
new file mode 100644
index 000000000..e30e90a91
Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/right.png differ
diff --git a/companion/src/images/simulator/JumperTPRO/top.png b/companion/src/images/simulator/JumperTPRO/top.png
new file mode 100644
index 000000000..7cf5226ff
Binary files /dev/null and b/companion/src/images/simulator/JumperTPRO/top.png differ
diff --git a/companion/src/modeledit/CMakeLists.txt b/companion/src/modeledit/CMakeLists.txt
index 73f0acf92..7404f821e 100644
--- a/companion/src/modeledit/CMakeLists.txt
+++ b/companion/src/modeledit/CMakeLists.txt
@@ -45,6 +45,7 @@ set(modeledit_HDRS
set(modeledit_UIS
setup_timer.ui
setup_module.ui
+ setup_function_switches.ui
flightmode.ui
telemetry_customscreen.ui
telemetry_sensor.ui
diff --git a/companion/src/modeledit/setup.cpp b/companion/src/modeledit/setup.cpp
index 9b4222d50..f12d83a74 100644
--- a/companion/src/modeledit/setup.cpp
+++ b/companion/src/modeledit/setup.cpp
@@ -22,6 +22,7 @@
#include "ui_setup.h"
#include "ui_setup_timer.h"
#include "ui_setup_module.h"
+#include "ui_setup_function_switches.h"
#include "appdata.h"
#include "modelprinter.h"
#include "multiprotocols.h"
@@ -982,6 +983,167 @@ void ModulePanel::onClearAccessRxClicked()
}
}
+/******************************************************************************/
+FunctionSwitchesPanel::FunctionSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware):
+ ModelPanel(parent, model, generalSettings, firmware),
+ ui(new Ui::FunctionSwitches)
+{
+ ui->setupUi(this);
+
+ AbstractStaticItemModel *fsConfig = ModelData::funcSwitchConfigItemModel();
+ AbstractStaticItemModel *fsStart = ModelData::funcSwitchStartItemModel();
+
+ lock = true;
+
+ QRegExp rx(CHAR_FOR_NAMES_REGEX);
+
+ switchcnt = Boards::getCapability(firmware->getBoard(), Board::NumFunctionSwitches);
+
+ for (int i = 0; i < switchcnt; i++) {
+ QLabel * lblSwitchId = new QLabel(this);
+ lblSwitchId->setText(tr("SW%1").arg(i + 1));
+
+ AutoLineEdit * aleName = new AutoLineEdit(this);
+ aleName->setProperty("index", i);
+ aleName->setValidator(new QRegExpValidator(rx, this));
+ aleName->setField((char *)model.functionSwitchNames[i], 3);
+
+ QComboBox * cboConfig = new QComboBox(this);
+ cboConfig->setProperty("index", i);
+ cboConfig->setModel(fsConfig);
+
+ QComboBox * cboStartPosn = new QComboBox(this);
+ cboStartPosn->setProperty("index", i);
+ cboStartPosn->setModel(fsStart);
+
+ QSpinBox * sbGroup = new QSpinBox(this);
+ sbGroup->setProperty("index", i);
+ sbGroup->setMaximum(3);
+
+ int row = 0;
+ int coloffset = 1;
+ ui->gridSwitches->addWidget(lblSwitchId, row++, i + coloffset);
+ ui->gridSwitches->addWidget(aleName, row++, i + coloffset);
+ ui->gridSwitches->addWidget(cboConfig, row++, i + coloffset);
+ ui->gridSwitches->addWidget(cboStartPosn, row++, i + coloffset);
+ ui->gridSwitches->addWidget(sbGroup, row++, i + coloffset);
+
+ connect(cboConfig, QOverload::of(&QComboBox::currentIndexChanged), this, &FunctionSwitchesPanel::on_configCurrentIndexChanged);
+ connect(cboStartPosn, QOverload::of(&QComboBox::currentIndexChanged), this, &FunctionSwitchesPanel::on_startPosnCurrentIndexChanged);
+ connect(sbGroup, QOverload::of(&QSpinBox::valueChanged), this, &FunctionSwitchesPanel::on_groupChanged);
+
+ aleNames << aleName;
+ cboConfigs << cboConfig;
+ cboStartupPosns << cboStartPosn;
+ sbGroups << sbGroup;
+ }
+
+ update();
+
+ lock = false;
+}
+
+FunctionSwitchesPanel::~FunctionSwitchesPanel()
+{
+ delete ui;
+}
+
+void FunctionSwitchesPanel::update()
+{
+ for (int i = 0; i < switchcnt; i++) {
+ update(i);
+ }
+}
+
+void FunctionSwitchesPanel::update(int index)
+{
+ lock = true;
+
+ for (int i = 0; i < switchcnt; i++) {
+ aleNames[i]->update();
+ cboConfigs[i]->setCurrentIndex((model->functionSwitchConfig >> (2 * i)) & 0x03);
+ cboStartupPosns[i]->setCurrentIndex((model->functionSwitchStartConfig >> (2 * i)) & 0x03);
+ sbGroups[i]->setValue((model->functionSwitchGroup >> (2 * i)) & 0x03);
+
+ if (cboConfigs[i]->currentIndex() < 2)
+ cboStartupPosns[i]->setEnabled(false);
+ else
+ cboStartupPosns[i]->setEnabled(true);
+
+ if (cboConfigs[i]->currentIndex() < 1)
+ sbGroups[i]->setEnabled(false);
+ else
+ sbGroups[i]->setEnabled(true);
+ }
+
+ lock = false;
+}
+
+void FunctionSwitchesPanel::on_configCurrentIndexChanged(int index)
+{
+ if (!sender())
+ return;
+
+ QComboBox * cb = qobject_cast(sender());
+
+ if (cb && !lock) {
+ lock = true;
+ bool ok = false;
+ int i = sender()->property("index").toInt(&ok);
+ if (ok && ((model->functionSwitchConfig >> (2 * i)) & 0x03) != (unsigned int)index) {
+ unsigned int mask = ((unsigned int) 0x03 << (2 * i));
+ model->functionSwitchConfig = (model->functionSwitchConfig & ~ mask) | ((unsigned int) index << (2 * i));
+ if (index < 2)
+ model->functionSwitchStartConfig = (model->functionSwitchStartConfig & ~ mask) | ((unsigned int) 0 << (2 * i));
+ if (index < 1)
+ model->functionSwitchGroup = (model->functionSwitchGroup & ~ mask) | ((unsigned int) 0 << (2 * i));
+ update(i);
+ emit modified();
+ }
+ lock = false;
+ }
+}
+
+void FunctionSwitchesPanel::on_startPosnCurrentIndexChanged(int index)
+{
+ if (!sender())
+ return;
+
+ QComboBox * cb = qobject_cast(sender());
+
+ if (cb && !lock) {
+ lock = true;
+ bool ok = false;
+ int i = sender()->property("index").toInt(&ok);
+ if (ok && ((model->functionSwitchStartConfig >> (2 * i)) & 0x03) != (unsigned int)index) {
+ unsigned int mask = ((unsigned int) 0x03 << (2 * i));
+ model->functionSwitchStartConfig = (model->functionSwitchStartConfig & ~ mask) | ((unsigned int) index << (2 * i));
+ emit modified();
+ }
+ lock = false;
+ }
+}
+
+void FunctionSwitchesPanel::on_groupChanged(int value)
+{
+ if (!sender())
+ return;
+
+ QSpinBox * sb = qobject_cast(sender());
+
+ if (sb && !lock) {
+ lock = true;
+ bool ok = false;
+ int i = sender()->property("index").toInt(&ok);
+ if (ok && ((model->functionSwitchGroup >> (2 * i)) & 0x03) != (unsigned int)value) {
+ unsigned int mask = ((unsigned int) 0x03 << (2 * i));
+ model->functionSwitchGroup = (model->functionSwitchGroup & ~ mask) | ((unsigned int) value << (2 * i));
+ emit modified();
+ }
+ lock = false;
+ }
+}
+
/******************************************************************************/
SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware,
@@ -1221,6 +1383,11 @@ SetupPanel::SetupPanel(QWidget * parent, ModelData & model, GeneralSettings & ge
ui->trimsDisplay->setField(model.trimsDisplay, this);
+ if (Boards::getCapability(firmware->getBoard(), Board::NumFunctionSwitches) > 0)
+ ui->functionSwitchesLayout->addWidget(new FunctionSwitchesPanel(this, model, generalSettings, firmware));
+ //else
+ // ui->functionSwitchesLayout->hide();
+
for (int i = firmware->getCapability(NumFirstUsableModule); i < firmware->getCapability(NumModules); i++) {
modules[i] = new ModulePanel(this, model, model.moduleData[i], generalSettings, firmware, i);
ui->modulesLayout->addWidget(modules[i]);
diff --git a/companion/src/modeledit/setup.h b/companion/src/modeledit/setup.h
index 824b28acb..c63932237 100644
--- a/companion/src/modeledit/setup.h
+++ b/companion/src/modeledit/setup.h
@@ -31,8 +31,11 @@ namespace Ui {
class Setup;
class Timer;
class Module;
+ class FunctionSwitches;
}
+class AutoLineEdit;
+
class TimerPanel : public ModelPanel
{
Q_OBJECT
@@ -128,6 +131,31 @@ class ModulePanel : public ModelPanel
void updateFailsafeUI(unsigned channel, quint8 updtSb);
};
+class FunctionSwitchesPanel : public ModelPanel
+{
+ Q_OBJECT
+
+ public:
+ FunctionSwitchesPanel(QWidget * parent, ModelData & model, GeneralSettings & generalSettings, Firmware * firmware);
+ virtual ~FunctionSwitchesPanel();
+
+ virtual void update();
+ void update(int index);
+
+ private slots:
+ void on_configCurrentIndexChanged(int index);
+ void on_startPosnCurrentIndexChanged(int index);
+ void on_groupChanged(int value);
+
+ private:
+ Ui::FunctionSwitches * ui;
+ QVector aleNames;
+ QVector cboConfigs;
+ QVector cboStartupPosns;
+ QVector sbGroups;
+ int switchcnt;
+};
+
class SetupPanel : public ModelPanel
{
Q_OBJECT
diff --git a/companion/src/modeledit/setup.ui b/companion/src/modeledit/setup.ui
index ee0ec28a3..51aae4f1e 100644
--- a/companion/src/modeledit/setup.ui
+++ b/companion/src/modeledit/setup.ui
@@ -7,7 +7,7 @@
0
0
1007
- 405
+ 435
@@ -630,6 +630,9 @@ If this is checked the throttle will be reversed. Idle will be forward, trim wi
+ -
+
+
-
diff --git a/companion/src/modeledit/setup_function_switches.ui b/companion/src/modeledit/setup_function_switches.ui
new file mode 100644
index 000000000..acfd88e5d
--- /dev/null
+++ b/companion/src/modeledit/setup_function_switches.ui
@@ -0,0 +1,121 @@
+
+
+ FunctionSwitches
+
+
+
+ 0
+ 0
+ 231
+ 140
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+
+ 75
+ true
+
+
+
+ Function Switches
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+
+ -
+
+
+ QLayout::SetMinimumSize
+
+
-
+
+
+ Type
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Group
+
+
+
+ -
+
+
+ Start
+
+
+
+ -
+
+
+ Name
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
diff --git a/companion/src/multimodelprinter.cpp b/companion/src/multimodelprinter.cpp
index 1cf0140e3..8c38776e5 100644
--- a/companion/src/multimodelprinter.cpp
+++ b/companion/src/multimodelprinter.cpp
@@ -277,6 +277,9 @@ QString MultiModelPrinter::print(QTextDocument * document)
if (firmware->getCapability(Timers)) {
str.append(printTimers());
}
+ if (Boards::getCapability(firmware->getBoard(), Board::NumFunctionSwitches)) {
+ str.append(printFunctionSwitches());
+ }
str.append(printModules());
if (firmware->getCapability(Heli))
str.append(printHeliSetup());
@@ -938,3 +941,52 @@ QString MultiModelPrinter::printChecklist()
}
return str;
}
+
+QString MultiModelPrinter::printFunctionSwitches()
+{
+ QString str;
+ MultiColumns columns(modelPrinterMap.size());
+ columns.appendSectionTableStart();
+
+ int numFS = Boards::getCapability(firmware->getBoard(), Board::NumFunctionSwitches);
+ int colwidth = 80 / numFS;
+
+ QStringList headings = { tr("Function Switches") };
+ for (int i = 0; i < numFS; i++) {
+ headings << tr("Switch %1").arg(i + 1);
+ }
+ columns.appendRowHeader(headings);
+
+ columns.appendRowStart(tr("Name"), 20);
+
+ for (int i = 0; i < numFS; i++) {
+ COMPARECELLWIDTH(model->functionSwitchNames[i], colwidth);
+ }
+
+ columns.appendRowEnd();
+ columns.appendRowStart(tr("Type"), 20);
+
+ for (int i = 0; i < numFS; i++) {
+ COMPARECELLWIDTH(model->funcSwitchConfigToString((unsigned int)i), colwidth);
+ }
+
+ columns.appendRowEnd();
+ columns.appendRowStart(tr("Start"), 20);
+
+ for (int i = 0; i < numFS; i++) {
+ COMPARECELLWIDTH(model->funcSwitchStartToString((unsigned int)i), colwidth);
+ }
+
+ columns.appendRowEnd();
+ columns.appendRowStart(tr("Group"), 20);
+
+ for (int i = 0; i < numFS; i++) {
+ COMPARECELLWIDTH((model->functionSwitchGroup >> (2 * i)) & 0x03, colwidth);
+ }
+
+ columns.appendRowEnd();
+
+ columns.appendTableEnd();
+ str.append(columns.print());
+ return str;
+}
diff --git a/companion/src/multimodelprinter.h b/companion/src/multimodelprinter.h
index 4214bc45b..8cc48642c 100644
--- a/companion/src/multimodelprinter.h
+++ b/companion/src/multimodelprinter.h
@@ -95,6 +95,7 @@ class MultiModelPrinter: public QObject
QString printTelemetryScreens();
QString printGlobalFunctions();
QString printChecklist();
+ QString printFunctionSwitches();
};
#endif // _MULTIMODELPRINTER_H_
diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt
index cc605abbb..091867696 100644
--- a/companion/src/simulation/CMakeLists.txt
+++ b/companion/src/simulation/CMakeLists.txt
@@ -14,6 +14,7 @@ set(simulation_SRCS
simulateduiwidgetX12.cpp
simulateduiwidgetJumperT12.cpp
simulateduiwidgetJumperTLITE.cpp
+ simulateduiwidgetJumperTPRO.cpp
simulateduiwidgetJumperT16.cpp
simulateduiwidgetJumperT18.cpp
simulateduiwidgetTX12.cpp
@@ -46,6 +47,7 @@ set(simulation_UIS
simulateduiwidgetX12.ui
simulateduiwidgetJumperT12.ui
simulateduiwidgetJumperTLITE.ui
+ simulateduiwidgetJumperTPRO.ui
simulateduiwidgetJumperT16.ui
simulateduiwidgetJumperT18.ui
simulateduiwidgetTX12.ui
diff --git a/companion/src/simulation/simulateduiwidget.h b/companion/src/simulation/simulateduiwidget.h
index 579ad567f..187a60660 100644
--- a/companion/src/simulation/simulateduiwidget.h
+++ b/companion/src/simulation/simulateduiwidget.h
@@ -113,6 +113,7 @@ namespace Ui {
class SimulatedUIWidgetX12;
class SimulatedUIWidgetJumperT12;
class SimulatedUIWidgetJumperTLITE;
+ class SimulatedUIWidgetJumperTPRO;
class SimulatedUIWidgetJumperT16;
class SimulatedUIWidgetJumperT18;
class SimulatedUIWidgetTX16S;
@@ -258,6 +259,18 @@ class SimulatedUIWidgetJumperTLITE: public SimulatedUIWidget
Ui::SimulatedUIWidgetJumperTLITE * ui;
};
+class SimulatedUIWidgetJumperTPRO: public SimulatedUIWidget
+{
+ Q_OBJECT
+
+ public:
+ explicit SimulatedUIWidgetJumperTPRO(SimulatorInterface * simulator, QWidget * parent = NULL);
+ virtual ~SimulatedUIWidgetJumperTPRO();
+
+ private:
+ Ui::SimulatedUIWidgetJumperTPRO * ui;
+};
+
class SimulatedUIWidgetJumperT16: public SimulatedUIWidget
{
Q_OBJECT
diff --git a/companion/src/simulation/simulateduiwidgetJumperTPRO.cpp b/companion/src/simulation/simulateduiwidgetJumperTPRO.cpp
new file mode 100644
index 000000000..e46c7fbad
--- /dev/null
+++ b/companion/src/simulation/simulateduiwidgetJumperTPRO.cpp
@@ -0,0 +1,54 @@
+#include "simulateduiwidget.h"
+#include "ui_simulateduiwidgetJumperTPRO.h"
+
+// NOTE: RadioUiAction(NUMBER,...): NUMBER relates to enum EnumKeys in the specific board.h
+
+SimulatedUIWidgetJumperTPRO::SimulatedUIWidgetJumperTPRO(SimulatorInterface *simulator, QWidget * parent):
+ SimulatedUIWidget(simulator, parent),
+ ui(new Ui::SimulatedUIWidgetJumperTPRO)
+{
+ RadioUiAction * act;
+
+ ui->setupUi(this);
+
+ act = new RadioUiAction(0, QList() << Qt::Key_PageUp << Qt::Key_Up, SIMU_STR_HLP_KEYS_GO_UP, SIMU_STR_HLP_ACT_MENU_ICN);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(70, 85, 110, 90), "JumperTPRO/left.png", act));
+
+ act = new RadioUiAction(3, QList() << Qt::Key_PageDown << Qt::Key_Down, SIMU_STR_HLP_KEYS_GO_DN, SIMU_STR_HLP_ACT_PAGE);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(53, 174, 110, 90), "JumperTPRO/left.png", act));
+
+ act = new RadioUiAction(1, QList() << Qt::Key_Delete << Qt::Key_Escape << Qt::Key_Backspace, SIMU_STR_HLP_KEYS_EXIT, SIMU_STR_HLP_ACT_EXIT);
+ addRadioWidget(ui->leftbuttons->addArea(QRect(11, 257, 110, 90), "JumperTPRO/left.png", act));
+
+ m_mouseMidClickAction = new RadioUiAction(2, QList() << Qt::Key_Enter << Qt::Key_Return, SIMU_STR_HLP_KEYS_ACTIVATE, SIMU_STR_HLP_ACT_ROT_DN);
+ addRadioWidget(ui->rightbuttons->addArea(QRect(10, 96, 200, 220), "JumperTPRO/right.png", m_mouseMidClickAction));
+
+ //addRadioWidget(ui->leftbuttons->addArea(QRect(10, 65, 70, 50), "JumperTPRO/left_scrnshot.png", m_screenshotAction));
+
+ 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);
+}
+
+SimulatedUIWidgetJumperTPRO::~SimulatedUIWidgetJumperTPRO()
+{
+ delete ui;
+}
diff --git a/companion/src/simulation/simulateduiwidgetJumperTPRO.ui b/companion/src/simulation/simulateduiwidgetJumperTPRO.ui
new file mode 100644
index 000000000..5a77f11ff
--- /dev/null
+++ b/companion/src/simulation/simulateduiwidgetJumperTPRO.ui
@@ -0,0 +1,258 @@
+
+
+ SimulatedUIWidgetJumperTPRO
+
+
+
+ 0
+ 0
+ 725
+ 389
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 725
+ 389
+
+
+
+
+ 501
+ 310
+
+
+
+ Jumper T-Pro 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
+
+
+
+
+ 234
+ 368
+
+
+
+
+ 234
+ 368
+
+
+
+ background:url(:/images/simulator/JumperTPRO/left.png);
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 256
+ 231
+
+
+
+
+ 256
+ 231
+
+
+
+ background-color: rgb(215, 243, 255);
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 236
+ 368
+
+
+
+
+ 236
+ 368
+
+
+
+ background:url(:/images/simulator/JumperTPRO/right.png)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 255
+ 85
+
+
+
+
+ 255
+ 85
+
+
+
+ background:url(:/images/simulator/JumperTPRO/top.png)
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 255
+ 131
+
+
+
+
+ 255
+ 131
+
+
+
+ background:url(:/images/simulator/JumperTPRO/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
+
+ 1
+
+
+ ButtonsWidget
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp
index b087c7055..8f3ef08c2 100644
--- a/companion/src/simulation/simulatorwidget.cpp
+++ b/companion/src/simulation/simulatorwidget.cpp
@@ -94,6 +94,9 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
case Board::BOARD_JUMPER_TLITE:
radioUiWidget = new SimulatedUIWidgetJumperTLITE(simulator, this);
break;
+ case Board::BOARD_JUMPER_TPRO:
+ radioUiWidget = new SimulatedUIWidgetJumperTPRO(simulator, this);
+ break;
case Board::BOARD_JUMPER_T16:
radioUiWidget = new SimulatedUIWidgetJumperT16(simulator, this);
break;
diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h
index fd108bf56..5af5187c5 100644
--- a/radio/src/dataconstants.h
+++ b/radio/src/dataconstants.h
@@ -419,7 +419,12 @@ enum SwitchSources {
SWSRC_SD2,
#endif
-#if defined(STORAGE_SWITCH_E)
+#if defined(FUNCTION_SWITCHES) && defined(RADIO_TPRO)
+ SWSRC_FIRST_FUNCTION_SWITCH SKIP,
+ SWSRC_SE0 = SWSRC_FIRST_FUNCTION_SWITCH,
+ SWSRC_SE1,
+ SWSRC_SE2,
+#elif defined(STORAGE_SWITCH_E)
SWSRC_SE0,
SWSRC_SE1,
SWSRC_SE2,
@@ -569,7 +574,7 @@ enum SwitchSources {
SWSRC_INVERT SKIP = SWSRC_COUNT+1,
};
-#if NUM_SWITCHES >= 8
+#if NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES >= 8
#define SWSRC_TRAINER SWSRC_SH2
#else
#define SWSRC_TRAINER SWSRC_LAST_SWITCH,
@@ -786,11 +791,15 @@ enum MixSources {
static_assert(MIXSRC_FIRST_LOGICAL_SWITCH == MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES, "Wrong switches definition in MIXSRC list");
#endif
-#define MIXSRC_FIRST (MIXSRC_NONE + 1)
-#define MIXSRC_LAST MIXSRC_LAST_CH
-#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES - 1)
-#define INPUTSRC_FIRST MIXSRC_Rud
-#define INPUTSRC_LAST MIXSRC_LAST_TELEM
+#define MIXSRC_FIRST (MIXSRC_NONE + 1)
+#define MIXSRC_LAST MIXSRC_LAST_CH
+#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + STORAGE_NUM_SWITCHES - 1)
+#define INPUTSRC_FIRST MIXSRC_Rud
+#define INPUTSRC_LAST MIXSRC_LAST_TELEM
+#if defined(FUNCTION_SWITCHES)
+#define MIXSRC_LAST_REGULAR_SWITCH (MIXSRC_FIRST_SWITCH + NUM_REGULAR_SWITCHES - 1)
+#define MIXSRC_FIRST_FS_SWITCH (MIXSRC_LAST_REGULAR_SWITCH + 1)
+#endif
enum BacklightMode {
e_backlight_mode_off = 0,
diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h
index 5cc4c4319..8da911cf5 100644
--- a/radio/src/datastructs.h
+++ b/radio/src/datastructs.h
@@ -121,6 +121,9 @@ static inline void check_struct()
#elif defined(PCBXLITE)
CHKSIZE(RadioData, 858);
CHKSIZE(ModelData, 6159);
+#elif defined(RADIO_TPRO)
+ CHKSIZE(RadioData, 841);
+ CHKSIZE(ModelData, 6184);
#elif defined(PCBX7)
CHKSIZE(RadioData, 864);
CHKSIZE(ModelData, 6159);
diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h
index e062e926d..c4453ee69 100644
--- a/radio/src/datastructs_private.h
+++ b/radio/src/datastructs_private.h
@@ -616,6 +616,17 @@ PACK(struct CustomScreenData {
#define SCRIPT_DATA
#endif
+#if defined(FUNCTION_SWITCHES) && NUM_FUNCTIONS_SWITCHES < 8
+ #define FUNCTION_SWITCHS_FIELDS \
+ uint16_t functionSwitchConfig; \
+ uint16_t functionSwitchGroup; \
+ uint16_t functionSwitchStartConfig; \
+ uint8_t functionSwitchLogicalState; \
+ char switchNames[NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME];
+#else
+ #define FUNCTION_SWITCHS_FIELDS
+#endif
+
PACK(struct PartialModel {
ModelHeader header;
TimerData timers[MAX_TIMERS];
@@ -683,6 +694,8 @@ PACK(struct ModelData {
char modelRegistrationID[PXX2_LEN_REGISTRATION_ID];
+ FUNCTION_SWITCHS_FIELDS
+
bool isTrainerTraineeEnable() const
{
#if defined(PCBNV14)
@@ -794,7 +807,7 @@ PACK(struct TrainerData {
uint8_t backlightColor; \
CUST_ARRAY(sticksConfig, struct_sticksConfig, stick_name_valid); \
swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \
- char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME] SKIP; \
+ char switchNames[STORAGE_NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES][LEN_SWITCH_NAME] SKIP; \
char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME] SKIP; \
BLUETOOTH_FIELDS
#else
diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp
index f6a6c6160..920647245 100644
--- a/radio/src/gui/128x64/model_setup.cpp
+++ b/radio/src/gui/128x64/model_setup.cpp
@@ -39,7 +39,7 @@ uint8_t g_moduleIdx;
uint8_t getSwitchWarningsCount()
{
uint8_t count = 0;
- for (int i=0; ipersistent = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, timer->persistent, 0, 2, attr, event);
break;
}
+#if defined(FUNCTION_SWITCHES)
+ case ITEM_MODEL_SETUP_LABEL:
+ lcdDrawTextAlignedLeft(y, "Function Switches");
+ break;
+
+ case ITEM_MODEL_SETUP_SW1:
+ case ITEM_MODEL_SETUP_SW2:
+ case ITEM_MODEL_SETUP_SW3:
+ case ITEM_MODEL_SETUP_SW4:
+ case ITEM_MODEL_SETUP_SW5:
+ case ITEM_MODEL_SETUP_SW6:
+ {
+ int index = k - ITEM_MODEL_SETUP_SW1;
+ int config = FSWITCH_CONFIG(index);
+ lcdDrawTextAtIndex(INDENT_WIDTH, y, STR_VSRCRAW, MIXSRC_FIRST_SWITCH + NUM_REGULAR_SWITCHES - MIXSRC_Rud + index + 1, menuHorizontalPosition < 0 ? attr : 0);
+ if (ZEXIST(g_model.switchNames[index]) || (attr && s_editMode > 0 && menuHorizontalPosition == 0))
+ editName(35, y, g_model.switchNames[index], LEN_SWITCH_NAME, event, menuHorizontalPosition == 0 ? attr : 0, 0, old_editMode);
+ else
+ lcdDrawMMM(35, y, menuHorizontalPosition == 0 ? attr : 0);
+ config = editChoice(30 + 5*FW, y, "", STR_SWTYPES, config, SWITCH_NONE, SWITCH_2POS, menuHorizontalPosition == 1 ? attr : 0, event);
+ if (attr && checkIncDec_Ret) {
+ swconfig_t mask = (swconfig_t)0x03 << (2*index);
+ g_model.functionSwitchConfig = (g_model.functionSwitchConfig & ~mask) | ((swconfig_t(config) & 0x03) << (2*index));
+ }
+
+ config = FSWITCH_GROUP(index);
+ config = editChoice(30 + 15*FW, y, "", STR_FSGROUPS, config, 0, 3, menuHorizontalPosition == 2 ? attr : 0, event);
+ if (attr && checkIncDec_Ret && menuHorizontalPosition == 2) {
+ swconfig_t mask = (swconfig_t) 0x03 << (2 * index);
+ g_model.functionSwitchGroup = (g_model.functionSwitchGroup & ~mask) | ((swconfig_t(config) & 0x03) << (2 * index));
+ }
+ break;
+ }
+
+ case ITEM_MODEL_SETUP_FS_STARTUP:
+ {
+ char c;
+ lcdDrawText(0, y, INDENT "Start", menuHorizontalPosition < 0 ? attr : 0);
+ for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) {
+ uint8_t startPos = (g_model.functionSwitchStartConfig >> 2 * i) & 0x03;
+ c = STR_CHAR_UP STR_CHAR_DOWN "="[(g_model.functionSwitchStartConfig >> 2 * i) & 0x03];
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN - (2 + FW) + i * 2 * FW, y, i + 1, 0);
+ lcdDrawChar(lcdNextPos, y, c, attr && (menuHorizontalPosition == i) ? (s_editMode ? INVERS + BLINK : INVERS) : 0);
+ if (attr && menuHorizontalPosition == i) {
+ CHECK_INCDEC_MODELVAR(event, startPos, 0, 2);
+ }
+ if (attr && checkIncDec_Ret) {
+ swconfig_t mask = (swconfig_t)0x03 << (2*i);
+ g_model.functionSwitchStartConfig = (g_model.functionSwitchStartConfig & ~mask) | ((swconfig_t(startPos) & 0x03) << (2*i));
+ storageDirty(EE_MODEL);
+ }
+ }
+ break;
+ }
+#endif
case ITEM_MODEL_SETUP_EXTENDED_LIMITS:
g_model.extendedLimits = editCheckBox(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event);
break;
@@ -724,7 +796,7 @@ void menuModelSetup(event_t event)
}
int current = 0;
- for (int i = 0; i < NUM_SWITCHES; i++) {
+ for (int i = 0; i < NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES; i++) {
if (SWITCH_WARNING_ALLOWED(i)) {
div_t qr = div(current, MAX_SWITCH_PER_LINE);
if (!READ_ONLY() && event == EVT_KEY_BREAK(KEY_ENTER) && attr &&
diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp
index 02f9b4b86..2452b900b 100644
--- a/radio/src/gui/128x64/radio_diagkeys.cpp
+++ b/radio/src/gui/128x64/radio_diagkeys.cpp
@@ -41,7 +41,7 @@ void menuRadioDiagKeys(event_t event)
lcdDrawText(14*FW, MENU_HEADER_HEIGHT + 1, STR_VTRIM);
- for (uint8_t i=0; i<9; i++) {
+ for (uint8_t i=0; i<10; i++) {
coord_t y;
if (i < NUM_TRIMS_KEYS) {
@@ -69,10 +69,19 @@ void menuRadioDiagKeys(event_t event)
drawSwitch(8*FW, y, i+1, 0);
displaySwitchState(11*FW+2, y, i);
}
+#elif (NUM_SWITCHES > 6)
+ if (i < NUM_SWITCHES) {
+ if (SWITCH_EXISTS(i)) {
+ y = (i > 4) ? FH*(i-4) : MENU_HEADER_HEIGHT + FH*i;
+ getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i);
+ getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3));
+ drawSwitch(i > 4 ? 11*FW-5: 8*FW-9, y, sw, 0, false);
+ }
+ }
#else
if (i < NUM_SWITCHES) {
if (SWITCH_EXISTS(i)) {
- y = (NUM_SWITCHES > 6 ? 0 : MENU_HEADER_HEIGHT) + FH*i;
+ y = (NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES > 6 ? 0 : MENU_HEADER_HEIGHT) + FH*i;
getvalue_t val = getValue(MIXSRC_FIRST_SWITCH+i);
getvalue_t sw = ((val < 0) ? 3*i+1 : ((val == 0) ? 3*i+2 : 3*i+3));
drawSwitch(8*FW+4, y, sw, 0);
@@ -81,8 +90,18 @@ void menuRadioDiagKeys(event_t event)
#endif
}
+#if defined(FUNCTION_SWITCHES) && defined(DEBUG)
+ lcdDrawText(LCD_W / 2 , LCD_H - 2 * FH, "Phys");
+ lcdDrawText(LCD_W / 2 , LCD_H - 1 * FH, "Log");
+
+ for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) {
+ lcdDrawNumber(LCD_W / 2 + 20 + (i + 1) * FW , LCD_H - 2 * FH, getFSPhysicalState(i));
+ lcdDrawNumber(LCD_W / 2 + 20 + (i + 1) * FW , LCD_H - 1 * FH, getFSLogicalState(i));
+ }
+#endif
+
#if defined(ROTARY_ENCODER_NAVIGATION)
- coord_t y = MENU_HEADER_HEIGHT + 1 + FH*KEY_COUNT;
+ coord_t y = LCD_H - FH - 1;
lcdDrawText(0, y, STR_ROTARY_ENCODER);
lcdDrawNumber(5*FW+FWNUM+2, y, rotencValue / ROTARY_ENCODER_GRANULARITY, RIGHT);
#endif
diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp
index 471dc7168..35039c4a7 100644
--- a/radio/src/gui/128x64/view_main.cpp
+++ b/radio/src/gui/128x64/view_main.cpp
@@ -660,7 +660,7 @@ void menuMainView(event_t event)
}
}
#elif defined(PCBTARANIS)
- uint8_t switches = min(NUM_SWITCHES, 6);
+ uint8_t switches = min(NUM_SWITCHES- NUM_FUNCTIONS_SWITCHES, 6);
for (int i = 0; i < switches; ++i) {
if (SWITCH_EXISTS(i)) {
uint8_t x = 2 * FW - 2, y = 4 * FH + i * FH + 1;
diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp
index 48bb47246..67de15c46 100644
--- a/radio/src/gui/common/stdlcd/radio_hardware.cpp
+++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp
@@ -55,6 +55,7 @@ enum {
ITEM_RADIO_HARDWARE_SB,
ITEM_RADIO_HARDWARE_SC,
ITEM_RADIO_HARDWARE_SD,
+#if !defined(RADIO_TPRO)
#if defined(HARDWARE_SWITCH_E)
ITEM_RADIO_HARDWARE_SE,
#endif
@@ -73,6 +74,7 @@ enum {
#if defined(HARDWARE_SWITCH_J)
ITEM_RADIO_HARDWARE_SJ,
#endif
+#endif
#if defined(HARDWARE_SWITCH_K)
ITEM_RADIO_HARDWARE_SK,
ITEM_RADIO_HARDWARE_SL,
@@ -154,6 +156,8 @@ enum {
#if defined(PCBX9E)
#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
+#elif defined(RADIO_TPRO)
+ #define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
#elif defined(RADIO_T12)
#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|HIDDEN_ROW, NAVIGATION_LINE_BY_LINE|HIDDEN_ROW
#elif NUM_SWITCHES == 9
@@ -432,6 +436,7 @@ void menuRadioHardware(event_t event)
case ITEM_RADIO_HARDWARE_SB:
case ITEM_RADIO_HARDWARE_SC:
case ITEM_RADIO_HARDWARE_SD:
+#if !defined(RADIO_TPRO)
#if defined(HARDWARE_SWITCH_E)
case ITEM_RADIO_HARDWARE_SE:
#endif
@@ -450,6 +455,7 @@ void menuRadioHardware(event_t event)
#if defined(HARDWARE_SWITCH_J)
case ITEM_RADIO_HARDWARE_SJ:
#endif
+#endif
#if defined(HARDWARE_SWITCH_K)
case ITEM_RADIO_HARDWARE_SK:
case ITEM_RADIO_HARDWARE_SL:
diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp
index a7e5dc6c9..a02c3a78b 100644
--- a/radio/src/hal/adc_driver.cpp
+++ b/radio/src/hal/adc_driver.cpp
@@ -59,6 +59,8 @@ const etx_hal_adc_driver_t* etx_hal_adc_driver = nullptr;
const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, -1,-1, 1, 1};
#elif defined(RADIO_ZORRO)
const int8_t adcDirection[NUM_ANALOGS] = {-1, 1, 1, -1, -1, 1, 1, 1};
+#elif defined(RADIO_TPRO)
+ const int8_t adcDirection[NUM_ANALOGS] = {1,-1,1,-1, 1,1, 1, 1};
#elif defined(PCBX7)
const int8_t adcDirection[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1, 1};
#elif defined(PCBX9LITE)
diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt
index 8a75d379c..685778108 100644
--- a/radio/src/lua/CMakeLists.txt
+++ b/radio/src/lua/CMakeLists.txt
@@ -30,6 +30,7 @@ if(PYTHONINTERP_FOUND)
add_lua_export_target(x12s ${LUA_INCLUDES} -DPCBHORUS -DPCBX12S)
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(tpro ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TPRO)
add_lua_export_target(tx12 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_TX12)
add_lua_export_target(zorro ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_ZORRO)
add_lua_export_target(t8 ${LUA_INCLUDES} -DPCBTARANIS -DPCBX7 -DRADIO_T8)
diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp
index 8ac29f153..354cdd1c8 100644
--- a/radio/src/lua/api_general.cpp
+++ b/radio/src/lua/api_general.cpp
@@ -50,6 +50,8 @@
#include "lua/lua_exports_t12.inc"
#elif defined(RADIO_TLITE)
#include "lua/lua_exports_tlite.inc"
+#elif defined(RADIO_TPRO)
+ #include "lua/lua_exports_tpro.inc"
#elif defined(RADIO_TX12)
#include "lua/lua_exports_tx12.inc"
#elif defined(RADIO_ZORRO)
diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp
index 92214f605..cdb90e6df 100644
--- a/radio/src/mixer.cpp
+++ b/radio/src/mixer.cpp
@@ -348,6 +348,20 @@ getvalue_t getValue(mixsrc_t i)
// TODO : find a better define
#if defined(PCBFRSKY) || defined(PCBFLYSKY)
+#if defined(FUNCTION_SWITCHES)
+ else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_REGULAR_SWITCH) {
+ mixsrc_t sw = i - MIXSRC_FIRST_SWITCH;
+ if (SWITCH_EXISTS(sw)) {
+ return (switchState(3*sw) ? -1024 : (IS_CONFIG_3POS(sw) && switchState(3*sw+1) ? 0 : 1024));
+ }
+ else {
+ return 0;
+ }
+ }
+ else if (i >= MIXSRC_FIRST_FS_SWITCH && i <= MIXSRC_LAST_SWITCH) {
+ return getFSLogicalState(i - MIXSRC_FIRST_SWITCH - NUM_REGULAR_SWITCHES) ? +1024 : -1024;
+ }
+#else
else if (i >= MIXSRC_FIRST_SWITCH && i <= MIXSRC_LAST_SWITCH) {
mixsrc_t sw = i - MIXSRC_FIRST_SWITCH;
if (SWITCH_EXISTS(sw)) {
@@ -357,6 +371,7 @@ getvalue_t getValue(mixsrc_t i)
return 0;
}
}
+#endif
#else
else if (i == MIXSRC_3POS) {
return (getSwitch(SW_ID0+1) ? -1024 : (getSwitch(SW_ID1+1) ? 0 : 1024));
diff --git a/radio/src/model_init.cpp b/radio/src/model_init.cpp
index 492ccb190..ce3b3cf7b 100644
--- a/radio/src/model_init.cpp
+++ b/radio/src/model_init.cpp
@@ -114,6 +114,13 @@ void applyDefaultTemplate()
setDefaultModelRegistrationID();
+#if defined(FUNCTION_SWITCHES)
+ g_model.functionSwitchConfig = DEFAULT_FS_CONFIG;
+ g_model.functionSwitchGroup = DEFAULT_FS_GROUPS;
+ g_model.functionSwitchStartConfig = DEFAULT_FS_STARTUP_CONFIG;
+ g_model.functionSwitchLogicalState = 0;
+#endif
+
#if defined(COLORLCD)
//TODO: not sure yet we need it here
loadDefaultLayout();
diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h
index 958e529a3..a8117e792 100644
--- a/radio/src/myeeprom.h
+++ b/radio/src/myeeprom.h
@@ -83,9 +83,18 @@
#if defined(PCBFRSKY) || defined(PCBNV14)
#define SWITCH_CONFIG(x) (bfGet(g_eeGeneral.switchConfig, 2*(x), 2))
+#if defined(FUNCTION_SWITCHES)
+ #define FSWITCH_CONFIG(x) (bfGet(g_model.functionSwitchConfig, 2*(x), 2))
+ #define FSWITCH_GROUP(x) (bfGet(g_model.functionSwitchGroup, 2*(x), 2))
+ #define IS_SWITCH_FS(x) (x >= NUM_REGULAR_SWITCHES)
+ #define SWITCH_EXISTS(x) (IS_SWITCH_FS(x) ? true : (FSWITCH_CONFIG(x) != SWITCH_NONE))
+ #define IS_CONFIG_3POS(x) (IS_SWITCH_FS(x) ? (FSWITCH_CONFIG(x - NUM_REGULAR_SWITCHES) == SWITCH_3POS) : (SWITCH_CONFIG(x) == SWITCH_3POS))
+ #define IS_CONFIG_TOGGLE(x) (IS_SWITCH_FS(x) ? (FSWITCH_CONFIG(x - NUM_REGULAR_SWITCHES) == SWITCH_TOGGLE) : (SWITCH_CONFIG(x) == SWITCH_TOGGLE))
+#else
#define SWITCH_EXISTS(x) (SWITCH_CONFIG(x) != SWITCH_NONE)
#define IS_CONFIG_3POS(x) (SWITCH_CONFIG(x) == SWITCH_3POS)
#define IS_CONFIG_TOGGLE(x) (SWITCH_CONFIG(x) == SWITCH_TOGGLE)
+#endif
#define SWITCH_WARNING_ALLOWED(x) (SWITCH_EXISTS(x) && !IS_CONFIG_TOGGLE(x))
#else
#define IS_CONFIG_3POS(x) IS_3POS(x)
diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp
index f358af4a4..16895d2c6 100644
--- a/radio/src/opentx.cpp
+++ b/radio/src/opentx.cpp
@@ -171,6 +171,10 @@ void per10ms()
readKeysAndTrims();
+#if defined(FUNCTION_SWITCHES)
+ evalFunctionSwitches();
+#endif
+
#if defined(ROTARY_ENCODER_NAVIGATION)
if (IS_ROTARY_ENCODER_NAVIGATION_ENABLE()) {
static rotenc_t rePreviousValue;
@@ -372,7 +376,6 @@ uint16_t evalChkSum()
return sum;
}
-
bool isInputRecursive(int index)
{
ExpoData * line = expoAddress(0);
@@ -1414,6 +1417,12 @@ void opentxStart(const uint8_t startOptions = OPENTX_START_DEFAULT_ARGS)
ALERT(STR_TEST_WARNING, TR_TEST_NOTSAFE, AU_ERROR);
#endif
+#if defined(FUNCTION_SWITCHES)
+ if (!UNEXPECTED_SHUTDOWN()) {
+ setFSStartupPosition();
+ }
+#endif
+
#if defined(GUI)
if (calibration_needed) {
#if defined(LIBOPENUI)
diff --git a/radio/src/opentx_constants.h b/radio/src/opentx_constants.h
index 4b6559a65..bcb934df5 100644
--- a/radio/src/opentx_constants.h
+++ b/radio/src/opentx_constants.h
@@ -41,6 +41,12 @@ enum SliderConfig {
SLIDER_WITH_DETENT,
};
+enum fsStartPositionType {
+ FS_START_UP,
+ FS_START_DOWN,
+ FS_START_PREVIOUS
+};
+
enum CalibrationState {
CALIB_START,
CALIB_SET_MIDPOINT,
diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h
index 2ac4f5dc6..43896b690 100644
--- a/radio/src/sdcard.h
+++ b/radio/src/sdcard.h
@@ -152,6 +152,8 @@ const char * getBasename(const char * path);
#define OTX_FOURCC 0x3D78746F // otx for Jumper T12
#elif defined(RADIO_TLITE)
#define OTX_FOURCC 0x4278746F // otx for Jumper TLite
+#elif defined(RADIO_TPRO)
+ #define OTX_FOURCC 0x4678746F // otx for Jumper TPro
#elif defined(RADIO_TX12)
#define OTX_FOURCC 0x4178746F // otx for Radiomaster TX12
#elif defined(RADIO_ZORRO)
diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp
index 53410cb2e..e88309434 100644
--- a/radio/src/simu.cpp
+++ b/radio/src/simu.cpp
@@ -445,7 +445,14 @@ void OpenTxSim::updateKeysAndSwitches(bool start)
SWITCH_KEY(C, 2, 3);
SWITCH_KEY(D, 3, 3);
- #if defined(HARDWARE_SWITCH_G) && defined(HARDWARE_SWITCH_H)
+ #if defined(RADIO_TPRO)
+ SWITCH_KEY(1, 4, 2);
+ SWITCH_KEY(2, 5, 2);
+ SWITCH_KEY(3, 6, 2);
+ SWITCH_KEY(4, 7, 2);
+ SWITCH_KEY(5, 8, 2);
+ SWITCH_KEY(6, 9, 2);
+ #elif defined(HARDWARE_SWITCH_G) && defined(HARDWARE_SWITCH_H)
SWITCH_KEY(E, 4, 3);
SWITCH_KEY(F, 5, 2);
SWITCH_KEY(G, 6, 3);
diff --git a/radio/src/storage/conversions/CMakeLists.txt b/radio/src/storage/conversions/CMakeLists.txt
index 601482530..75ec49ad2 100644
--- a/radio/src/storage/conversions/CMakeLists.txt
+++ b/radio/src/storage/conversions/CMakeLists.txt
@@ -1,8 +1,11 @@
set(STORAGE_CONVERSIONS 219)
-if(PCB STREQUAL X7 AND PCBREV STREQUAL ZORRO)
- set(STORAGE_CONVERSIONS 221)
+if(PCB STREQUAL X7)
+ if(PCBREV STREQUAL ZORRO OR PCBREV STREQUAL TPRO)
+ set(STORAGE_CONVERSIONS 221)
+ endif()
endif()
+message("Storage conversion: ${STORAGE_CONVERSIONS}")
if(STORAGE_CONVERSIONS)
add_definitions(-DSTORAGE_CONVERSIONS=${STORAGE_CONVERSIONS})
diff --git a/radio/src/storage/conversions/conversions_219_220.cpp b/radio/src/storage/conversions/conversions_219_220.cpp
index d65d528af..efbaaa7c7 100644
--- a/radio/src/storage/conversions/conversions_219_220.cpp
+++ b/radio/src/storage/conversions/conversions_219_220.cpp
@@ -35,6 +35,8 @@
#include
#endif
+#if STORAGE_CONVERSIONS < 220
+
//
// Summary of all changes between 219 & 220
//
@@ -349,3 +351,5 @@ const char* convertRadioData_219_to_220()
return nullptr;
}
#endif
+
+#endif
diff --git a/radio/src/storage/conversions/conversions_220_221.cpp b/radio/src/storage/conversions/conversions_220_221.cpp
index 634f8b960..7a1981c82 100644
--- a/radio/src/storage/conversions/conversions_220_221.cpp
+++ b/radio/src/storage/conversions/conversions_220_221.cpp
@@ -44,6 +44,8 @@ namespace yaml_conv_220 {
const YamlNode* get_partialmodel_nodes();
};
+#if STORAGE_CONVERSIONS < 221
+
#if defined(STORAGE_MODELSLIST)
void patchFilenameToYaml(char* str);
@@ -184,3 +186,5 @@ const char* convertRadioData_220_to_221()
}
#endif
+
+#endif
diff --git a/radio/src/storage/conversions/yaml/dataconstants_220.h b/radio/src/storage/conversions/yaml/dataconstants_220.h
index aefde174c..a520dd2d2 100644
--- a/radio/src/storage/conversions/yaml/dataconstants_220.h
+++ b/radio/src/storage/conversions/yaml/dataconstants_220.h
@@ -92,6 +92,8 @@
#if defined(PCBXLITES) || defined(PCBXLITE)
#define STORAGE_NUM_SWITCHES 6
+#elif defined(RADIO_TPRO)
+#define STORAGE_NUM_SWITCHES 10
#elif defined(RADIO_TLITE) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_T8) || defined(PCBX7ACCESS) || defined(PCBX7)
#define STORAGE_NUM_SWITCHES 8
#elif defined(PCBX9LITES)
diff --git a/radio/src/storage/conversions/yaml/datastructs_220.h b/radio/src/storage/conversions/yaml/datastructs_220.h
index 2e5392317..b99edaf6e 100644
--- a/radio/src/storage/conversions/yaml/datastructs_220.h
+++ b/radio/src/storage/conversions/yaml/datastructs_220.h
@@ -999,6 +999,9 @@ static inline void check_struct()
#elif defined(PCBXLITE)
CHKSIZE(RadioData, 859);
CHKSIZE(ModelData, 6157);
+#elif defined(RADIO_TPRO)
+ CHKSIZE(RadioData, 860);
+ CHKSIZE(ModelData, 6157);
#elif defined(PCBX7)
CHKSIZE(RadioData, 865);
CHKSIZE(ModelData, 6157);
diff --git a/radio/src/storage/yaml/CMakeLists.txt b/radio/src/storage/yaml/CMakeLists.txt
index f6ca45fc6..0611d5334 100644
--- a/radio/src/storage/yaml/CMakeLists.txt
+++ b/radio/src/storage/yaml/CMakeLists.txt
@@ -29,6 +29,8 @@ elseif(PCB STREQUAL X7)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_zorro.cpp)
elseif(PCBREV STREQUAL T8)
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_t8.cpp)
+ elseif(PCBREV STREQUAL TPRO)
+ set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_tpro.cpp)
else()
set(YAML_GEN_OUTPUT storage/yaml/yaml_datastructs_x7.cpp)
endif()
diff --git a/radio/src/storage/yaml/yaml_datastructs.cpp b/radio/src/storage/yaml/yaml_datastructs.cpp
index 11ae7730f..f7d3d1fa1 100644
--- a/radio/src/storage/yaml/yaml_datastructs.cpp
+++ b/radio/src/storage/yaml/yaml_datastructs.cpp
@@ -44,6 +44,8 @@
#include "yaml_datastructs_zorro.cpp"
#elif defined(RADIO_T8)
#include "yaml_datastructs_t8.cpp"
+ #elif defined(RADIO_TPRO)
+ #include "yaml_datastructs_tpro.cpp"
#else
#include "yaml_datastructs_x7.cpp"
#endif
diff --git a/radio/src/storage/yaml/yaml_datastructs_tpro.cpp b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp
new file mode 100644
index 000000000..bbc59e22c
--- /dev/null
+++ b/radio/src/storage/yaml/yaml_datastructs_tpro.cpp
@@ -0,0 +1,880 @@
+// generated by generate_yaml.py
+
+//
+// Enums first
+//
+
+const struct YamlIdStr enum_BacklightMode[] = {
+ { e_backlight_mode_off, "backlight_mode_off" },
+ { e_backlight_mode_keys, "backlight_mode_keys" },
+ { e_backlight_mode_sticks, "backlight_mode_sticks" },
+ { e_backlight_mode_all, "backlight_mode_all" },
+ { e_backlight_mode_on, "backlight_mode_on" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_AntennaModes[] = {
+ { ANTENNA_MODE_INTERNAL, "MODE_INTERNAL" },
+ { ANTENNA_MODE_ASK, "MODE_ASK" },
+ { ANTENNA_MODE_PER_MODEL, "MODE_PER_MODEL" },
+ { ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" },
+ { ANTENNA_MODE_FIRST, "MODE_FIRST" },
+ { ANTENNA_MODE_LAST, "MODE_LAST" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_ModuleType[] = {
+ { MODULE_TYPE_NONE, "TYPE_NONE" },
+ { MODULE_TYPE_PPM, "TYPE_PPM" },
+ { MODULE_TYPE_XJT_PXX1, "TYPE_XJT_PXX1" },
+ { MODULE_TYPE_ISRM_PXX2, "TYPE_ISRM_PXX2" },
+ { MODULE_TYPE_DSM2, "TYPE_DSM2" },
+ { MODULE_TYPE_CROSSFIRE, "TYPE_CROSSFIRE" },
+ { MODULE_TYPE_MULTIMODULE, "TYPE_MULTIMODULE" },
+ { MODULE_TYPE_R9M_PXX1, "TYPE_R9M_PXX1" },
+ { MODULE_TYPE_R9M_PXX2, "TYPE_R9M_PXX2" },
+ { MODULE_TYPE_R9M_LITE_PXX1, "TYPE_R9M_LITE_PXX1" },
+ { MODULE_TYPE_R9M_LITE_PXX2, "TYPE_R9M_LITE_PXX2" },
+ { MODULE_TYPE_GHOST, "TYPE_GHOST" },
+ { MODULE_TYPE_R9M_LITE_PRO_PXX2, "TYPE_R9M_LITE_PRO_PXX2" },
+ { MODULE_TYPE_SBUS, "TYPE_SBUS" },
+ { MODULE_TYPE_XJT_LITE_PXX2, "TYPE_XJT_LITE_PXX2" },
+ { MODULE_TYPE_FLYSKY, "TYPE_FLYSKY" },
+ { MODULE_TYPE_COUNT, "TYPE_COUNT" },
+ { MODULE_TYPE_MAX, "TYPE_MAX" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_TrainerMultiplex[] = {
+ { TRAINER_OFF, "OFF" },
+ { TRAINER_ADD, "ADD" },
+ { TRAINER_REPL, "REPL" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_BeeperMode[] = {
+ { e_mode_quiet, "mode_quiet" },
+ { e_mode_alarms, "mode_alarms" },
+ { e_mode_nokeys, "mode_nokeys" },
+ { e_mode_all, "mode_all" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_BluetoothModes[] = {
+ { BLUETOOTH_OFF, "OFF" },
+ { BLUETOOTH_TELEMETRY, "TELEMETRY" },
+ { BLUETOOTH_TRAINER, "TRAINER" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_Functions[] = {
+ { FUNC_OVERRIDE_CHANNEL, "OVERRIDE_CHANNEL" },
+ { FUNC_TRAINER, "TRAINER" },
+ { FUNC_INSTANT_TRIM, "INSTANT_TRIM" },
+ { FUNC_RESET, "RESET" },
+ { FUNC_SET_TIMER, "SET_TIMER" },
+ { FUNC_ADJUST_GVAR, "ADJUST_GVAR" },
+ { FUNC_VOLUME, "VOLUME" },
+ { FUNC_SET_FAILSAFE, "SET_FAILSAFE" },
+ { FUNC_RANGECHECK, "RANGECHECK" },
+ { FUNC_BIND, "BIND" },
+ { FUNC_PLAY_SOUND, "PLAY_SOUND" },
+ { FUNC_PLAY_TRACK, "PLAY_TRACK" },
+ { FUNC_PLAY_VALUE, "PLAY_VALUE" },
+ { FUNC_RESERVE4, "RESERVE4" },
+ { FUNC_PLAY_SCRIPT, "PLAY_SCRIPT" },
+ { FUNC_RESERVE5, "RESERVE5" },
+ { FUNC_BACKGND_MUSIC, "BACKGND_MUSIC" },
+ { FUNC_BACKGND_MUSIC_PAUSE, "BACKGND_MUSIC_PAUSE" },
+ { FUNC_VARIO, "VARIO" },
+ { FUNC_HAPTIC, "HAPTIC" },
+ { FUNC_LOGS, "LOGS" },
+ { FUNC_BACKLIGHT, "BACKLIGHT" },
+ { FUNC_SCREENSHOT, "SCREENSHOT" },
+ { FUNC_RACING_MODE, "RACING_MODE" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_UartModes[] = {
+ { UART_MODE_NONE, "MODE_NONE" },
+ { UART_MODE_TELEMETRY_MIRROR, "MODE_TELEMETRY_MIRROR" },
+ { UART_MODE_TELEMETRY, "MODE_TELEMETRY" },
+ { UART_MODE_SBUS_TRAINER, "MODE_SBUS_TRAINER" },
+ { UART_MODE_LUA, "MODE_LUA" },
+ { UART_MODE_COUNT, "MODE_COUNT" },
+ { UART_MODE_MAX, "MODE_MAX" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_TimerModes[] = {
+ { TMRMODE_OFF, "OFF" },
+ { TMRMODE_ON, "ON" },
+ { TMRMODE_START, "START" },
+ { TMRMODE_THR, "THR" },
+ { TMRMODE_THR_REL, "THR_REL" },
+ { TMRMODE_THR_START, "THR_START" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_MixerMultiplex[] = {
+ { MLTPX_ADD, "ADD" },
+ { MLTPX_MUL, "MUL" },
+ { MLTPX_REPL, "REPL" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_MixSources[] = {
+ { MIXSRC_NONE, "NONE" },
+ { MIXSRC_Rud, "Rud" },
+ { MIXSRC_Ele, "Ele" },
+ { MIXSRC_Thr, "Thr" },
+ { MIXSRC_Ail, "Ail" },
+ { MIXSRC_POT1, "POT1" },
+ { MIXSRC_POT2, "POT2" },
+ { MIXSRC_MAX, "MAX" },
+ { MIXSRC_CYC1, "CYC1" },
+ { MIXSRC_CYC2, "CYC2" },
+ { MIXSRC_CYC3, "CYC3" },
+ { MIXSRC_TrimRud, "TrimRud" },
+ { MIXSRC_TrimEle, "TrimEle" },
+ { MIXSRC_TrimThr, "TrimThr" },
+ { MIXSRC_TrimAil, "TrimAil" },
+ { MIXSRC_SA, "SA" },
+ { MIXSRC_SB, "SB" },
+ { MIXSRC_SC, "SC" },
+ { MIXSRC_SD, "SD" },
+ { MIXSRC_SE, "SE" },
+ { MIXSRC_SF, "SF" },
+ { MIXSRC_SG, "SG" },
+ { MIXSRC_SH, "SH" },
+ { MIXSRC_SI, "SI" },
+ { MIXSRC_SJ, "SJ" },
+ { MIXSRC_SW1, "SW1" },
+ { MIXSRC_CH1, "CH1" },
+ { MIXSRC_CH2, "CH2" },
+ { MIXSRC_CH3, "CH3" },
+ { MIXSRC_CH4, "CH4" },
+ { MIXSRC_CH5, "CH5" },
+ { MIXSRC_CH6, "CH6" },
+ { MIXSRC_CH7, "CH7" },
+ { MIXSRC_CH8, "CH8" },
+ { MIXSRC_CH9, "CH9" },
+ { MIXSRC_CH10, "CH10" },
+ { MIXSRC_CH11, "CH11" },
+ { MIXSRC_CH12, "CH12" },
+ { MIXSRC_CH13, "CH13" },
+ { MIXSRC_CH14, "CH14" },
+ { MIXSRC_CH15, "CH15" },
+ { MIXSRC_CH16, "CH16" },
+ { MIXSRC_GVAR1, "GVAR1" },
+ { MIXSRC_TX_VOLTAGE, "TX_VOLTAGE" },
+ { MIXSRC_TX_TIME, "TX_TIME" },
+ { MIXSRC_TX_GPS, "TX_GPS" },
+ { MIXSRC_TIMER1, "TIMER1" },
+ { MIXSRC_TIMER2, "TIMER2" },
+ { MIXSRC_TIMER3, "TIMER3" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_LogicalSwitchesFunctions[] = {
+ { LS_FUNC_NONE, "FUNC_NONE" },
+ { LS_FUNC_VEQUAL, "FUNC_VEQUAL" },
+ { LS_FUNC_VALMOSTEQUAL, "FUNC_VALMOSTEQUAL" },
+ { LS_FUNC_VPOS, "FUNC_VPOS" },
+ { LS_FUNC_VNEG, "FUNC_VNEG" },
+ { LS_FUNC_RANGE, "FUNC_RANGE" },
+ { LS_FUNC_APOS, "FUNC_APOS" },
+ { LS_FUNC_ANEG, "FUNC_ANEG" },
+ { LS_FUNC_AND, "FUNC_AND" },
+ { LS_FUNC_OR, "FUNC_OR" },
+ { LS_FUNC_XOR, "FUNC_XOR" },
+ { LS_FUNC_EDGE, "FUNC_EDGE" },
+ { LS_FUNC_EQUAL, "FUNC_EQUAL" },
+ { LS_FUNC_GREATER, "FUNC_GREATER" },
+ { LS_FUNC_LESS, "FUNC_LESS" },
+ { LS_FUNC_DIFFEGREATER, "FUNC_DIFFEGREATER" },
+ { LS_FUNC_ADIFFEGREATER, "FUNC_ADIFFEGREATER" },
+ { LS_FUNC_TIMER, "FUNC_TIMER" },
+ { LS_FUNC_STICKY, "FUNC_STICKY" },
+ { LS_FUNC_COUNT, "FUNC_COUNT" },
+ { LS_FUNC_MAX, "FUNC_MAX" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_SwashType[] = {
+ { SWASH_TYPE_NONE, "TYPE_NONE" },
+ { SWASH_TYPE_120, "TYPE_120" },
+ { SWASH_TYPE_120X, "TYPE_120X" },
+ { SWASH_TYPE_140, "TYPE_140" },
+ { SWASH_TYPE_90, "TYPE_90" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_SwitchSources[] = {
+ { SWSRC_NONE, "NONE" },
+ { SWSRC_SA0, "SA0" },
+ { SWSRC_SA1, "SA1" },
+ { SWSRC_SA2, "SA2" },
+ { SWSRC_SB0, "SB0" },
+ { SWSRC_SB1, "SB1" },
+ { SWSRC_SB2, "SB2" },
+ { SWSRC_SC0, "SC0" },
+ { SWSRC_SC1, "SC1" },
+ { SWSRC_SC2, "SC2" },
+ { SWSRC_SD0, "SD0" },
+ { SWSRC_SD1, "SD1" },
+ { SWSRC_SD2, "SD2" },
+ { SWSRC_SE0, "SE0" },
+ { SWSRC_SE1, "SE1" },
+ { SWSRC_SE2, "SE2" },
+ { SWSRC_SF0, "SF0" },
+ { SWSRC_SF1, "SF1" },
+ { SWSRC_SF2, "SF2" },
+ { SWSRC_SG0, "SG0" },
+ { SWSRC_SG1, "SG1" },
+ { SWSRC_SG2, "SG2" },
+ { SWSRC_SH0, "SH0" },
+ { SWSRC_SH1, "SH1" },
+ { SWSRC_SH2, "SH2" },
+ { SWSRC_SI0, "SI0" },
+ { SWSRC_SI1, "SI1" },
+ { SWSRC_SI2, "SI2" },
+ { SWSRC_SJ0, "SJ0" },
+ { SWSRC_SJ1, "SJ1" },
+ { SWSRC_SJ2, "SJ2" },
+ { SWSRC_TrimRudLeft, "TrimRudLeft" },
+ { SWSRC_TrimRudRight, "TrimRudRight" },
+ { SWSRC_TrimEleDown, "TrimEleDown" },
+ { SWSRC_TrimEleUp, "TrimEleUp" },
+ { SWSRC_TrimThrDown, "TrimThrDown" },
+ { SWSRC_TrimThrUp, "TrimThrUp" },
+ { SWSRC_TrimAilLeft, "TrimAilLeft" },
+ { SWSRC_TrimAilRight, "TrimAilRight" },
+ { SWSRC_SW1, "SW1" },
+ { SWSRC_SW2, "SW2" },
+ { SWSRC_ON, "ON" },
+ { SWSRC_ONE, "ONE" },
+ { SWSRC_TELEMETRY_STREAMING, "TELEMETRY_STREAMING" },
+ { SWSRC_RADIO_ACTIVITY, "RADIO_ACTIVITY" },
+ { SWSRC_OFF, "OFF" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_PotsWarnMode[] = {
+ { POTS_WARN_OFF, "WARN_OFF" },
+ { POTS_WARN_MANUAL, "WARN_MANUAL" },
+ { POTS_WARN_AUTO, "WARN_AUTO" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_FailsafeModes[] = {
+ { FAILSAFE_NOT_SET, "NOT_SET" },
+ { FAILSAFE_HOLD, "HOLD" },
+ { FAILSAFE_CUSTOM, "CUSTOM" },
+ { FAILSAFE_NOPULSES, "NOPULSES" },
+ { FAILSAFE_RECEIVER, "RECEIVER" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_TelemetrySensorFormula[] = {
+ { TELEM_FORMULA_ADD, "FORMULA_ADD" },
+ { TELEM_FORMULA_AVERAGE, "FORMULA_AVERAGE" },
+ { TELEM_FORMULA_MIN, "FORMULA_MIN" },
+ { TELEM_FORMULA_MAX, "FORMULA_MAX" },
+ { TELEM_FORMULA_MULTIPLY, "FORMULA_MULTIPLY" },
+ { TELEM_FORMULA_TOTALIZE, "FORMULA_TOTALIZE" },
+ { TELEM_FORMULA_CELL, "FORMULA_CELL" },
+ { TELEM_FORMULA_CONSUMPTION, "FORMULA_CONSUMPTION" },
+ { TELEM_FORMULA_DIST, "FORMULA_DIST" },
+ { 0, NULL }
+};
+const struct YamlIdStr enum_TelemetrySensorType[] = {
+ { TELEM_TYPE_CUSTOM, "TYPE_CUSTOM" },
+ { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" },
+ { 0, NULL }
+};
+
+//
+// Structs last
+//
+
+static const struct YamlNode struct_CalibData[] = {
+ YAML_IDX_CUST("calib",r_calib,w_calib),
+ YAML_SIGNED( "mid", 16 ),
+ YAML_SIGNED( "spanNeg", 16 ),
+ YAML_SIGNED( "spanPos", 16 ),
+ YAML_END
+};
+static const struct YamlNode struct_signed_16[] = {
+ YAML_IDX,
+ YAML_SIGNED( "val", 16 ),
+ YAML_END
+};
+static const struct YamlNode struct_TrainerMix[] = {
+ YAML_IDX,
+ YAML_UNSIGNED( "srcChn", 6 ),
+ YAML_ENUM("mode", 2, enum_TrainerMultiplex),
+ YAML_SIGNED( "studWeight", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_TrainerData[] = {
+ YAML_ARRAY("calib", 16, 4, struct_signed_16, NULL),
+ YAML_ARRAY("mix", 16, 4, struct_TrainerMix, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_1[] = {
+ YAML_STRING("name", 6),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_2[] = {
+ YAML_SIGNED( "val", 16 ),
+ YAML_UNSIGNED( "mode", 8 ),
+ YAML_UNSIGNED( "param", 8 ),
+ YAML_SIGNED( "spare", 32 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_3[] = {
+ YAML_SIGNED( "val1", 32 ),
+ YAML_SIGNED( "val2", 32 ),
+ YAML_END
+};
+static const struct YamlNode union_anonymous_0_elmts[] = {
+ YAML_STRUCT("play", 48, struct_anonymous_1, NULL),
+ YAML_STRUCT("all", 64, struct_anonymous_2, NULL),
+ YAML_STRUCT("clear", 64, struct_anonymous_3, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_CustomFunctionData[] = {
+ YAML_IDX,
+ YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
+ YAML_ENUM("func", 7, enum_Functions),
+ YAML_CUSTOM("def",r_customFn,w_customFn),
+ YAML_PADDING( 64 ),
+ YAML_PADDING( 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_string_24[] = {
+ YAML_IDX,
+ YAML_STRING("val", 3),
+ YAML_END
+};
+static const struct YamlNode struct_RadioData[] = {
+ YAML_UNSIGNED( "version", 8 ),
+ YAML_PADDING( 16 ),
+ YAML_ARRAY("calib", 48, 6, struct_CalibData, NULL),
+ YAML_PADDING( 16 ),
+ YAML_SIGNED( "currModel", 8 ),
+ YAML_UNSIGNED( "contrast", 8 ),
+ YAML_UNSIGNED( "vBatWarn", 8 ),
+ YAML_SIGNED( "txVoltageCalibration", 8 ),
+ YAML_ENUM("backlightMode", 3, enum_BacklightMode),
+ YAML_ENUM("antennaMode", 2, enum_AntennaModes),
+ YAML_UNSIGNED( "disableRtcWarning", 1 ),
+ YAML_UNSIGNED( "keysBacklight", 1 ),
+ YAML_PADDING( 1 ),
+ YAML_ENUM("internalModule", 8, enum_ModuleType),
+ YAML_STRUCT("trainer", 128, struct_TrainerData, NULL),
+ YAML_UNSIGNED( "view", 8 ),
+ YAML_PADDING( 2 ),
+ YAML_UNSIGNED( "fai", 1 ),
+ YAML_SIGNED_CUST( "beepMode", 2, r_beeperMode, w_beeperMode ),
+ YAML_UNSIGNED( "alarmsFlash", 1 ),
+ YAML_UNSIGNED( "disableMemoryWarning", 1 ),
+ YAML_UNSIGNED( "disableAlarmWarning", 1 ),
+ YAML_UNSIGNED( "stickMode", 2 ),
+ YAML_SIGNED( "timezone", 5 ),
+ YAML_UNSIGNED( "adjustRTC", 1 ),
+ YAML_UNSIGNED( "inactivityTimer", 8 ),
+ YAML_UNSIGNED( "telemetryBaudrate", 3 ),
+ YAML_SIGNED( "splashMode", 3 ),
+ YAML_SIGNED_CUST( "hapticMode", 2, r_beeperMode, w_beeperMode ),
+ YAML_SIGNED( "switchesDelay", 8 ),
+ YAML_UNSIGNED( "lightAutoOff", 8 ),
+ YAML_UNSIGNED( "templateSetup", 8 ),
+ YAML_SIGNED( "PPM_Multiplier", 8 ),
+ YAML_SIGNED_CUST( "hapticLength", 8, r_5pos, w_5pos ),
+ YAML_SIGNED_CUST( "beepLength", 3, r_5pos, w_5pos ),
+ YAML_SIGNED_CUST( "hapticStrength", 3, r_5pos, w_5pos ),
+ YAML_UNSIGNED( "gpsFormat", 1 ),
+ YAML_UNSIGNED( "unexpectedShutdown", 1 ),
+ YAML_UNSIGNED_CUST( "speakerPitch", 8, r_spPitch, w_spPitch ),
+ YAML_SIGNED_CUST( "speakerVolume", 8, r_vol, w_vol ),
+ YAML_SIGNED_CUST( "vBatMin", 8, r_vbat_min, w_vbat_min ),
+ YAML_SIGNED_CUST( "vBatMax", 8, r_vbat_max, w_vbat_max ),
+ YAML_UNSIGNED( "backlightBright", 8 ),
+ YAML_UNSIGNED( "globalTimer", 32 ),
+ YAML_UNSIGNED( "bluetoothBaudrate", 4 ),
+ YAML_ENUM("bluetoothMode", 4, enum_BluetoothModes),
+ YAML_UNSIGNED( "countryCode", 2 ),
+ YAML_SIGNED( "pwrOnSpeed", 3 ),
+ YAML_SIGNED( "pwrOffSpeed", 3 ),
+ YAML_UNSIGNED( "imperial", 1 ),
+ YAML_UNSIGNED( "jitterFilter", 1 ),
+ YAML_UNSIGNED( "disableRssiPoweroffAlarm", 1 ),
+ YAML_UNSIGNED( "USBMode", 2 ),
+ YAML_UNSIGNED( "jackMode", 2 ),
+ YAML_PADDING( 1 ),
+ YAML_STRING("ttsLanguage", 2),
+ YAML_SIGNED_CUST( "beepVolume", 4, r_5pos, w_5pos ),
+ YAML_SIGNED_CUST( "wavVolume", 4, r_5pos, w_5pos ),
+ YAML_SIGNED_CUST( "varioVolume", 4, r_5pos, w_5pos ),
+ YAML_SIGNED_CUST( "backgroundVolume", 4, r_5pos, w_5pos ),
+ YAML_SIGNED_CUST( "varioPitch", 8, r_vPitch, w_vPitch ),
+ YAML_SIGNED_CUST( "varioRange", 8, r_vPitch, w_vPitch ),
+ YAML_SIGNED( "varioRepeat", 8 ),
+ YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
+ YAML_ENUM("auxSerialMode", 4, enum_UartModes),
+ YAML_ARRAY("slidersConfig", 1, 4, struct_sliderConfig, nullptr),
+ YAML_ARRAY("potsConfig", 2, 4, struct_potConfig, nullptr),
+ YAML_UNSIGNED( "backlightColor", 8 ),
+ YAML_ARRAY("sticksConfig", 0, 4, struct_sticksConfig, stick_name_valid),
+ YAML_ARRAY("switchConfig", 2, 8, struct_switchConfig, nullptr),
+ YAML_PADDING( 96 ),
+ YAML_PADDING( 144 ),
+ YAML_STRING("ownerRegistrationID", 8),
+ YAML_SIGNED( "uartSampleMode", 2 ),
+ YAML_END
+};
+static const struct YamlNode struct_unsigned_8[] = {
+ YAML_IDX,
+ YAML_UNSIGNED( "val", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_ModelHeader[] = {
+ YAML_STRING("name", 10),
+ YAML_ARRAY("modelId", 8, 2, struct_unsigned_8, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_TimerData[] = {
+ YAML_IDX,
+ YAML_UNSIGNED( "start", 22 ),
+ YAML_SIGNED_CUST( "swtch", 10, r_swtchSrc, w_swtchSrc ),
+ YAML_SIGNED( "value", 22 ),
+ YAML_ENUM("mode", 3, enum_TimerModes),
+ YAML_UNSIGNED( "countdownBeep", 2 ),
+ YAML_UNSIGNED( "minuteBeep", 1 ),
+ YAML_UNSIGNED( "persistent", 2 ),
+ YAML_SIGNED( "countdownStart", 2 ),
+ YAML_STRING("name", 3),
+ YAML_END
+};
+static const struct YamlNode struct_CurveRef[] = {
+ YAML_UNSIGNED( "type", 8 ),
+ YAML_SIGNED( "value", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_MixData[] = {
+ YAML_SIGNED_CUST( "weight", 11, in_read_weight, in_write_weight ),
+ YAML_UNSIGNED( "destCh", 5 ),
+ YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_UNSIGNED( "carryTrim", 1 ),
+ YAML_UNSIGNED( "mixWarn", 2 ),
+ YAML_ENUM("mltpx", 2, enum_MixerMultiplex),
+ YAML_PADDING( 1 ),
+ YAML_SIGNED( "offset", 14 ),
+ YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
+ YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
+ YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
+ YAML_UNSIGNED( "delayUp", 8 ),
+ YAML_UNSIGNED( "delayDown", 8 ),
+ YAML_UNSIGNED( "speedUp", 8 ),
+ YAML_UNSIGNED( "speedDown", 8 ),
+ YAML_STRING("name", 6),
+ YAML_END
+};
+static const struct YamlNode struct_LimitData[] = {
+ YAML_IDX,
+ YAML_SIGNED( "min", 11 ),
+ YAML_SIGNED( "max", 11 ),
+ YAML_SIGNED( "ppmCenter", 10 ),
+ YAML_SIGNED( "offset", 11 ),
+ YAML_UNSIGNED( "symetrical", 1 ),
+ YAML_UNSIGNED( "revert", 1 ),
+ YAML_PADDING( 3 ),
+ YAML_SIGNED( "curve", 8 ),
+ YAML_STRING("name", 4),
+ YAML_END
+};
+static const struct YamlNode struct_ExpoData[] = {
+ YAML_UNSIGNED( "mode", 2 ),
+ YAML_UNSIGNED( "scale", 14 ),
+ YAML_UNSIGNED_CUST( "srcRaw", 10, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_SIGNED( "carryTrim", 6 ),
+ YAML_UNSIGNED( "chn", 5 ),
+ YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
+ YAML_UNSIGNED_CUST( "flightModes", 9, r_flightModes, w_flightModes ),
+ YAML_SIGNED_CUST( "weight", 8, in_read_weight, in_write_weight ),
+ YAML_PADDING( 1 ),
+ YAML_STRING("name", 6),
+ YAML_SIGNED( "offset", 8 ),
+ YAML_STRUCT("curve", 16, struct_CurveRef, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_CurveHeader[] = {
+ YAML_IDX,
+ YAML_UNSIGNED( "type", 1 ),
+ YAML_UNSIGNED( "smooth", 1 ),
+ YAML_SIGNED( "points", 6 ),
+ YAML_STRING("name", 3),
+ YAML_END
+};
+static const struct YamlNode struct_signed_8[] = {
+ YAML_IDX,
+ YAML_SIGNED( "val", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_LogicalSwitchData[] = {
+ YAML_IDX,
+ YAML_ENUM("func", 8, enum_LogicalSwitchesFunctions),
+ YAML_CUSTOM("def",r_logicSw,w_logicSw),
+ YAML_PADDING( 10 ),
+ YAML_PADDING( 10 ),
+ YAML_SIGNED_CUST( "andsw", 9, r_swtchSrc, w_swtchSrc ),
+ YAML_PADDING( 1 ),
+ YAML_PADDING( 2 ),
+ YAML_PADDING( 16 ),
+ YAML_UNSIGNED( "delay", 8 ),
+ YAML_UNSIGNED( "duration", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_SwashRingData[] = {
+ YAML_ENUM("type", 8, enum_SwashType),
+ YAML_UNSIGNED( "value", 8 ),
+ YAML_UNSIGNED_CUST( "collectiveSource", 8, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_UNSIGNED_CUST( "aileronSource", 8, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_UNSIGNED_CUST( "elevatorSource", 8, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_SIGNED( "collectiveWeight", 8 ),
+ YAML_SIGNED( "aileronWeight", 8 ),
+ YAML_SIGNED( "elevatorWeight", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_trim_t[] = {
+ YAML_IDX,
+ YAML_SIGNED( "value", 11 ),
+ YAML_UNSIGNED( "mode", 5 ),
+ YAML_END
+};
+static const struct YamlNode struct_FlightModeData[] = {
+ YAML_IDX,
+ YAML_ARRAY("trim", 16, 4, struct_trim_t, NULL),
+ YAML_STRING("name", 6),
+ YAML_SIGNED_CUST( "swtch", 9, r_swtchSrc, w_swtchSrc ),
+ YAML_PADDING( 7 ),
+ YAML_UNSIGNED( "fadeIn", 8 ),
+ YAML_UNSIGNED( "fadeOut", 8 ),
+ YAML_ARRAY("gvars", 16, 9, struct_signed_16, gvar_is_active),
+ YAML_END
+};
+static const struct YamlNode struct_GVarData[] = {
+ YAML_IDX,
+ YAML_STRING("name", 3),
+ YAML_UNSIGNED( "min", 12 ),
+ YAML_UNSIGNED( "max", 12 ),
+ YAML_UNSIGNED( "popup", 1 ),
+ YAML_UNSIGNED( "prec", 1 ),
+ YAML_UNSIGNED( "unit", 2 ),
+ YAML_PADDING( 4 ),
+ YAML_END
+};
+static const struct YamlNode struct_VarioData[] = {
+ YAML_UNSIGNED_CUST( "source", 7, r_tele_sensor, w_tele_sensor ),
+ YAML_UNSIGNED( "centerSilent", 1 ),
+ YAML_SIGNED( "centerMax", 8 ),
+ YAML_SIGNED( "centerMin", 8 ),
+ YAML_SIGNED( "min", 8 ),
+ YAML_SIGNED( "max", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_RssiAlarmData[] = {
+ YAML_SIGNED( "disabled", 1 ),
+ YAML_PADDING( 1 ),
+ YAML_SIGNED( "warning", 6 ),
+ YAML_PADDING( 2 ),
+ YAML_SIGNED( "critical", 6 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_5[] = {
+ YAML_SIGNED( "delay", 6 ),
+ YAML_UNSIGNED( "pulsePol", 1 ),
+ YAML_UNSIGNED( "outputType", 1 ),
+ YAML_SIGNED( "frameLength", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_6[] = {
+ YAML_PADDING( 3 ),
+ YAML_UNSIGNED( "disableTelemetry", 1 ),
+ YAML_UNSIGNED( "disableMapping", 1 ),
+ YAML_PADDING( 1 ),
+ YAML_UNSIGNED( "autoBindMode", 1 ),
+ YAML_UNSIGNED( "lowPowerMode", 1 ),
+ YAML_SIGNED( "optionValue", 8 ),
+ YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
+ YAML_UNSIGNED( "receiverHigherChannels", 1 ),
+ YAML_PADDING( 6 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_7[] = {
+ YAML_UNSIGNED( "power", 2 ),
+ YAML_PADDING( 2 ),
+ YAML_UNSIGNED( "receiverTelemetryOff", 1 ),
+ YAML_UNSIGNED( "receiverHigherChannels", 1 ),
+ YAML_SIGNED( "antennaMode", 2 ),
+ YAML_PADDING( 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_8[] = {
+ YAML_PADDING( 6 ),
+ YAML_UNSIGNED( "noninverted", 1 ),
+ YAML_PADDING( 1 ),
+ YAML_SIGNED( "refreshRate", 8 ),
+ YAML_END
+};
+static const struct YamlNode struct_string_64[] = {
+ YAML_IDX,
+ YAML_STRING("val", 8),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_9[] = {
+ YAML_UNSIGNED( "receivers", 7 ),
+ YAML_UNSIGNED( "racingMode", 1 ),
+ YAML_ARRAY("receiverName", 64, 3, struct_string_64, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_10[] = {
+ YAML_ARRAY("rx_id", 8, 4, struct_unsigned_8, NULL),
+ YAML_UNSIGNED( "mode", 3 ),
+ YAML_UNSIGNED( "rfPower", 1 ),
+ YAML_UNSIGNED( "reserved", 4 ),
+ YAML_ARRAY("rx_freq", 8, 2, struct_unsigned_8, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_11[] = {
+ YAML_UNSIGNED( "bindPower", 3 ),
+ YAML_UNSIGNED( "runPower", 3 ),
+ YAML_UNSIGNED( "emi", 1 ),
+ YAML_UNSIGNED( "telemetry", 1 ),
+ YAML_UNSIGNED( "failsafeTimeout", 16 ),
+ YAML_ARRAY("rx_freq", 8, 2, struct_unsigned_8, NULL),
+ YAML_UNSIGNED( "mode", 2 ),
+ YAML_UNSIGNED( "reserved", 6 ),
+ YAML_END
+};
+static const struct YamlNode union_anonymous_4_elmts[] = {
+ YAML_ARRAY("raw", 8, 25, struct_unsigned_8, NULL),
+ YAML_STRUCT("ppm", 16, struct_anonymous_5, NULL),
+ YAML_STRUCT("multi", 24, struct_anonymous_6, NULL),
+ YAML_STRUCT("pxx", 16, struct_anonymous_7, NULL),
+ YAML_STRUCT("sbus", 16, struct_anonymous_8, NULL),
+ YAML_STRUCT("pxx2", 200, struct_anonymous_9, NULL),
+ YAML_STRUCT("flysky", 56, struct_anonymous_10, NULL),
+ YAML_STRUCT("afhds3", 64, struct_anonymous_11, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_ModuleData[] = {
+ YAML_IDX,
+ YAML_ENUM("type", 4, enum_ModuleType),
+ YAML_PADDING( 4 ),
+ YAML_CUSTOM("subType",r_modSubtype,w_modSubtype),
+ YAML_UNSIGNED( "channelsStart", 8 ),
+ YAML_SIGNED_CUST( "channelsCount", 8, r_channelsCount, w_channelsCount ),
+ YAML_ENUM("failsafeMode", 4, enum_FailsafeModes),
+ YAML_PADDING( 3 ),
+ YAML_PADDING( 1 ),
+ YAML_UNION("mod", 200, union_anonymous_4_elmts, select_mod_type),
+ YAML_END
+};
+static const struct YamlNode struct_TrainerModuleData[] = {
+ YAML_UNSIGNED_CUST( "mode", 8, r_trainerMode, w_trainerMode ),
+ YAML_UNSIGNED( "channelsStart", 8 ),
+ YAML_SIGNED( "channelsCount", 8 ),
+ YAML_SIGNED( "frameLength", 8 ),
+ YAML_SIGNED( "delay", 6 ),
+ YAML_UNSIGNED( "pulsePol", 1 ),
+ YAML_PADDING( 1 ),
+ YAML_END
+};
+static const struct YamlNode union_ScriptDataInput_elmts[] = {
+ YAML_SIGNED( "value", 16 ),
+ YAML_UNSIGNED_CUST( "source", 16, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_END
+};
+static const struct YamlNode union_ScriptDataInput[] = {
+ YAML_IDX,
+ YAML_UNION("u", 16, union_ScriptDataInput_elmts, select_script_input),
+ YAML_END
+};
+static const struct YamlNode struct_ScriptData[] = {
+ YAML_IDX,
+ YAML_STRING("file", 6),
+ YAML_STRING("name", 6),
+ YAML_ARRAY("inputs", 16, 6, union_ScriptDataInput, NULL),
+ YAML_END
+};
+static const struct YamlNode union_anonymous_12_elmts[] = {
+ YAML_UNSIGNED( "id", 16 ),
+ YAML_UNSIGNED( "persistentValue", 16 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_14[] = {
+ YAML_UNSIGNED( "physID", 5 ),
+ YAML_UNSIGNED( "rxIndex", 3 ),
+ YAML_END
+};
+static const struct YamlNode union_anonymous_13_elmts[] = {
+ YAML_STRUCT("frskyInstance", 8, struct_anonymous_14, NULL),
+ YAML_UNSIGNED( "instance", 8 ),
+ YAML_ENUM("formula", 8, enum_TelemetrySensorFormula),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_16[] = {
+ YAML_UNSIGNED( "ratio", 16 ),
+ YAML_SIGNED( "offset", 16 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_17[] = {
+ YAML_UNSIGNED( "source", 8 ),
+ YAML_UNSIGNED( "index", 8 ),
+ YAML_PADDING( 16 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_18[] = {
+ YAML_ARRAY("sources", 8, 4, struct_signed_8, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_19[] = {
+ YAML_UNSIGNED( "source", 8 ),
+ YAML_PADDING( 24 ),
+ YAML_END
+};
+static const struct YamlNode struct_anonymous_20[] = {
+ YAML_UNSIGNED( "gps", 8 ),
+ YAML_UNSIGNED( "alt", 8 ),
+ YAML_PADDING( 16 ),
+ YAML_END
+};
+static const struct YamlNode union_anonymous_15_elmts[] = {
+ YAML_STRUCT("custom", 32, struct_anonymous_16, NULL),
+ YAML_STRUCT("cell", 32, struct_anonymous_17, NULL),
+ YAML_STRUCT("calc", 32, struct_anonymous_18, NULL),
+ YAML_STRUCT("consumption", 32, struct_anonymous_19, NULL),
+ YAML_STRUCT("dist", 32, struct_anonymous_20, NULL),
+ YAML_UNSIGNED( "param", 32 ),
+ YAML_END
+};
+static const struct YamlNode struct_TelemetrySensor[] = {
+ YAML_IDX,
+ YAML_UNION("id1", 16, union_anonymous_12_elmts, select_id1),
+ YAML_UNION("id2", 8, union_anonymous_13_elmts, select_id2),
+ YAML_STRING("label", 4),
+ YAML_UNSIGNED( "subId", 8 ),
+ YAML_ENUM("type", 1, enum_TelemetrySensorType),
+ YAML_PADDING( 1 ),
+ YAML_UNSIGNED( "unit", 6 ),
+ YAML_UNSIGNED( "prec", 2 ),
+ YAML_UNSIGNED( "autoOffset", 1 ),
+ YAML_UNSIGNED( "filter", 1 ),
+ YAML_UNSIGNED( "logs", 1 ),
+ YAML_UNSIGNED( "persistent", 1 ),
+ YAML_UNSIGNED( "onlyPositive", 1 ),
+ YAML_PADDING( 1 ),
+ YAML_UNION("cfg", 32, union_anonymous_15_elmts, select_sensor_cfg),
+ YAML_END
+};
+static const struct YamlNode struct_FrSkyBarData[] = {
+ YAML_IDX,
+ YAML_UNSIGNED_CUST( "source", 16, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_SIGNED( "barMin", 16 ),
+ YAML_SIGNED( "barMax", 16 ),
+ YAML_END
+};
+static const struct YamlNode struct_LineDataSource[] = {
+ YAML_IDX,
+ YAML_UNSIGNED_CUST( "val", 16, r_mixSrcRaw, w_mixSrcRaw ),
+ YAML_END
+};
+static const struct YamlNode struct_FrSkyLineData[] = {
+ YAML_IDX,
+ YAML_ARRAY("sources", 16, 2, struct_LineDataSource, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_TelemetryScriptData[] = {
+ YAML_STRING("file", 6),
+ YAML_ARRAY("inputs", 16, 8, struct_signed_16, NULL),
+ YAML_END
+};
+static const struct YamlNode union_TelemetryScreenData_u_elmts[] = {
+ YAML_ARRAY("bars", 48, 4, struct_FrSkyBarData, NULL),
+ YAML_ARRAY("lines", 32, 4, struct_FrSkyLineData, NULL),
+ YAML_STRUCT("script", 176, struct_TelemetryScriptData, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_TelemetryScreenData[] = {
+ YAML_IDX,
+ YAML_CUSTOM("type",r_tele_screen_type,w_tele_screen_type),
+ YAML_UNION("u", 192, union_TelemetryScreenData_u_elmts, select_tele_screen_data),
+ YAML_END
+};
+static const struct YamlNode struct_ModelData[] = {
+ YAML_STRUCT("header", 96, struct_ModelHeader, NULL),
+ YAML_ARRAY("timers", 88, 3, struct_TimerData, NULL),
+ YAML_UNSIGNED( "telemetryProtocol", 3 ),
+ YAML_UNSIGNED( "thrTrim", 1 ),
+ YAML_UNSIGNED( "noGlobalFunctions", 1 ),
+ YAML_UNSIGNED( "displayTrims", 2 ),
+ YAML_UNSIGNED( "ignoreSensorIds", 1 ),
+ YAML_SIGNED( "trimInc", 3 ),
+ YAML_UNSIGNED( "disableThrottleWarning", 1 ),
+ YAML_UNSIGNED( "displayChecklist", 1 ),
+ YAML_UNSIGNED( "extendedLimits", 1 ),
+ YAML_UNSIGNED( "extendedTrims", 1 ),
+ YAML_UNSIGNED( "throttleReversed", 1 ),
+ YAML_UNSIGNED( "beepANACenter", 16 ),
+ YAML_ARRAY("mixData", 160, 64, struct_MixData, NULL),
+ YAML_ARRAY("limitData", 88, 32, struct_LimitData, NULL),
+ YAML_ARRAY("expoData", 136, 64, struct_ExpoData, NULL),
+ YAML_ARRAY("curves", 32, 32, struct_CurveHeader, NULL),
+ YAML_ARRAY("points", 8, 512, struct_signed_8, NULL),
+ YAML_ARRAY("logicalSw", 72, 64, struct_LogicalSwitchData, NULL),
+ YAML_ARRAY("customFn", 88, 64, struct_CustomFunctionData, cfn_is_active),
+ YAML_STRUCT("swashR", 64, struct_SwashRingData, swash_is_active),
+ YAML_ARRAY("flightModeData", 288, 9, struct_FlightModeData, fmd_is_active),
+ YAML_UNSIGNED_CUST( "thrTraceSrc", 8, r_thrSrc, w_thrSrc ),
+ YAML_CUSTOM("switchWarningState",r_swtchWarn,w_swtchWarn),
+ YAML_PADDING( 32 ),
+ YAML_ARRAY("gvars", 56, 9, struct_GVarData, NULL),
+ YAML_STRUCT("varioData", 40, struct_VarioData, NULL),
+ YAML_UNSIGNED_CUST( "rssiSource", 8, r_tele_sensor, w_tele_sensor ),
+ YAML_STRUCT("rssiAlarms", 16, struct_RssiAlarmData, NULL),
+ YAML_PADDING( 3 ),
+ YAML_UNSIGNED( "thrTrimSw", 3 ),
+ YAML_ENUM("potsWarnMode", 2, enum_PotsWarnMode),
+ YAML_ARRAY("moduleData", 232, 2, struct_ModuleData, NULL),
+ YAML_ARRAY("failsafeChannels", 16, 32, struct_signed_16, NULL),
+ YAML_STRUCT("trainerData", 40, struct_TrainerModuleData, NULL),
+ YAML_ARRAY("scriptsData", 192, 7, struct_ScriptData, NULL),
+ YAML_ARRAY("inputNames", 24, 32, struct_string_24, NULL),
+ YAML_UNSIGNED( "potsWarnEnabled", 16 ),
+ YAML_ARRAY("potsWarnPosition", 8, 2, struct_signed_8, NULL),
+ YAML_ARRAY("telemetrySensors", 112, 40, struct_TelemetrySensor, NULL),
+ YAML_PADDING( 8 ),
+ YAML_ARRAY("screens", 192, 4, struct_TelemetryScreenData, NULL),
+ YAML_UNSIGNED( "view", 8 ),
+ YAML_STRING("modelRegistrationID", 8),
+ YAML_UNSIGNED( "functionSwitchConfig", 16 ),
+ YAML_UNSIGNED( "functionSwitchGroup", 16 ),
+ YAML_UNSIGNED( "functionSwitchStartConfig", 16 ),
+ YAML_UNSIGNED( "functionSwitchLogicalState", 8 ),
+ YAML_ARRAY("switchNames", 24, 6, struct_string_24, NULL),
+ YAML_END
+};
+static const struct YamlNode struct_PartialModel[] = {
+ YAML_STRUCT("header", 96, struct_ModelHeader, NULL),
+ YAML_ARRAY("timers", 88, 3, struct_TimerData, NULL),
+ YAML_END
+};
+
+#define MAX_RADIODATA_MODELDATA_PARTIALMODEL_STR_LEN 26
+
+static const struct YamlNode __RadioData_root_node = YAML_ROOT( struct_RadioData );
+
+const YamlNode* get_radiodata_nodes()
+{
+ return &__RadioData_root_node;
+}
+static const struct YamlNode __ModelData_root_node = YAML_ROOT( struct_ModelData );
+
+const YamlNode* get_modeldata_nodes()
+{
+ return &__ModelData_root_node;
+}
+static const struct YamlNode __PartialModel_root_node = YAML_ROOT( struct_PartialModel );
+
+const YamlNode* get_partialmodel_nodes()
+{
+ return &__PartialModel_root_node;
+}
+
diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp
index 291e109ae..885201f86 100644
--- a/radio/src/strhelpers.cpp
+++ b/radio/src/strhelpers.cpp
@@ -444,20 +444,20 @@ int getRawSwitchIdx(char sw)
char getRawSwitchFromIdx(int idx)
{
-#if defined(PCBX7) && !defined(RADIO_TX12) && !defined(RADIO_ZORRO)
+#if defined(PCBX7) && !defined(RADIO_TX12) && !defined(RADIO_ZORRO) && !defined(RADIO_TPRO)
if (idx >= 5)
return 'H' + idx - 5;
else if (idx == 4)
-#if defined(RADIO_T12)
+ #if defined(RADIO_T12)
return 'G';
-#else
+ #else
return 'F';
-#endif
+ #endif
else
return 'A' + idx;
#else
return 'A' + idx;
-#endif
+#endif
}
char *getSwitchName(char *dest, swsrc_t idx)
@@ -467,6 +467,13 @@ char *getSwitchName(char *dest, swsrc_t idx)
dest =
strAppend(dest, g_eeGeneral.switchNames[swinfo.quot], LEN_SWITCH_NAME);
} else {
+#if defined(FUNCTIONS_SWITCHES)
+ if (swinfo.quot >= NUM_REGULAR_SWITCHES) {
+ *dest++ = 'W';
+ *dest++ = '1' + swinfo.quot - 4;
+ return dest;
+ }
+#endif
*dest++ = 'S';
*dest++ = getRawSwitchFromIdx(swinfo.quot);
}
diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp
index 5d77bb168..d8f5b8819 100644
--- a/radio/src/switches.cpp
+++ b/radio/src/switches.cpp
@@ -70,6 +70,85 @@ uint8_t potsPos[NUM_XPOTS];
#define SWITCH_POSITION(sw) (switchesPos & ((MASK_CFN_TYPE)1<<(sw)))
#define POT_POSITION(sw) ((potsPos[(sw)/XPOTS_MULTIPOS_COUNT] & 0x0f) == ((sw) % XPOTS_MULTIPOS_COUNT))
+#if defined(FUNCTION_SWITCHES)
+// Non pushed : SWSRC_Sx0 = -1024 = Sx(up) = state 0
+// Pushed : SWSRC_Sx2 = +1024 = Sx(down) = state 1
+
+uint8_t fsPreviousState = 0;
+
+void setFSStartupPosition()
+{
+ for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) {
+ uint8_t startPos = (g_model.functionSwitchStartConfig >> 2 * i) & 0x03;
+ switch(startPos) {
+ case FS_START_DOWN:
+ g_model.functionSwitchLogicalState &= ~(1 << i); // clear state
+ break;
+
+ case FS_START_UP:
+ g_model.functionSwitchLogicalState |= 1 << i;
+ break;
+
+ case FS_START_PREVIOUS:
+ default:
+ // Do nothing, use existing g_model.functionSwitchLogicalState value
+ break;
+ }
+ }
+}
+
+uint8_t getFSLogicalState(uint8_t index)
+{
+ return (uint8_t )(bfSingleBitGet(g_model.functionSwitchLogicalState, index) >> (index));
+}
+
+uint8_t getFSPhysicalState(uint8_t index)
+{
+ return switchState(((index + NUM_REGULAR_SWITCHES) * 3) + 2) ? 1 : 0;
+}
+
+uint8_t getFSPreviousPhysicalState(uint8_t index)
+{
+ return (uint8_t )(bfSingleBitGet(fsPreviousState, index) >> (index));
+}
+
+void evalFunctionSwitches()
+{
+ for (uint8_t i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) {
+ if (FSWITCH_CONFIG(i) == SWITCH_NONE) {
+ fsLedOff(i);
+ continue;
+ }
+
+ uint8_t physicalState = getFSPhysicalState(i);
+ if (physicalState != getFSPreviousPhysicalState(i)) { // FS was moved
+ if (FSWITCH_CONFIG(i) == SWITCH_2POS && physicalState == 1) {
+ g_model.functionSwitchLogicalState ^= 1 << i; // Toggle bit
+ }
+ else if (FSWITCH_CONFIG(i) == SWITCH_TOGGLE) {
+ g_model.functionSwitchLogicalState ^= (physicalState ^ g_model.functionSwitchLogicalState) & (1 << i); // Set bit to switch value
+ }
+ if (FSWITCH_GROUP(i) && physicalState == 1) { // switch is in a group, other in group need to be turned off
+ for (uint8_t j = 0; j < NUM_FUNCTIONS_SWITCHES; j++) {
+ if (i == j)
+ continue;
+ if (FSWITCH_GROUP(j) == FSWITCH_GROUP(i)) {
+ g_model.functionSwitchLogicalState &= ~(1 << j); // clear state
+ }
+ }
+ }
+ fsPreviousState ^= 1 << i; // Toggle state
+ storageDirty(EE_MODEL);
+ }
+
+ if (getFSLogicalState(i))
+ fsLedOn(i);
+ else
+ fsLedOff(i);
+ }
+}
+#endif
+
div_t switchInfo(int switchPosition)
{
return div(switchPosition-SWSRC_FIRST_SWITCH, 3);
@@ -133,6 +212,11 @@ void getSwitchesPosition(bool startup)
CHECK_2POS(SW_SA);
CHECK_3POS(0, SW_SB);
CHECK_3POS(1, SW_SC);
+#elif defined(RADIO_TPRO)
+ CHECK_3POS(0, SW_SA);
+ CHECK_3POS(1, SW_SB);
+ CHECK_2POS(SW_SC);
+ CHECK_2POS(SW_SD);
#else
CHECK_3POS(0, SW_SA);
CHECK_3POS(1, SW_SB);
@@ -165,14 +249,24 @@ void getSwitchesPosition(bool startup)
CHECK_2POS(SW_SD);
CHECK_3POS(2, SW_SE);
CHECK_3POS(3, SW_SF);
+#elif defined(RADIO_TPRO)
+ CHECK_2POS(SW_SE);
+ CHECK_2POS(SW_SF);
+ CHECK_2POS(SW_SG);
+ CHECK_2POS(SW_SH);
+ CHECK_2POS(SW_SI);
+ CHECK_2POS(SW_SJ);
#elif defined(PCBX7)
CHECK_3POS(3, SW_SD);
- #if defined(RADIO_T12)
- CHECK_2POS(SW_SG);
- #else
+ #if defined(HARDWARE_SWITCH_F)
CHECK_2POS(SW_SF);
#endif
- CHECK_2POS(SW_SH);
+ #if defined(HARDWARE_SWITCH_G)
+ CHECK_2POS(SW_SG);
+ #endif
+ #if defined(HARDWARE_SWITCH_H)
+ CHECK_2POS(SW_SH);
+ #endif
#else
CHECK_3POS(3, SW_SD);
CHECK_3POS(4, SW_SE);
@@ -456,8 +550,8 @@ bool getSwitch(swsrc_t swtch, uint8_t flags)
result = latencyToggleSwitch;
}
#endif
- else if (cs_idx <= SWSRC_LAST_SWITCH) {
-#if defined(PCBFRSKY)
+ else if (cs_idx <= (SWSRC_LAST_SWITCH - 3 * NUM_FUNCTIONS_SWITCHES)) {
+#if defined(PCBFRSKY) || defined(PCBFLYSKY)
if (flags & GETSWITCH_MIDPOS_DELAY)
result = SWITCH_POSITION(cs_idx-SWSRC_FIRST_SWITCH);
else
@@ -465,8 +559,14 @@ bool getSwitch(swsrc_t swtch, uint8_t flags)
#else
result = switchState(cs_idx-SWSRC_FIRST_SWITCH);
#endif
-
}
+#if defined(FUNCTION_SWITCHES)
+ else if (cs_idx <= SWSRC_LAST_SWITCH) {
+ div_t qr = div(cs_idx - 3 * NUM_FUNCTIONS_SWITCHES, 3);
+ auto value = getFSLogicalState(qr.quot + 1);
+ result = qr.rem == -2 ? 1 - value : value;
+ }
+#endif
#if NUM_XPOTS > 0
else if (cs_idx <= SWSRC_LAST_MULTIPOS_SWITCH) {
result = POT_POSITION(cs_idx-SWSRC_FIRST_MULTIPOS_SWITCH);
@@ -526,13 +626,14 @@ void evalLogicalSwitches(bool isCurrentFlightmode)
}
swarnstate_t switches_states = 0;
+uint8_t fsswitches_states = 0;
swsrc_t getMovedSwitch()
{
static tmr10ms_t s_move_last_time = 0;
swsrc_t result = 0;
// Switches
- for (int i = 0; i < NUM_SWITCHES; i++) {
+ for (int i = 0; i < NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES; i++) {
if (SWITCH_EXISTS(i)) {
swarnstate_t mask = ((swarnstate_t) 0x07 << (i * 3));
uint8_t prev = (switches_states & mask) >> (i * 3);
@@ -544,6 +645,20 @@ swsrc_t getMovedSwitch()
}
}
}
+
+#if defined(FUNCTION_SWITCHES)
+ for (int i = 0; i < NUM_FUNCTIONS_SWITCHES; i++) {
+ if (FSWITCH_CONFIG(i) != SWITCH_NONE) {
+ auto prev = (uint8_t )(bfSingleBitGet(fsswitches_states, i) >> (i));
+ uint8_t next = getFSLogicalState(i);
+ if (prev != next) {
+ switches_states ^= (-next ^ switches_states) & (1 << i);
+ result = 2 + (3 * (i + NUM_REGULAR_SWITCHES)) + next;
+ }
+ }
+ }
+#endif
+
// Multipos
for (int i = 0; i < NUM_XPOTS; i++) {
if (IS_POT_MULTIPOS(POT1 + i)) {
diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h
index f9e1873f3..7450b124a 100644
--- a/radio/src/targets/horus/board.h
+++ b/radio/src/targets/horus/board.h
@@ -304,6 +304,10 @@ enum EnumSwitchesPositions
#define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3)
+#if !defined(NUM_FUNCTIONS_SWITCHES)
+#define NUM_FUNCTIONS_SWITCHES 0
+#endif
+
void keysInit();
uint32_t switchState(uint8_t index);
uint32_t readKeys();
diff --git a/radio/src/targets/nv14/board.h b/radio/src/targets/nv14/board.h
index c70100315..0677593b3 100644
--- a/radio/src/targets/nv14/board.h
+++ b/radio/src/targets/nv14/board.h
@@ -235,6 +235,10 @@ enum EnumSwitchesPositions
#define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3)
+#if !defined(NUM_FUNCTIONS_SWITCHES)
+#define NUM_FUNCTIONS_SWITCHES 0
+#endif
+
void monitorInit();
void keysInit();
uint8_t keyState(uint8_t index);
diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h
index e12be5f6d..7ac83b00b 100644
--- a/radio/src/targets/sky9x/board.h
+++ b/radio/src/targets/sky9x/board.h
@@ -57,6 +57,10 @@ void rotaryEncoderEnd();
#define STORAGE_NUM_SWITCHES NUM_SWITCHES
#define NUM_SWITCHES_POSITIONS 9
+#if !defined(NUM_FUNCTIONS_SWITCHES)
+#define NUM_FUNCTIONS_SWITCHES 0
+#endif
+
enum EnumKeys
{
KEY_MENU,
diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt
index 15ff14c05..599d77188 100644
--- a/radio/src/targets/taranis/CMakeLists.txt
+++ b/radio/src/targets/taranis/CMakeLists.txt
@@ -138,6 +138,20 @@ elseif(PCB STREQUAL X7)
add_definitions(-DRADIO_FAMILY_JUMPER_T12)
add_definitions(-DEEPROM_VARIANT=0x4001)
add_definitions(-DMANUFACTURER_JUMPER)
+ elseif(PCBREV STREQUAL TPRO)
+ set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module")
+ set(INTERNAL_MODULE_SERIAL YES)
+ set(FLAVOUR tpro)
+ set(NAVIGATION_TYPE x7)
+ set(CPU_TYPE STM32F2)
+ set(ROTARY_ENCODER YES)
+ set(CPU_TYPE_FULL STM32F205xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
+ set(LUA_EXPORT lua_export_tpro)
+ add_definitions(-DFUNCTION_SWITCHES)
+ add_definitions(-DRADIO_TPRO)
+ add_definitions(-DEEPROM_VARIANT=0x4005)
+ add_definitions(-DMANUFACTURER_JUMPER)
elseif(PCBREV STREQUAL TLITE)
set(DEFAULT_INTERNAL_MODULE MULTIMODULE CACHE STRING "Default internal module")
set(INTERNAL_MODULE_SERIAL YES)
diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h
index 01df37927..7688a76a5 100644
--- a/radio/src/targets/taranis/board.h
+++ b/radio/src/targets/taranis/board.h
@@ -38,7 +38,7 @@ void rotaryEncoderInit();
void rotaryEncoderCheck();
#endif
-#if defined(RADIO_ZORRO)
+#if defined(RADIO_ZORRO) || defined(RADIO_TPRO)
#define ROTARY_ENCODER_INVERT
#endif
@@ -330,7 +330,16 @@ enum EnumSwitches
SW_SE,
SW_SF,
SW_SG,
- SW_SH
+ SW_SH,
+ SW_SI,
+ SW_SJ,
+ SW_SK,
+ SW_SL,
+ SW_SM,
+ SW_SO,
+ SW_SP,
+ SW_SQ,
+ SW_SR,
};
#if defined(RADIO_TX12)
#define IS_3POS(x) ((x) != SW_SA && (x) != SW_SD)
@@ -353,22 +362,22 @@ enum EnumSwitchesPositions
SW_SD0,
SW_SD1,
SW_SD2,
-#if defined(PCBX9) || defined(PCBXLITES) || defined(PCBX9LITES) || defined(RADIO_TX12) || defined(RADIO_ZORRO)
+#if defined(HARDWARE_SWITCH_E)
SW_SE0,
SW_SE1,
SW_SE2,
#endif
-#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || (defined(PCBX7) && !defined(RADIO_T12)) || defined(PCBXLITES) || defined(PCBX9LITES) || defined(RADIO_T8) || defined(RADIO_ZORRO)
+#if defined(HARDWARE_SWITCH_F)
SW_SF0,
SW_SF1,
SW_SF2,
#endif
-#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || defined(PCBX9LITES) || defined(RADIO_T12) || defined(RADIO_ZORRO)
+#if defined(HARDWARE_SWITCH_G)
SW_SG0,
SW_SG1,
SW_SG2,
#endif
-#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) || (defined(PCBX7) && !defined(RADIO_TX12)) || defined(RADIO_T8) || defined(RADIO_ZORRO)
+#if defined(HARDWARE_SWITCH_H)
SW_SH0,
SW_SH1,
SW_SH2,
@@ -440,6 +449,16 @@ enum EnumSwitchesPositions
#define STORAGE_NUM_SWITCHES 8
#define DEFAULT_SWITCH_CONFIG (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0);
#define DEFAULT_POTS_CONFIG (0)
+#elif defined(RADIO_TPRO)
+ #define NUM_SWITCHES 10
+ #define NUM_FUNCTIONS_SWITCHES 6
+ #define NUM_REGULAR_SWITCHES (NUM_SWITCHES - NUM_FUNCTIONS_SWITCHES)
+ #define STORAGE_NUM_SWITCHES 10
+ #define DEFAULT_SWITCH_CONFIG (SWITCH_TOGGLE << 6) + (SWITCH_TOGGLE << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0);
+ #define DEFAULT_FS_CONFIG (SWITCH_2POS << 10) + (SWITCH_2POS << 8) + (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_2POS << 2) + (SWITCH_2POS << 0)
+ #define DEFAULT_FS_GROUPS (1 << 10) + (1 << 8) + (1 << 6) + (1 << 4) + (1 << 2) + (1 << 0) // Set all FS to group 1 to act like a 6pos
+ #define DEFAULT_FS_STARTUP_CONFIG ((FS_START_PREVIOUS << 10) + (FS_START_PREVIOUS << 8) + (FS_START_PREVIOUS << 6) + (FS_START_PREVIOUS << 4) + (FS_START_PREVIOUS << 2) + (FS_START_PREVIOUS << 0)) // keep last state by default
+ #define DEFAULT_POTS_CONFIG (POT_WITHOUT_DETENT << 0) + (POT_WITH_DETENT << 2); // S1 = pot without detent, S2 = pot with detent
#elif defined(RADIO_FAMILY_JUMPER_T12)
#define NUM_SWITCHES 8
#define STORAGE_NUM_SWITCHES NUM_SWITCHES
@@ -500,17 +519,24 @@ enum EnumSwitchesPositions
#define DEFAULT_SLIDERS_CONFIG (SLIDER_WITH_DETENT << 1) + (SLIDER_WITH_DETENT << 0)
#endif
+#if !defined(NUM_FUNCTIONS_SWITCHES)
+ #define NUM_FUNCTIONS_SWITCHES 0
+#endif
+
#define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3)
void keysInit();
uint32_t switchState(uint8_t index);
-#if defined(RADIO_ZORRO)
-static const uint8_t switchReOrder[] = {1, 0, 4, 2, 3, 5};
-#else
-static const uint8_t switchReOrder[] = {0, 1, 2, 3, 4, 5};
-#endif
uint32_t readKeys();
uint32_t readTrims();
+#if defined(FUNCTION_SWITCHES)
+extern uint8_t fsPreviousState;
+void evalFunctionSwitches();
+void setFSStartupPosition();
+uint8_t getFSLogicalState(uint8_t index);
+uint8_t getFSPhysicalState(uint8_t index);
+#endif
+
#define TRIMS_PRESSED() (readTrims())
#define KEYS_PRESSED() (readKeys())
@@ -757,6 +783,10 @@ uint8_t isBacklightEnabled();
#define USB_NAME "Jumper TLite"
#define USB_MANUFACTURER 'J', 'U', 'M', 'P', 'E', 'R', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'T', '-', 'L', 'I', 'T', 'E', ' ', ' ' /* 8 Bytes */
+#elif defined(RADIO_TPRO)
+ #define USB_NAME "Jumper TPro"
+ #define USB_MANUFACTURER 'J', 'U', 'M', 'P', 'E', 'R', ' ', ' ' /* 8 bytes */
+ #define USB_PRODUCT 'T', '-', 'P', 'R', 'O', ' ', ' ', ' ' /* 8 Bytes */
#else
#define USB_NAME "FrSky Taranis"
#define USB_MANUFACTURER 'F', 'r', 'S', 'k', 'y', ' ', ' ', ' ' /* 8 bytes */
@@ -926,6 +956,10 @@ void ledOff();
void ledRed();
void ledGreen();
void ledBlue();
+#if defined(FUNCTION_SWITCHES)
+void fsLedOff(uint8_t);
+void fsLedOn(uint8_t);
+#endif
// LCD driver
#if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E)
@@ -942,7 +976,7 @@ void ledBlue();
#define IS_LCD_RESET_NEEDED() true
#define LCD_CONTRAST_MIN 10
#define LCD_CONTRAST_MAX 30
-#if defined(RADIO_TX12) || defined(RADIO_FAMILY_JUMPER_T12)
+#if defined(RADIO_TX12) || defined(RADIO_TPRO) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TPRO)
#define LCD_CONTRAST_DEFAULT 25
#else
#define LCD_CONTRAST_DEFAULT 15
diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h
index 4db84712d..ea2bec79b 100644
--- a/radio/src/targets/taranis/hal.h
+++ b/radio/src/targets/taranis/hal.h
@@ -53,7 +53,7 @@
#define KEYS_GPIO_PIN_LEFT GPIO_Pin_12 // PE.12
#define KEYS_GPIO_REG_RIGHT GPIOE->IDR
#define KEYS_GPIO_PIN_RIGHT GPIO_Pin_13 // PE.13
-#elif defined(RADIO_FAMILY_JUMPER_T12)
+#elif defined(RADIO_FAMILY_JUMPER_T12) && !defined(RADIO_TPRO)
#define KEYS_GPIO_REG_EXIT GPIOD->IDR
#define KEYS_GPIO_PIN_EXIT GPIO_Pin_2 // PD.02
#define KEYS_GPIO_REG_ENTER GPIOE->IDR
@@ -174,7 +174,7 @@
#define ROTARY_ENCODER_EXTI_PortSource EXTI_PortSourceGPIOE
#define ROTARY_ENCODER_EXTI_PinSource1 EXTI_PinSource10
#define ROTARY_ENCODER_EXTI_PinSource2 EXTI_PinSource11
-#elif defined(RADIO_X7) || defined(RADIO_X7ACCESS)
+#elif defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TPRO)
#define ROTARY_ENCODER_NAVIGATION
#define ROTARY_ENCODER_GPIO GPIOE
#define ROTARY_ENCODER_GPIO_PIN_A GPIO_Pin_9 // PE.09
@@ -368,6 +368,13 @@
#define HARDWARE_SWITCH_A
#define SWITCHES_GPIO_REG_A GPIOE->IDR
#define SWITCHES_GPIO_PIN_A GPIO_Pin_14 // PE.14
+#elif defined(RADIO_TPRO)
+ #define STORAGE_SWITCH_A
+ #define HARDWARE_SWITCH_A
+ #define SWITCHES_GPIO_REG_A_L GPIOE->IDR
+ #define SWITCHES_GPIO_PIN_A_L GPIO_Pin_13 // PE.13
+ #define SWITCHES_GPIO_REG_A_H GPIOE->IDR
+ #define SWITCHES_GPIO_PIN_A_H GPIO_Pin_7 // PE.07
#elif defined(PCBX7)
#define STORAGE_SWITCH_A
#define HARDWARE_SWITCH_A
@@ -405,7 +412,7 @@
#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)
+#elif defined(RADIO_TLITE) || defined(RADIO_TPRO)
#define STORAGE_SWITCH_B
#define HARDWARE_SWITCH_B
#define SWITCHES_GPIO_REG_B_L GPIOE->IDR
@@ -470,7 +477,7 @@
#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)
+#elif defined(RADIO_TLITE) || defined(RADIO_TPRO)
#define STORAGE_SWITCH_C
#define HARDWARE_SWITCH_C
#define SWITCHES_GPIO_REG_C GPIOE->IDR
@@ -527,7 +534,7 @@
#define HARDWARE_SWITCH_D
#define SWITCHES_GPIO_REG_D GPIOE->IDR
#define SWITCHES_GPIO_PIN_D GPIO_Pin_8 // PE.08
-#elif defined(RADIO_TLITE)
+#elif defined(RADIO_TLITE) || defined(RADIO_TPRO)
#define STORAGE_SWITCH_D
#define HARDWARE_SWITCH_D
#define SWITCHES_GPIO_REG_D GPIOD->IDR
@@ -585,6 +592,12 @@
#define SWITCHES_GPIO_PIN_E_H GPIO_Pin_13 // PE.13
#define SWITCHES_GPIO_REG_E_L GPIOE->IDR
#define SWITCHES_GPIO_PIN_E_L GPIO_Pin_7 // PE.07
+#elif defined(RADIO_TPRO)
+ // SW1
+ #define STORAGE_SWITCH_E
+ #define HARDWARE_SWITCH_E
+ #define SWITCHES_GPIO_REG_E GPIOG->IDR
+ #define SWITCHES_GPIO_PIN_E GPIO_Pin_7 // PG.07
#elif defined(PCBX7)
// no SWE
#else
@@ -628,7 +641,13 @@
#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_T8) || defined(RADIO_TLITE)
+#elif defined(RADIO_TPRO)
+ // SW2
+ #define STORAGE_SWITCH_F
+ #define HARDWARE_SWITCH_F
+ #define SWITCHES_GPIO_REG_F GPIOG->IDR
+ #define SWITCHES_GPIO_PIN_F GPIO_Pin_6 // PG.06
+#elif defined(RADIO_T8) || defined(RADIO_TLITE) || defined(RADIO_TPRO)
// no SWF
#define STORAGE_SWITCH_F
#elif defined(RADIO_T12)
@@ -662,6 +681,12 @@
#define HARDWARE_SWITCH_G
#define SWITCHES_GPIO_REG_G GPIOE->IDR
#define SWITCHES_GPIO_PIN_G GPIO_Pin_14 // PE.14
+#elif defined(RADIO_TPRO)
+ // SW3
+ #define STORAGE_SWITCH_G
+ #define HARDWARE_SWITCH_G
+ #define SWITCHES_GPIO_REG_G GPIOG->IDR
+ #define SWITCHES_GPIO_PIN_G GPIO_Pin_5 // PG.05
#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_T8)
// no SWG
#else
@@ -689,7 +714,13 @@
#define STORAGE_SWITCH_H
// no SWH
#elif defined(RADIO_TX12)
-#elif defined(RADIO_TLITE)
+#elif defined(RADIO_TPRO)
+ // SW4
+ #define STORAGE_SWITCH_H
+ #define HARDWARE_SWITCH_H
+ #define SWITCHES_GPIO_REG_H GPIOG->IDR
+ #define SWITCHES_GPIO_PIN_H GPIO_Pin_4 // PG.04
+#elif defined(RADIO_TLITE) || defined(RADIO_TPRO)
// no SWH
#define STORAGE_SWITCH_H
#elif defined(PCBX7)
@@ -740,6 +771,17 @@
#define STORAGE_SWITCH_J
#elif defined(RADIO_ZORRO)
// No I/J
+#elif defined(RADIO_TPRO)
+ // SW5
+ #define STORAGE_SWITCH_I
+ #define HARDWARE_SWITCH_I
+ #define SWITCHES_GPIO_REG_I GPIOG->IDR
+ #define SWITCHES_GPIO_PIN_I GPIO_Pin_3 // PG.03
+ // SW6
+ #define STORAGE_SWITCH_J
+ #define HARDWARE_SWITCH_J
+ #define SWITCHES_GPIO_REG_J GPIOG->IDR
+ #define SWITCHES_GPIO_PIN_J GPIO_Pin_2 // PG.02
#elif defined(PCBX7)
#define STORAGE_SWITCH_I
#define HARDWARE_SWITCH_I
@@ -849,6 +891,13 @@
#define KEYS_GPIOB_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5)
#define KEYS_GPIOC_PINS (GPIO_Pin_4 | GPIO_Pin_5)
#define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14)
+#elif defined(RADIO_TPRO)
+ #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG)
+ #define KEYS_GPIOA_PINS (GPIO_Pin_5)
+ #define KEYS_GPIOC_PINS (GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3)
+ #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_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15)
+ #define KEYS_GPIOG_PINS (GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7)
#elif defined(RADIO_FAMILY_JUMPER_T12)
#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
@@ -1067,6 +1116,30 @@
#define ADC_GPIOC_PINS ADC_GPIO_PIN_BATT
#define ADC_CHANNEL_BATT ADC_Channel_10
#define ADC_VREF_PREC2 330
+#elif defined(RADIO_TPRO)
+ #define HARDWARE_POT1
+ #define HARDWARE_POT2
+ #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_POT1 GPIO_Pin_0 // PB.00
+ #define ADC_GPIO_PIN_POT2 GPIO_Pin_6 // PA.06
+ #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 | ADC_GPIO_PIN_POT2)
+ #define ADC_GPIOB_PINS ADC_GPIO_PIN_POT1
+ #define ADC_GPIOC_PINS ADC_GPIO_PIN_BATT
+ #define ADC_CHANNEL_POT1 ADC_Channel_6
+ #define ADC_CHANNEL_POT2 ADC_Channel_8
+ #define ADC_CHANNEL_BATT ADC_Channel_10
+ #define ADC_VREF_PREC2 330
#elif defined(PCBX7)
#define HARDWARE_POT1
#define HARDWARE_POT2
@@ -1244,6 +1317,19 @@
#define LED_BLUE_GPIO_PIN GPIO_Pin_6 // PE.06
#endif
+#if defined(FUNCTION_SWITCHES)
+ #define FS_RCC_AHB1Periph RCC_AHB1Periph_GPIOF
+ #define GPIO_FSLED_GPIO_ON GPIO_SetBits
+ #define GPIO_FSLED_GPIO_OFF GPIO_ResetBits
+ #define FSLED_GPIO GPIOF
+ #define FSLED_GPIO_PIN_1 GPIO_Pin_5
+ #define FSLED_GPIO_PIN_2 GPIO_Pin_4
+ #define FSLED_GPIO_PIN_3 GPIO_Pin_3
+ #define FSLED_GPIO_PIN_4 GPIO_Pin_2
+ #define FSLED_GPIO_PIN_5 GPIO_Pin_1
+ #define FSLED_GPIO_PIN_6 GPIO_Pin_0
+#endif
+
// Internal Module
#if defined(PCBXLITE)
#define EXTERNAL_ANTENNA
@@ -1362,7 +1448,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(HARDWARE_INTERNAL_MODULE)) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8)
+#elif (defined(RADIO_FAMILY_JUMPER_T12) && defined(HARDWARE_INTERNAL_MODULE)) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TPRO)
#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
@@ -1612,7 +1698,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) || defined(RADIO_ZORRO) || defined(RADIO_T8)
+#if defined(RADIO_X7) || defined(RADIO_X7ACCESS) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TPRO)
#define TELEMETRY_EXTI_REUSE_INTERRUPT_ROTARY_ENCODER
#elif defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_X9DP2019)
#define TELEMETRY_EXTI_IRQHandler EXTI9_5_IRQHandler
@@ -1724,7 +1810,7 @@
#define INTMODULE_HEARTBEAT_EXTI_IRQHandler EXTI1_IRQHandler
#elif defined(RADIO_ZORRO)
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph 0
-#elif defined(RADIO_X7) || defined(RADIO_TX12)
+#elif defined(RADIO_X7) || defined(RADIO_TX12) || defined(RADIO_TPRO)
#define INTMODULE_HEARTBEAT
#define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER
#define INTMODULE_HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOC
@@ -1912,7 +1998,7 @@
#define KEYS_BACKLIGHT_RCC_AHB1Periph 0
// LCD driver
-#if defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_T8)
+#if defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_T8) || defined(RADIO_TPRO)
#define LCD_VERTICAL_INVERT
#endif
#if defined(PCBX9E)
@@ -2116,12 +2202,12 @@
#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_ZORRO) || defined(RADIO_T8) || defined(RADIO_TLITE)
+#elif defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TLITE) || defined(RADIO_TPRO)
#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
#define AUDIO_MUTE_DELAY 500 // ms
-#if defined(RADIO_TLITE)
+#if defined(RADIO_TLITE) || defined(RADIO_TPRO)
#define AUDIO_UNMUTE_DELAY 250 // ms
#else
#define AUDIO_UNMUTE_DELAY 150 // ms
diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp
index 3dc4260eb..1d5d3fccf 100644
--- a/radio/src/targets/taranis/keys_driver.cpp
+++ b/radio/src/targets/taranis/keys_driver.cpp
@@ -210,7 +210,7 @@ uint32_t switchState(uint8_t index)
ADD_2POS_CASE(A);
ADD_3POS_CASE(B, 1);
ADD_3POS_CASE(C, 2);
-#elif defined(RADIO_TLITE)
+#elif defined(RADIO_TLITE) || defined(RADIO_TPRO)
ADD_3POS_CASE(A, 0);
ADD_3POS_CASE(B, 1);
ADD_2POS_CASE(C);
@@ -256,6 +256,13 @@ uint32_t switchState(uint8_t index)
ADD_2POS_CASE(D);
#elif defined(RADIO_TLITE)
// Only 4 switches
+#elif defined(RADIO_TPRO)
+ ADD_2POS_CASE(E);
+ ADD_2POS_CASE(F);
+ ADD_2POS_CASE(G);
+ ADD_2POS_CASE(H);
+ ADD_2POS_CASE(I);
+ ADD_2POS_CASE(J);
#elif defined(PCBX7)
ADD_3POS_CASE(D, 3);
#if defined(RADIO_T12)
diff --git a/radio/src/targets/taranis/lcd_driver_spi.cpp b/radio/src/targets/taranis/lcd_driver_spi.cpp
index 53ac9ac25..e3f9069c8 100644
--- a/radio/src/targets/taranis/lcd_driver_spi.cpp
+++ b/radio/src/targets/taranis/lcd_driver_spi.cpp
@@ -21,7 +21,7 @@
#include "opentx.h"
-#if defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8)
+#if defined(RADIO_FAMILY_JUMPER_T12) || defined(RADIO_TX12) || defined(RADIO_ZORRO) || defined(RADIO_T8) || defined(RADIO_TPRO)
#define LCD_CONTRAST_OFFSET -10
#else
#define LCD_CONTRAST_OFFSET 160
diff --git a/radio/src/targets/taranis/led_driver.cpp b/radio/src/targets/taranis/led_driver.cpp
index 04033c655..0b6824cf0 100644
--- a/radio/src/targets/taranis/led_driver.cpp
+++ b/radio/src/targets/taranis/led_driver.cpp
@@ -43,8 +43,32 @@ void ledInit()
GPIO_InitStructure.GPIO_Pin = LED_BLUE_GPIO_PIN;
GPIO_Init(LED_BLUE_GPIO, &GPIO_InitStructure);
#endif
+
+#if defined(FUNCTION_SWITCHES)
+ RCC_AHB1PeriphClockCmd(FS_RCC_AHB1Periph, ENABLE);
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Pin = FSLED_GPIO_PIN_1 | FSLED_GPIO_PIN_2 | FSLED_GPIO_PIN_3 | FSLED_GPIO_PIN_4 | FSLED_GPIO_PIN_5 | FSLED_GPIO_PIN_6;
+ GPIO_Init(FSLED_GPIO, &GPIO_InitStructure);
+#endif
}
+#if defined(FUNCTION_SWITCHES)
+constexpr uint32_t fsLeds[] = {FSLED_GPIO_PIN_1, FSLED_GPIO_PIN_2, FSLED_GPIO_PIN_3, FSLED_GPIO_PIN_4, FSLED_GPIO_PIN_5, FSLED_GPIO_PIN_6};
+
+void fsLedOff(uint8_t index)
+{
+ GPIO_FSLED_GPIO_OFF(FSLED_GPIO, fsLeds[index]);
+}
+
+void fsLedOn(uint8_t index)
+{
+ GPIO_FSLED_GPIO_ON(FSLED_GPIO, fsLeds[index]);
+}
+#endif
+
void ledOff()
{
#if defined(LED_RED_GPIO)
diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp
index 418d4b639..d54529847 100644
--- a/radio/src/translations.cpp
+++ b/radio/src/translations.cpp
@@ -94,6 +94,7 @@ ISTR(CRSF_BAUDRATE);
ISTR(PPM_POL);
ISTR(SBUS_INVERSION_VALUES);
ISTR(SPORT_MODES);
+ISTR(FSGROUPS);
#if defined(PCBSKY9X) && defined(REVX)
ISTR(VOUTPUT_TYPE);
diff --git a/radio/src/translations.h b/radio/src/translations.h
index f1c16e9a2..e37110dbb 100644
--- a/radio/src/translations.h
+++ b/radio/src/translations.h
@@ -178,6 +178,7 @@ extern const char STR_MULTI_POWER[];
extern const char STR_MULTI_TELEMETRY_MODE[];
extern const char STR_MULTI_WBUS_MODE[];
extern const char STR_SPORT_MODES[];
+extern const char STR_FSGROUPS[];
extern const char STR_AFHDS3_ONE_TO_ONE_TELEMETRY[];
extern const char STR_AFHDS3_ONE_TO_MANY[];
diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h
index fca9c7ecd..2d3936df5 100644
--- a/radio/src/translations/untranslated.h
+++ b/radio/src/translations/untranslated.h
@@ -40,9 +40,20 @@
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW STR_CHAR_POT"S1\0" STR_CHAR_POT"S2\0"
#define TR_SW_VSRCRAW STR_CHAR_SWITCH"SA\0" STR_CHAR_SWITCH"SB\0" STR_CHAR_SWITCH"SC\0" STR_CHAR_SWITCH"SD\0" STR_CHAR_SWITCH"SE\0" STR_CHAR_SWITCH"SF\0"
-#elif defined(RADIO_FAMILY_JUMPER_T12)
+#elif defined(RADIO_TPRO)
#define TR_POTS_VSRCRAW STR_CHAR_POT"S1\0" STR_CHAR_POT"S2\0"
- #define TR_SW_VSRCRAW STR_CHAR_SWITCH"SA\0" STR_CHAR_SWITCH"SB\0" STR_CHAR_SWITCH"SC\0" STR_CHAR_SWITCH"SD\0" STR_CHAR_SWITCH"SG\0" STR_CHAR_SWITCH"SH\0" STR_CHAR_SWITCH"SI\0" STR_CHAR_SWITCH"SJ\0"
+#define TR_SW_VSRCRAW \
+ STR_CHAR_SWITCH \
+ "SA\0" STR_CHAR_SWITCH "SB\0" STR_CHAR_SWITCH "SC\0" STR_CHAR_SWITCH \
+ "SD\0" STR_CHAR_SWITCH "SW1" STR_CHAR_SWITCH "SW2" STR_CHAR_SWITCH \
+ "SW3" STR_CHAR_SWITCH "SW4" STR_CHAR_SWITCH "SW5" STR_CHAR_SWITCH "SW6"
+#elif defined(RADIO_FAMILY_JUMPER_T12)
+#define TR_POTS_VSRCRAW STR_CHAR_POT "S1\0" STR_CHAR_POT "S2\0"
+#define TR_SW_VSRCRAW \
+ STR_CHAR_SWITCH "SA\0" STR_CHAR_SWITCH "SB\0" STR_CHAR_SWITCH \
+ "SC\0" STR_CHAR_SWITCH "SD\0" STR_CHAR_SWITCH \
+ "SG\0" STR_CHAR_SWITCH "SH\0" STR_CHAR_SWITCH \
+ "SI\0" STR_CHAR_SWITCH "SJ\0"
#elif defined(RADIO_TX12)
#define TR_POTS_VSRCRAW STR_CHAR_POT "S1\0" STR_CHAR_POT "S2\0"
#define TR_SW_VSRCRAW STR_CHAR_SWITCH "SA\0" STR_CHAR_SWITCH "SB\0" STR_CHAR_SWITCH "SC\0" STR_CHAR_SWITCH "SD\0" STR_CHAR_SWITCH "SE\0" STR_CHAR_SWITCH "SF\0" STR_CHAR_SWITCH "SI\0" STR_CHAR_SWITCH "SJ\0"
@@ -372,3 +383,7 @@
#define TR_EDIT_THEME "EDIT THEME"
#define TR_DETAILS "Details"
#define TR_THEME_EDITOR "THEMES"
+
+#define LEN_FSGROUPS "\001"
+#define TR_FSGROUPS "-""1""2""3"
+
diff --git a/tools/build-companion-nightly-win32.sh b/tools/build-companion-nightly-win32.sh
index 0ca9d2edf..8d21395d7 100644
--- a/tools/build-companion-nightly-win32.sh
+++ b/tools/build-companion-nightly-win32.sh
@@ -81,6 +81,10 @@ cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TLITE ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
+cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TPRO ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
cmake ${COMMON_OPTIONS} -DPCB=X9D ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
diff --git a/tools/build-companion-nightly.sh b/tools/build-companion-nightly.sh
index eef3aef73..c342da9f4 100755
--- a/tools/build-companion-nightly.sh
+++ b/tools/build-companion-nightly.sh
@@ -81,6 +81,10 @@ cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TLITE ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
+cmake ${COMMON_OPTIONS} -DPCB=X7 -DPCBREV=TPRO ${SRCDIR}
+make -j${JOBS} libsimulator
+rm CMakeCache.txt
+
cmake ${COMMON_OPTIONS} -DPCB=X9D ${SRCDIR}
make -j${JOBS} libsimulator
rm CMakeCache.txt
diff --git a/tools/build-gh.sh b/tools/build-gh.sh
index 89dc53ea8..097357516 100755
--- a/tools/build-gh.sh
+++ b/tools/build-gh.sh
@@ -99,6 +99,9 @@ do
tlite)
BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=TLITE"
;;
+ tpro)
+ BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=TPRO"
+ ;;
xlite)
BUILD_OPTIONS+="-DPCB=XLITE"
;;
diff --git a/tools/build-jumper.py b/tools/build-jumper.py
index cfce0920c..8e7d9e171 100755
--- a/tools/build-jumper.py
+++ b/tools/build-jumper.py
@@ -14,6 +14,11 @@ boards = {
"PCBREV": "TLITE",
"DEFAULT_MODE": "2",
},
+ "TPRO": {
+ "PCB": "X7",
+ "PCBREV": "TPRO",
+ "DEFAULT_MODE": "2",
+ },
"T12": {
"PCB": "X7",
"PCBREV": "T12",
diff --git a/tools/generate-yaml.sh b/tools/generate-yaml.sh
index dbaea4f2e..c4f7e150b 100755
--- a/tools/generate-yaml.sh
+++ b/tools/generate-yaml.sh
@@ -9,7 +9,7 @@ if [[ -n ${GCC_ARM} ]] ; then
export PATH=${GCC_ARM}:$PATH
fi
-: ${FLAVOR:="t12;t8;tlite;tx12;zorro;tx16s;x12s;nv14;x7;x9d;x9dp;x9e;x9lite;x9lites;xlite;xlites"}
+: ${FLAVOR:="t12;t8;tlite;tpro;tx12;zorro;tx16s;x12s;nv14;x7;x9d;x9dp;x9e;x9lite;x9lites;xlite;xlites"}
: ${SRCDIR:=$(dirname $(pwd)/"$0")/..}
: ${COMMON_OPTIONS:="-DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_RULE_MESSAGES=OFF -DDISABLE_COMPANION=YES -Wno-dev -DYAML_STORAGE=YES "}
@@ -53,6 +53,9 @@ do
tlite)
BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=TLITE"
;;
+ tpro)
+ BUILD_OPTIONS+="-DPCB=X7 -DPCBREV=TPRO"
+ ;;
xlite)
BUILD_OPTIONS+="-DPCB=XLITE"
;;