Implement Multimodule TX options for Companion
This commit is contained in:
@@ -1830,3 +1830,32 @@ SimulatorInterface *GetCurrentFirmwareSimulator()
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int getNumSubtypes(MultiModuleRFProtocols type) {
|
||||
switch (type) {
|
||||
case MM_RF_PROTO_HISKY:
|
||||
case MM_RF_PROTO_DSM2:
|
||||
case MM_RF_PROTO_SYMAX:
|
||||
case MM_RF_PROTO_KN:
|
||||
return 2;
|
||||
|
||||
case MM_RF_PROTO_FRSKY:
|
||||
case MM_RF_PROTO_CG023:
|
||||
case MM_RF_PROTO_MT99XX:
|
||||
return 3;
|
||||
|
||||
case MM_RF_PROTO_FLYSKY:
|
||||
case MM_RF_PROTO_MJXQ:
|
||||
return 4;
|
||||
|
||||
case MM_RF_PROTO_YD717:
|
||||
return 5;
|
||||
|
||||
case MM_RF_PROTO_CX10:
|
||||
case MM_RF_PROTO_CUSTOM:
|
||||
return 8;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -849,9 +849,38 @@ enum PulsesProtocol {
|
||||
PULSES_PXX_XJT_LR12,
|
||||
PULSES_PXX_DJT,
|
||||
PULSES_CROSSFIRE,
|
||||
PULSES_MULTIMODULE,
|
||||
PULSES_PROTOCOL_LAST
|
||||
};
|
||||
|
||||
enum MultiModuleRFProtocols {
|
||||
MM_RF_PROTO_FLYSKY=0,
|
||||
MM_RF_PROTO_FIRST=MM_RF_PROTO_FLYSKY,
|
||||
MM_RF_PROTO_HUBSAN,
|
||||
MM_RF_PROTO_FRSKY,
|
||||
MM_RF_PROTO_HISKY,
|
||||
MM_RF_PROTO_V2X2,
|
||||
MM_RF_PROTO_DSM2,
|
||||
MM_RF_PROTO_DEVO,
|
||||
MM_RF_PROTO_YD717,
|
||||
MM_RF_PROTO_KN,
|
||||
MM_RF_PROTO_SYMAX,
|
||||
MM_RF_PROTO_SLT,
|
||||
MM_RF_PROTO_CX10,
|
||||
MM_RF_PROTO_CG023,
|
||||
MM_RF_PROTO_BAYANG,
|
||||
MM_RF_PROTO_ESky,
|
||||
MM_RF_PROTO_MT99XX,
|
||||
MM_RF_PROTO_MJXQ,
|
||||
MM_RF_PROTO_SHENQI,
|
||||
MM_RF_PROTO_FY326,
|
||||
MM_RF_PROTO_SFHSS,
|
||||
MM_RF_PROTO_CUSTOM,
|
||||
MM_RF_PROTO_LAST= MM_RF_PROTO_CUSTOM
|
||||
};
|
||||
|
||||
unsigned int getNumSubtypes(MultiModuleRFProtocols type);
|
||||
|
||||
enum TrainerProtocol {
|
||||
TRAINER_MASTER_JACK,
|
||||
TRAINER_SLAVE_JACK,
|
||||
@@ -865,19 +894,39 @@ class ModuleData {
|
||||
ModuleData() { clear(); }
|
||||
unsigned int modelId;
|
||||
int protocol;
|
||||
int subprotocol;
|
||||
unsigned int subType;
|
||||
bool invertedSerial;
|
||||
unsigned int channelsStart;
|
||||
int channelsCount; // 0=8 channels
|
||||
unsigned int failsafeMode;
|
||||
int failsafeChannels[C9X_NUM_CHNOUT];
|
||||
struct {
|
||||
int delay;
|
||||
bool pulsePol; // false = positive
|
||||
bool outputType; // false = open drain, true = push pull
|
||||
int frameLength;
|
||||
} ppm;
|
||||
|
||||
// By pure coincidence the struct are unions with the same datatype in Companion
|
||||
// and the firmware itself. If this changes the multi struct needs it own logic in the eeprom interface
|
||||
union {
|
||||
struct {
|
||||
int delay;
|
||||
bool pulsePol; // false = positive
|
||||
bool outputType; // false = open drain, true = push pull
|
||||
int frameLength;
|
||||
} ppm;
|
||||
struct {
|
||||
int rfProtocol;
|
||||
bool autoBindMode;
|
||||
bool lowPowerMode;
|
||||
int optionValue;
|
||||
} multi;
|
||||
};
|
||||
|
||||
// Currently the Eeprom read/write code does not work with unions
|
||||
// define a hack for the multi rf Protocol to get the real numbers here
|
||||
// (reverse the int => ms logic of the ppm delay)
|
||||
int getMultiRfProtocol () { return (multi.rfProtocol - 300) / 50; }
|
||||
void setMultiRfProtocol (int val) { multi.rfProtocol = 300 + 50 * val; }
|
||||
|
||||
void clear() { memset(this, 0, sizeof(ModuleData)); }
|
||||
QString polarityToString() const { return ppm.pulsePol ? QObject::tr("Positive") : QObject::tr("Negative"); } // TODO ModelPrinter
|
||||
|
||||
};
|
||||
|
||||
#define C9X_MAX_SCRIPTS 7
|
||||
@@ -1632,9 +1681,9 @@ class Firmware {
|
||||
}
|
||||
|
||||
virtual int getCapability(const Capability) = 0;
|
||||
|
||||
|
||||
virtual QTime getMaxTimerStart() = 0;
|
||||
|
||||
|
||||
virtual bool isTelemetrySourceAvailable(int source) = 0;
|
||||
|
||||
virtual int isAvailable(PulsesProtocol proto, int port=0) = 0;
|
||||
|
||||
@@ -83,6 +83,7 @@ class ProtocolsConversionTable: public ConversionTable
|
||||
}
|
||||
if (IS_TARANIS(board)) {
|
||||
addConversion(PULSES_CROSSFIRE, val++);
|
||||
addConversion(PULSES_MULTIMODULE, val++);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -865,6 +865,8 @@ int OpenTxFirmware::isAvailable(PulsesProtocol proto, int port)
|
||||
case PULSES_DSMX:
|
||||
case PULSES_CROSSFIRE:
|
||||
return 1;
|
||||
case PULSES_MULTIMODULE:
|
||||
return id.contains("multimodule") ? 1 : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1148,6 +1150,7 @@ void addOpenTxTaranisOptions(OpenTxFirmware * firmware)
|
||||
firmware->addOption("mixersmon", QObject::tr("Adds mixers output view to the CHANNELS MONITOR screen, pressing [ENT] switches between the views"));
|
||||
firmware->addOption("eu", QObject::tr("Removes D8 and LR12 FrSky protocols that are not legal for use in the EU on radios sold after Jan 1st, 2015"));
|
||||
firmware->addOption("internalppm", QObject::tr("Support for PPM internal module hack"));
|
||||
firmware->addOption("multimodule", QObject::tr("Support for the DIY-Multiprotocol-TX-Module"));
|
||||
}
|
||||
|
||||
void addOpenTxLcdOptions(OpenTxFirmware * firmware)
|
||||
@@ -1196,6 +1199,8 @@ void registerOpenTxFirmwares()
|
||||
firmware->addOption("noheli", QObject::tr("Disable HELI menu and cyclic mix support"));
|
||||
firmware->addOption("nogvars", QObject::tr("Disable Global variables"));
|
||||
firmware->addOption("lua", QObject::tr("Support for Lua model scripts"));
|
||||
/* untested */
|
||||
//firmware->addOption("multimodule", QObject::tr("Support for the DIY-Multiprotocol-TX-Module"));
|
||||
addOpenTxCommonOptions(firmware);
|
||||
firmwares.push_back(firmware);
|
||||
|
||||
|
||||
@@ -181,6 +181,11 @@ ModulePanel::ModulePanel(QWidget *parent, ModelData & model, ModuleData & module
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<=MM_RF_PROTO_LAST; i++)
|
||||
{
|
||||
ui->multiProtocol->addItem(ModelPrinter::printMultiRfProtocol(i), (QVariant) i);
|
||||
}
|
||||
|
||||
if (firmware->getCapability(HasFailsafe)) {
|
||||
for (int i=0; i<maxChannels; i++) {
|
||||
QLabel * label = new QLabel(this);
|
||||
@@ -226,6 +231,7 @@ ModulePanel::~ModulePanel()
|
||||
#define MASK_PPM_FIELDS 16
|
||||
#define MASK_FAILSAFES 32
|
||||
#define MASK_OPEN_DRAIN 64
|
||||
#define MASK_MULTIMODULE 128
|
||||
|
||||
void ModulePanel::update()
|
||||
{
|
||||
@@ -261,6 +267,9 @@ void ModulePanel::update()
|
||||
mask |= MASK_OPEN_DRAIN;
|
||||
}
|
||||
break;
|
||||
case PULSES_MULTIMODULE:
|
||||
mask |= MASK_CHANNELS_RANGE | MASK_RX_NUMBER | MASK_MULTIMODULE;
|
||||
break;
|
||||
case PULSES_OFF:
|
||||
default:
|
||||
break;
|
||||
@@ -306,6 +315,32 @@ void ModulePanel::update()
|
||||
ui->ppmFrameLength->setMaximum(firmware->getCapability(PPMFrameLength));
|
||||
ui->ppmFrameLength->setValue(22.5+((double)module.ppm.frameLength)*0.5);
|
||||
|
||||
// Multi settings fields
|
||||
ui->label_multiProtocol->setVisible(mask & MASK_MULTIMODULE);
|
||||
ui->multiProtocol->setVisible(mask & MASK_MULTIMODULE);
|
||||
ui->multiProtocol->setCurrentIndex(module.getMultiRfProtocol());
|
||||
ui->label_multiSubType->setVisible(mask & MASK_MULTIMODULE);
|
||||
ui->multiSubType->setVisible(mask & MASK_MULTIMODULE);
|
||||
|
||||
if (mask & MASK_MULTIMODULE) {
|
||||
int numEntries = getNumSubtypes(static_cast<MultiModuleRFProtocols>(module.getMultiRfProtocol()));
|
||||
// Removes extra items
|
||||
ui->multiSubType->setMaxCount(numEntries);
|
||||
for (int i=0; i < numEntries; i++) {
|
||||
if (i < ui->multiSubType->count())
|
||||
ui->multiSubType->setItemText(i, ModelPrinter::printMultiSubType(module.getMultiRfProtocol(), i));
|
||||
else
|
||||
ui->multiSubType->addItem(ModelPrinter::printMultiSubType(module.getMultiRfProtocol(), i), (QVariant) i);
|
||||
}
|
||||
}
|
||||
ui->multiSubType->setCurrentIndex(module.subType);
|
||||
|
||||
ui->cb_autoBind->setVisible(mask & MASK_MULTIMODULE);
|
||||
ui->cb_autoBind->setChecked(module.multi.autoBindMode ? Qt::Checked : Qt::Unchecked);
|
||||
ui->cb_lowPower->setVisible(mask & MASK_MULTIMODULE);
|
||||
ui->cb_lowPower->setChecked(module.multi.lowPowerMode ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
|
||||
if (firmware->getCapability(HasFailsafe)) {
|
||||
ui->label_failsafeMode->setVisible(mask & MASK_FAILSAFES);
|
||||
ui->failsafeMode->setVisible(mask & MASK_FAILSAFES);
|
||||
@@ -435,6 +470,39 @@ void ModulePanel::onFailsafeComboIndexChanged(int index)
|
||||
}
|
||||
}
|
||||
|
||||
void ModulePanel::on_multiProtocol_currentIndexChanged(int index)
|
||||
{
|
||||
if (!lock) {
|
||||
lock=true;
|
||||
module.setMultiRfProtocol(index);
|
||||
unsigned int maxSubTypes = getNumSubtypes(static_cast<MultiModuleRFProtocols>(index));
|
||||
module.subType = std::min(module.subType, maxSubTypes -1);
|
||||
update();
|
||||
emit modified();
|
||||
lock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ModulePanel::on_multiSubType_currentIndexChanged(int index)
|
||||
{
|
||||
if (!lock) {
|
||||
lock=true;
|
||||
module.subType = index;
|
||||
update();
|
||||
emit modified();
|
||||
lock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ModulePanel::on_autoBind_stateChanged(int state)
|
||||
{
|
||||
module.multi.autoBindMode = (state == Qt::Checked);
|
||||
}
|
||||
void ModulePanel::on_lowPower_stateChanged(int state)
|
||||
{
|
||||
module.multi.lowPowerMode = (state == Qt::Checked);
|
||||
}
|
||||
|
||||
void ModulePanel::updateFailsafe(int channel)
|
||||
{
|
||||
int failsafeValue = module.failsafeChannels[channel];
|
||||
|
||||
@@ -65,6 +65,10 @@ class ModulePanel : public ModelPanel
|
||||
void on_failsafeMode_currentIndexChanged(int value);
|
||||
void onFailsafeComboIndexChanged(int index);
|
||||
void onFailsafeSpinChanged(double value);
|
||||
void on_multiProtocol_currentIndexChanged(int index);
|
||||
void on_multiSubType_currentIndexChanged(int index);
|
||||
void on_autoBind_stateChanged(int state);
|
||||
void on_lowPower_stateChanged(int state);
|
||||
|
||||
private:
|
||||
ModuleData & module;
|
||||
|
||||
@@ -534,6 +534,26 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_multiProtocol">
|
||||
<property name="text">
|
||||
<string>Multi Radio Protocol</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="multiProtocol">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QLabel" name="label_rxNumber">
|
||||
<property name="maximumSize">
|
||||
@@ -571,6 +591,37 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="label_multiSubType">
|
||||
<property name="text">
|
||||
<string>SubType</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QComboBox" name="multiSubType">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QCheckBox" name="cb_autoBind">
|
||||
<property name="text">
|
||||
<string>Autobind</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="5">
|
||||
<widget class="QCheckBox" name="cb_lowPower">
|
||||
<property name="text">
|
||||
<string>Low Power</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -98,15 +98,72 @@ QString ModelPrinter::printModuleProtocol(unsigned int protocol)
|
||||
"LP45", "DSM2", "DSMX",
|
||||
"PPM16", "PPMsim",
|
||||
"FrSky XJT (D16)", "FrSky XJT (D8)", "FrSky XJT (LR12)", "FrSky DJT",
|
||||
"Crossfire"
|
||||
"Crossfire",
|
||||
"DIY Multiprotocol Module"
|
||||
};
|
||||
|
||||
return CHECK_IN_ARRAY(strings, protocol);
|
||||
}
|
||||
|
||||
QString ModelPrinter::printModule(int idx)
|
||||
QString ModelPrinter::printMultiRfProtocol(int rfProtocol)
|
||||
{
|
||||
const ModuleData & module = model.moduleData[idx];
|
||||
static const char *strings[] = {
|
||||
"FlySky", "Hubsan", "FrSky", "Hisky", "V2x2", "DSM", "Devo", "YD717", "KN", "SymaX", "SLT", "CX10", "CG023",
|
||||
"Bayang", "ESky", "MT99XX", "MJXQ", "Shenqi", "FY326", "SFHSS", "Custom"
|
||||
};
|
||||
if (rfProtocol > MM_RF_PROTO_CUSTOM)
|
||||
return "Custom - proto " + QString::number(rfProtocol & 0x1f);
|
||||
else
|
||||
return CHECK_IN_ARRAY(strings, rfProtocol);
|
||||
}
|
||||
|
||||
QString ModelPrinter::printMultiSubType(int rfProtocol, int subType) {
|
||||
/* custom protocols */
|
||||
if (rfProtocol >= MM_RF_PROTO_CUSTOM) {
|
||||
static const char *custom_subtype_strings[] = {"Subtype 0","Subtype 1","Subtype 2","Subtype 3","Subtype 4","Subtype 5","Subtype 6","Subtype 7"};
|
||||
return CHECK_IN_ARRAY(custom_subtype_strings, subType);
|
||||
}
|
||||
switch (rfProtocol) {
|
||||
case MM_RF_PROTO_FLYSKY:
|
||||
static const char *flysky_strings[] = {"Standard","V9x9","V6x6","V912"};
|
||||
return CHECK_IN_ARRAY(flysky_strings, subType);
|
||||
case MM_RF_PROTO_FRSKY:
|
||||
static const char *frsky_strings[] = {"D16", "D8", "D16 8ch"};
|
||||
return CHECK_IN_ARRAY(frsky_strings, subType);
|
||||
case MM_RF_PROTO_HISKY:
|
||||
static const char *hisky_strings[] = { "HiSky", "HK310" };
|
||||
return CHECK_IN_ARRAY(hisky_strings, subType);
|
||||
case MM_RF_PROTO_DSM2:
|
||||
static const char *dsm2_strings[] = {"DSM2", "DSMX"};
|
||||
return CHECK_IN_ARRAY(dsm2_strings, subType);
|
||||
case MM_RF_PROTO_YD717:
|
||||
static const char *yd717_strings[] = {"YD717", "Skywalker", "Syma X2", "XINXUN", "NIHUI"};
|
||||
return CHECK_IN_ARRAY(yd717_strings, subType);
|
||||
case MM_RF_PROTO_SYMAX:
|
||||
static const char *symax_strings[] = {"Standard", "Syma X5C"};
|
||||
return CHECK_IN_ARRAY(symax_strings, subType);
|
||||
case MM_RF_PROTO_CX10:
|
||||
static const char *cx10_strings[] = {"Green", "Blue", "DM007", "Q282", "JC3015a", "JC3015b", "MK33041", "Q242"};
|
||||
return CHECK_IN_ARRAY(cx10_strings, subType);
|
||||
case MM_RF_PROTO_CG023:
|
||||
static const char *cg023_strings[] = {"CG023", "YD829", "H3 3D"};
|
||||
return CHECK_IN_ARRAY(cg023_strings, subType);
|
||||
case MM_RF_PROTO_KN:
|
||||
static const char* kn_strings[] = {"WLtoys", "FeiLun"};
|
||||
return CHECK_IN_ARRAY(kn_strings, subType);
|
||||
case MM_RF_PROTO_MT99XX:
|
||||
static const char* mt99_strings[] = {"MT99","H7","YZ"};
|
||||
return CHECK_IN_ARRAY(mt99_strings, subType);
|
||||
case MM_RF_PROTO_MJXQ:
|
||||
static const char* mjxq_strings[] = {"WLH08", "X600", "X800", "H26D"};
|
||||
return CHECK_IN_ARRAY(mjxq_strings, subType);
|
||||
default:
|
||||
return "DEFAULT";
|
||||
}
|
||||
}
|
||||
|
||||
QString ModelPrinter::printModule(int idx) {
|
||||
const ModuleData &module = model.moduleData[idx];
|
||||
if (module.protocol == PULSES_OFF)
|
||||
return printModuleProtocol(module.protocol);
|
||||
else if (module.protocol == PULSES_PPM)
|
||||
@@ -116,6 +173,8 @@ QString ModelPrinter::printModule(int idx)
|
||||
if (module.protocol != PULSES_PXX_XJT_D8) {
|
||||
result += " " + tr("Receiver number(%1)").arg(module.modelId);
|
||||
}
|
||||
if (module.protocol == PULSES_MULTIMODULE)
|
||||
result += " " + tr("radio Protocol %1, subType %2, option value %3").arg(printMultiRfProtocol(module.multi.rfProtocol)).arg(printMultiSubType(module.multi.rfProtocol, module.subType)).arg(module.multi.optionValue);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ class ModelPrinter: public QObject
|
||||
QString printTrimIncrementMode();
|
||||
QString printThrottleTrimMode();
|
||||
static QString printModuleProtocol(unsigned int protocol);
|
||||
static QString printMultiRfProtocol(int rfProtocol);
|
||||
static QString printMultiSubType(int rfProtocol, int subType);
|
||||
QString printFlightModeSwitch(int index);
|
||||
QString printFlightModeName(int index);
|
||||
QString printFlightModes(unsigned int flightModes);
|
||||
|
||||
@@ -254,7 +254,8 @@ options_taranis = {
|
||||
"internalppm": ("TARANIS_INTERNAL_PPM", "YES", "NO"),
|
||||
"shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
|
||||
"timer3": ("TIMERS", "3", "2"),
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO")
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
|
||||
"multimodule": ("MULTIMODULE", "YES", "NO")
|
||||
}
|
||||
|
||||
options_taranisplus = {
|
||||
@@ -273,7 +274,8 @@ options_taranisplus = {
|
||||
"internalppm": ("TARANIS_INTERNAL_PPM", "YES", "NO"),
|
||||
"shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
|
||||
"timer3": ("TIMERS", "3", None),
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO")
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
|
||||
"multimodule": ("MULTIMODULE", "YES", "NO")
|
||||
}
|
||||
|
||||
options_taranisx9e = {
|
||||
@@ -293,7 +295,8 @@ options_taranisx9e = {
|
||||
"shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
|
||||
"timer3": ("TIMERS", "3", None),
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
|
||||
"horussticks": ("STICKS", "HORUS", "STANDARD")
|
||||
"horussticks": ("STICKS", "HORUS", "STANDARD"),
|
||||
"multimodule": ("MULTIMODULE", "YES", "NO")
|
||||
}
|
||||
|
||||
options_horus = {
|
||||
@@ -307,5 +310,6 @@ options_horus = {
|
||||
"massstorage": ("USB", "MASSSTORAGE", None),
|
||||
"cli": ("USB", "SERIAL", None),
|
||||
"timer3": ("TIMERS", "3", "2"),
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO")
|
||||
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
|
||||
"multimodule": ("MULTIMODULE", "YES", "NO")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user