Skip to content

Commit

Permalink
refactor(cpn): Support JSON radio hardware definitions (EdgeTX#4406)
Browse files Browse the repository at this point in the history
  • Loading branch information
Neil Horne authored Feb 4, 2024
1 parent c6ae44f commit 8329461
Show file tree
Hide file tree
Showing 63 changed files with 4,161 additions and 2,290 deletions.
17 changes: 17 additions & 0 deletions companion/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,22 @@ else()
message(STATUS "Qt lupdate not found, 'translations' target will not be availabe.")
endif()

############# Import radio hardware definitions ###############

set(HWDEFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/../../radio/src")
set(HWDEFS_TMPL "${COMPANION_SRC_DIRECTORY}/hwdefs.qrc.in")
set(HWDEFS_PHDR "HWDEF_JSON_LIST")
set(HWDEFS_QRC "${CMAKE_CURRENT_BINARY_DIR}/hwdefs.qrc")
set(HWDEFS_CMD "${COMPANION_SRC_DIRECTORY}/../util/generate_hwdefs_qrc.py")

add_custom_command(OUTPUT ${HWDEFS_QRC}
COMMAND ${HWDEFS_CMD} -d ${HWDEFS_DIR}
-t ${HWDEFS_TMPL}
-p ${HWDEFS_PHDR}
-o ${HWDEFS_QRC}
DEPENDS ${HWDEFS_TMPL}
)

############# Common lib ###############

set(common_SRCS
Expand All @@ -157,6 +173,7 @@ set(common_MOC_HDRS
set(common_RESOURCES
companion.qrc
${TRANSLATIONS_QRC}
${HWDEFS_QRC}
)

qt5_wrap_cpp(common_SRCS ${common_MOC_HDRS})
Expand Down
4 changes: 4 additions & 0 deletions companion/src/companion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "storage.h"
#include "translations.h"
#include "helpers.h"
#include "boardfactories.h"

#ifdef __APPLE__
#include <QProxyStyle>
Expand Down Expand Up @@ -231,6 +232,8 @@ int main(int argc, char *argv[])
}
#endif

Q_INIT_RESOURCE(hwdefs);
gBoardFactories = new BoardFactories();
registerStorageFactories();
registerOpenTxFirmwares();
SimulatorLoader::registerSimulators();
Expand Down Expand Up @@ -264,6 +267,7 @@ int main(int argc, char *argv[])
SimulatorLoader::unregisterSimulators();
unregisterOpenTxFirmwares();
unregisterStorageFactories();
gBoardFactories->unregisterBoardFactories();

#if defined(JOYSTICKS) || defined(SIMU_AUDIO)
SDL_Quit();
Expand Down
20 changes: 13 additions & 7 deletions companion/src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,24 @@
#define CPN_MAX_MODULES 2
#define CPN_MAX_STICKS Board::STICK_AXIS_COUNT
#define CPN_MAX_TRIMS Board::TRIM_AXIS_COUNT
#define CPN_MAX_POTS 8
#define CPN_MAX_SLIDERS 4
#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_SLIDERS + CPN_MAX_MOUSE_ANALOGS + CPN_MAX_GYRO_ANALOGS)
#define CPN_MAX_SWITCHES_FLEX 4 // v2.10 cmake parameter FLEXSW
#define CPN_MAX_SWITCHES_FUNCTION 6
#define CPN_MAX_SWITCHES_STD 20
#define CPN_MAX_SWITCHES (CPN_MAX_SWITCHES_STD + CPN_MAX_SWITCHES_FLEX + CPN_MAX_SWITCHES_FUNCTION)
#define CPN_MAX_SENSORS 60
#define CPN_MAX_SCRIPTS 9
#define CPN_MAX_SCRIPT_INPUTS 10
#define CPN_MAX_SPACEMOUSE 6
#define CPN_MAX_INPUTS 32 // v2.10 replaces CPN_MAX_ANALOGS - the value is abitary as radio ADC refactor is still a WIP

// pre v2.10
#define CPN_MAX_POTS 8
#define CPN_MAX_SLIDERS 4
#define CPN_MAX_MOUSE_ANALOGS 2
#define CPN_MAX_GYRO_ANALOGS 2
#define CPN_MAX_ANALOGS (CPN_MAX_STICKS + CPN_MAX_POTS + CPN_MAX_SLIDERS + CPN_MAX_MOUSE_ANALOGS + CPN_MAX_GYRO_ANALOGS)
// =========

#define CPN_STR_APP_NAME QCoreApplication::translate("Companion", "EdgeTX Companion")
#define CPN_STR_SIMU_NAME QCoreApplication::translate("Companion", "EdgeTX Simulator")
Expand Down
65 changes: 59 additions & 6 deletions companion/src/datamodels/compounditemmodels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ QString AbstractItemModel::idToString(const int value)
return "CurveRefType";
case IMID_CurveRefFunc:
return "CurveRefFunc";
case IMID_FlexSwitches:
return "FlexSwitches";
default:
return "Custom";
}
Expand Down Expand Up @@ -108,13 +110,12 @@ RawSourceItemModel::RawSourceItemModel(const GeneralSettings * const generalSett
for (int i = 0; i < firmware->getCapability(LuaScripts); i++)
addItems(SOURCE_TYPE_LUA_OUTPUT, RawSource::ScriptsGroup, firmware->getCapability(LuaOutputsPerScript), i * 16);
addItems(SOURCE_TYPE_VIRTUAL_INPUT, RawSource::InputsGroup, firmware->getCapability(VirtualInputs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::MaxAnalogs));
addItems(SOURCE_TYPE_STICK, RawSource::SourcesGroup, board->getCapability(Board::Inputs));
addItems(SOURCE_TYPE_TRIM, RawSource::TrimsGroup, board->getCapability(Board::NumTrims));
addItems(SOURCE_TYPE_SPACEMOUSE, RawSource::SourcesGroup, CPN_MAX_SPACEMOUSE);
addItems(SOURCE_TYPE_MIN, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_MAX, RawSource::SourcesGroup, 1);
addItems(SOURCE_TYPE_SWITCH, RawSource::SwitchesGroup, board->getCapability(Board::Switches));
addItems(SOURCE_TYPE_FUNCTIONSWITCH, RawSource::SwitchesGroup, board->getCapability(Board::FunctionSwitches));
addItems(SOURCE_TYPE_CUSTOM_SWITCH, RawSource::SwitchesGroup, firmware->getCapability(LogicalSwitches));
addItems(SOURCE_TYPE_CYC, RawSource::SourcesGroup, CPN_MAX_CYC);
addItems(SOURCE_TYPE_PPM, RawSource::SourcesGroup, firmware->getCapability(TrainerInputs));
Expand Down Expand Up @@ -175,13 +176,11 @@ RawSwitchItemModel::RawSwitchItemModel(const GeneralSettings * const generalSett
addItems(SWITCH_TYPE_VIRTUAL, -firmware->getCapability(LogicalSwitches));
addItems(SWITCH_TYPE_TRIM, -board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_MULTIPOS_POT, -(board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions)));
addItems(SWITCH_TYPE_FUNCTIONSWITCH, -board->getCapability(Board::NumFunctionSwitchesPositions));
addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_SWITCH, -board->getCapability(Board::SwitchesPositions));

// Ascending switch direction (including zero)
addItems(SWITCH_TYPE_NONE, 1);
addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchPositions));
addItems(SWITCH_TYPE_FUNCTIONSWITCH, board->getCapability(Board::NumFunctionSwitchesPositions));
addItems(SWITCH_TYPE_SWITCH, board->getCapability(Board::SwitchesPositions));
addItems(SWITCH_TYPE_MULTIPOS_POT, board->getCapability(Board::MultiposPots) * board->getCapability(Board::MultiposPotsPositions));
addItems(SWITCH_TYPE_TRIM, board->getCapability(Board::NumTrimSwitches));
addItems(SWITCH_TYPE_VIRTUAL, firmware->getCapability(LogicalSwitches));
Expand Down Expand Up @@ -571,6 +570,57 @@ PrecisionItemModel::PrecisionItemModel(const int minDecimals, const int maxDecim
}
}

//
// FlexSwitchesItemModel
//

FlexSwitchesItemModel::FlexSwitchesItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType) :
AbstractDynamicItemModel(generalSettings, modelData, firmware, board, boardType)
{
setId(IMID_FlexSwitches);

if (!generalSettings)
return;

setUpdateMask(IMUE_FunctionSwitches);
const int count = Boards::getCapability(boardType, Board::Inputs);

{
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(-1, IMDR_Id);
modelItem->setText(tr("None"));
modelItem->setData(true, IMDR_Available);
appendRow(modelItem);
}

for (int i = 0; i < count; ++i) {
QStandardItem * modelItem = new QStandardItem();
modelItem->setData(i, IMDR_Id);
setDynamicItemData(modelItem, i);
appendRow(modelItem);
}
}

void FlexSwitchesItemModel::setDynamicItemData(QStandardItem * item, const int value) const
{
item->setText(Boards::getInputName(value, boardType));
item->setData(generalSettings->isInputFlexSwitchAvailable(value), IMDR_Available);
}

void FlexSwitchesItemModel::update(const int event)
{
if (doUpdate(event)) {
emit aboutToBeUpdated();

for (int i = 1; i < rowCount(); ++i) { // skip None
setDynamicItemData(item(i), item(i)->data(IMDR_Id).toInt());
}

emit updateComplete();
}
}

//
// CompoundItemModelFactory
//
Expand Down Expand Up @@ -623,6 +673,9 @@ void CompoundItemModelFactory::addItemModel(const int id)
case AbstractItemModel::IMID_CurveRefFunc:
registerItemModel(new CurveRefFuncItemModel(generalSettings, modelData, firmware, board, boardType));
break;
case AbstractItemModel::IMID_FlexSwitches:
registerItemModel(new FlexSwitchesItemModel(generalSettings, modelData, firmware, board, boardType));
break;
default:
qDebug() << "Error: unknown item model: id";
break;
Expand Down
17 changes: 17 additions & 0 deletions companion/src/datamodels/compounditemmodels.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class AbstractItemModel: public QStandardItemModel
IMID_TeleSource,
IMID_CurveRefType,
IMID_CurveRefFunc,
IMID_FlexSwitches,
IMID_ReservedCount,
IMID_Custom
};
Expand Down Expand Up @@ -332,6 +333,22 @@ class PrecisionItemModel : public AbstractStaticItemModel
virtual ~PrecisionItemModel() {};
};

class FlexSwitchesItemModel: public AbstractDynamicItemModel
{
Q_OBJECT
public:
explicit FlexSwitchesItemModel(const GeneralSettings * const generalSettings, const ModelData * const modelData,
Firmware * firmware, const Boards * const board, const Board::Type boardType);
virtual ~FlexSwitchesItemModel() {};

public slots:
virtual void update(const int event = IMUE_SystemRefresh) override;

protected:
virtual void setDynamicItemData(QStandardItem * item, const int value) const;
};


//
// CompoundItemModelFactory
//
Expand Down
2 changes: 2 additions & 0 deletions companion/src/firmwares/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ project(firmwares)

set(${PROJECT_NAME}_NAMES
adjustmentreference
boardfactories
boardjson
boards
curvedata
curvereference
Expand Down
95 changes: 95 additions & 0 deletions companion/src/firmwares/boardfactories.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#include "boardfactories.h"

BoardFactories* gBoardFactories = nullptr;

BoardFactories::BoardFactories() :
m_default(nullptr)
{
if (registerBoard(Board::BOARD_UNKNOWN, ""))
m_default = instance(Board::BOARD_UNKNOWN);
}

BoardFactories::~BoardFactories()
{
unregisterBoardFactories();
}

BoardJson* BoardFactories::instance(Board::Type board) const
{
for (auto *registeredFactory : registeredBoardFactories) {
if (registeredFactory->instance()->board() == board)
return registeredFactory->instance();
}

return m_default;
}

// Registering firmware triggers registering the associated board
bool BoardFactories::registerBoard(Board::Type board, QString hwdefn)
{
if (board < Board::BOARD_UNKNOWN || board >= Board::BOARD_TYPE_COUNT)
return false;

if (m_default || board != Board::BOARD_UNKNOWN) {
BoardJson* regboard = instance(board);

if (regboard->board() == board) {
if (regboard->hwdefn() == hwdefn) {
//qDebug() << "Warning - Board" << Boards::getBoardName(regboard->board()) << "already registered";
return true;
}
else {
qDebug() << "Error - Board" << Boards::getBoardName(regboard->board()) << "already registered with"
<< regboard->hwdefn() << "hwdefn!";
return false;
}
}
}

BoardFactory *bf = new BoardFactory(board, hwdefn);
if (bf->instance()->loadDefinition()) {
if (registerBoardFactory(bf)) {
qDebug() << "Registered board:" << (board != Board::BOARD_UNKNOWN ? Boards::getBoardName(board) : "UNKNOWN (default)");
return true;
}
else
delete bf;
}
else
delete bf;

return false;
}

bool BoardFactories::registerBoardFactory(BoardFactory * factory)
{
registeredBoardFactories.append(factory);
return true;
}

void BoardFactories::unregisterBoardFactories()
{
for (auto *registeredFactory : registeredBoardFactories)
delete registeredFactory;
}
59 changes: 59 additions & 0 deletions companion/src/firmwares/boardfactories.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#pragma once

#include "boardjson.h"

class BoardFactory
{
public:
explicit BoardFactory(Board::Type board, QString hwdefn) :
m_instance(new BoardJson(board, hwdefn))
{}

virtual ~BoardFactory() {}

BoardJson* instance() const { return m_instance; }

private:
BoardJson *m_instance;
};

class BoardFactories
{
public:
explicit BoardFactories();
virtual ~BoardFactories();

BoardJson* instance(Board::Type board) const;

bool registerBoard(Board::Type board, QString hwdefn);
bool registerBoardFactory(BoardFactory * factory);
void unregisterBoardFactories();

private:
QList<BoardFactory *> registeredBoardFactories;

BoardJson *m_default;
};

extern BoardFactories* gBoardFactories;
Loading

0 comments on commit 8329461

Please sign in to comment.