Implement Multimodule TX options for Companion

This commit is contained in:
Arne Schwabe
2016-04-18 00:09:51 +02:00
parent 67364789a8
commit 7b30201867
10 changed files with 288 additions and 16 deletions
+29
View File
@@ -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;
}
}
+58 -9
View File
@@ -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);
+68
View File
@@ -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];
+4
View File
@@ -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;
+51
View File
@@ -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>
+62 -3
View File
@@ -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;
}
}
+2
View File
@@ -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);
+8 -4
View File
@@ -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")
}