diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt index c2b258537..f7eea5186 100644 --- a/companion/src/firmwares/CMakeLists.txt +++ b/companion/src/firmwares/CMakeLists.txt @@ -43,6 +43,7 @@ set(firmwares_SRCS edgetx/yaml_curvedata.cpp edgetx/yaml_moduledata.cpp edgetx/yaml_logicalswitchdata.cpp + edgetx/yaml_customfunctiondata.cpp datahelpers.cpp customisation_data.cpp ) diff --git a/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp b/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp new file mode 100644 index 000000000..4f9db6a41 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_customfunctiondata.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "yaml_customfunctiondata.h" +#include "yaml_rawswitch.h" +#include "yaml_rawsource.h" + +static bool fnHasEnable(AssignFunc fn) +{ + return (fn <= FuncInstantTrim) + || (fn >= FuncReset && fn <= FuncSetTimerLast) + || (fn >= FuncAdjustGV1 && fn <= FuncBindExternalModule) + || (fn == FuncVolume); +} + +static bool fnHasRepeat(AssignFunc fn) +{ + return (fn == FuncPlayPrompt) + || (fn == FuncPlayValue) + || (fn == FuncPlayHaptic) + || (fn == FuncPlaySound); +} + +static const YamlLookupTable customFnLut = { + { FuncOverrideCH1, "OVERRIDE_CHANNEL" }, + { FuncTrainer, "TRAINER" }, + { FuncInstantTrim, "INSTANT_TRIM" }, + { FuncReset, "RESET" }, + { FuncSetTimer1, "SET_TIMER" }, + { FuncAdjustGV1, "ADJUST_GVAR" }, + { FuncVolume, "VOLUME" }, + { FuncSetFailsafe, "SET_FAILSAFE" }, + { FuncRangeCheckInternalModule, "RANGECHECK" }, + { FuncBindInternalModule, "BIND" }, + { FuncPlaySound, "PLAY_SOUND" }, + { FuncPlayPrompt, "PLAY_TRACK" }, + { FuncPlayValue, "PLAY_VALUE" }, + { FuncPlayScript, "PLAY_SCRIPT" }, + { FuncBackgroundMusic, "BACKGND_MUSIC" }, + { FuncBackgroundMusicPause, "BACKGND_MUSIC_PAUSE" }, + { FuncVario, "VARIO" }, + { FuncPlayHaptic, "HAPTIC" }, + { FuncLogs, "LOGS" }, + { FuncBacklight, "BACKLIGHT" }, + { FuncScreenshot, "SCREENSHOT" }, + { FuncRacingMode, "RACING_MODE" }, + { FuncDisableTouch, "DISABLE_TOUCH" }, +}; + +static const YamlLookupTable trainerLut = { + { 0, "sticks" }, + { 1, "Rud" }, + { 2, "Ele" }, + { 3, "Thr" }, + { 4, "Ail" }, + { 5, "chans" }, +}; + +static const YamlLookupTable soundLut = { + { 0, "Bp1" }, + { 1, "Bp2" }, + { 2, "Bp3" }, + { 3, "Wrn1" }, + { 5, "Wrn2" }, + { 6, "Chee" }, + { 7, "Rata" }, + { 8, "Tick" }, + { 9, "Sirn" }, + { 10, "Ring" }, + { 11, "SciF" }, + { 12, "Robt" }, + { 13, "Chrp" }, + { 14, "Tada" }, + { 15, "Crck" }, + { 16, "Alrm" }, +}; + +static const YamlLookupTable resetLut = { + { 0, "Tmr1" }, + { 1, "Tmr2" }, + { 2, "Tmr3" }, + { 3, "All" }, + { 5, "Tele" }, +}; + +static const YamlLookupTable gvarModeLut = { + { FUNC_ADJUST_GVAR_CONSTANT, "Cst" }, + { FUNC_ADJUST_GVAR_SOURCE, "Src" }, + { FUNC_ADJUST_GVAR_GVAR, "GVar" }, + { FUNC_ADJUST_GVAR_INCDEC, "IncDec" }, +}; + +static const YamlLookupTable moduleLut = { + { 0, "Int" }, + { 1, "Ext" }, +}; + +namespace YAML +{ +Node convert::encode(const CustomFunctionData& rhs) +{ + Node node; + node["swtch"] = rhs.swtch; + + int fn = rhs.func; + int p1 = 0; + if(fn >= FuncOverrideCH1 && fn <= FuncOverrideCHLast) { + p1 = fn - (int)FuncOverrideCH1; + fn = (int)FuncOverrideCH1; + } else if (fn >= FuncTrainer && fn <= FuncTrainerChannels) { + p1 = fn - (int)FuncTrainer; + fn = (int)FuncTrainer; + } else if (fn >= FuncSetTimer1 && fn <= FuncSetTimerLast) { + p1 = fn - (int)FuncSetTimer1; + fn = (int)FuncSetTimer1; + } else if (fn >= FuncAdjustGV1 && fn <= FuncAdjustGVLast) { + p1 = fn - (int)FuncAdjustGV1; + fn = (int)FuncAdjustGV1; + } else if (fn >= FuncRangeCheckInternalModule && fn <= FuncRangeCheckExternalModule) { + p1 = fn - (int)FuncRangeCheckInternalModule; + fn = (int)FuncRangeCheckInternalModule; + } else if (fn >= FuncBindInternalModule && fn <= FuncBindExternalModule) { + p1 = fn - (int)FuncBindInternalModule; + fn = (int)FuncBindInternalModule; + } + node["func"] = LookupValue(customFnLut, fn); + + std::string def; + switch(fn) { + case FuncOverrideCH1: + def += std::to_string(p1); + def += ","; + def += std::to_string(rhs.param); + break; + case FuncTrainer: + def += LookupValue(trainerLut, p1); + break; + case FuncPlaySound: + def += std::to_string(rhs.param); + break; + case FuncPlayPrompt: + case FuncPlayScript: + case FuncBackgroundMusic: + def += std::string(rhs.paramarm); + break; + case FuncReset: + def += LookupValue(resetLut, rhs.param); + if (def.empty()) { + def += std::to_string(rhs.param); + } + break; + case FuncSetTimer1: { + def += LookupValue(resetLut, p1); + def += ","; + def += std::to_string(rhs.param); + } break; + case FuncAdjustGV1: { + // + GV # + def += std::to_string(p1); + def += ","; + def += LookupValue(gvarModeLut, rhs.adjustMode); + def += ","; + + switch(rhs.adjustMode) { + case FUNC_ADJUST_GVAR_CONSTANT: + case FUNC_ADJUST_GVAR_INCDEC: + def += std::to_string(rhs.param); + break; + case FUNC_ADJUST_GVAR_GVAR: + case FUNC_ADJUST_GVAR_SOURCE: { + def += YamlRawSourceEncode(RawSource(rhs.param)); + } break; + } + } break; + case FuncRangeCheckInternalModule: + case FuncBindInternalModule: { + def += LookupValue(moduleLut, p1); + } break; + default: + break; + } + + if (fnHasEnable(rhs.func)) { + if (!def.empty()) { + def += ","; + } + def += std::to_string((int)rhs.enabled); + } else if(fnHasRepeat(rhs.func)) { + if (!def.empty()) { + def += ","; + } + if (rhs.repeatParam == 0) { + def += "1x"; + } else if (rhs.repeatParam == 0xFF) { + def += "!1x"; + } else { + def += std::to_string(rhs.repeatParam); + } + } + + if (!def.empty()) { + node["def"] = def; + } + + return node; +} + +bool convert::decode(const Node& node, + CustomFunctionData& rhs) +{ + node["swtch"] >> rhs.swtch; + + int func = 0; + node["func"] >> func; + rhs.func = (AssignFunc)func; + + std::string def_str; + node["def"] >> def_str; + std::stringstream def(def_str); + + switch(rhs.func) { + case FuncOverrideCH1: { + int ch=0; + def >> ch; + rhs.func = (AssignFunc)((int)rhs.func + ch); + def.ignore(); + def >> rhs.param; + } break; + case FuncTrainer: { + int value=0; + Node(def.str()) >> trainerLut >> value; + rhs.func = (AssignFunc)((int)rhs.func + value); + } break; + case FuncPlaySound: + Node(def.str()) >> soundLut >> rhs.param; + break; + case FuncPlayPrompt: + case FuncPlayScript: + case FuncBackgroundMusic: + strncpy(rhs.paramarm, def.str().c_str(), sizeof(rhs.paramarm)-1); + break; + case FuncReset: { + try { + def >> rhs.param; + rhs.param += 5; // + FUNC_RESET_PARAM_FIRST_TELEM + break; + } catch(...) {} + Node(def.str()) >> resetLut >> rhs.param; + } break; + case FuncSetTimer1: { + // + timer # + std::string tmr_str; + getline(def, tmr_str, ','); + int tmr = 0; + Node(tmr_str) >> resetLut >> tmr; + rhs.func = (AssignFunc)((int)rhs.func + tmr); + def >> rhs.param; + } break; + case FuncAdjustGV1: { + // + GV # + int gvar_idx=0; + def >> gvar_idx; + rhs.func = (AssignFunc)((int)rhs.func + gvar_idx); + def.ignore(); + + std::string mode; + getline(def, mode, ','); + Node(mode) >> gvarModeLut >> rhs.adjustMode; + switch(rhs.adjustMode) { + case FUNC_ADJUST_GVAR_CONSTANT: + case FUNC_ADJUST_GVAR_INCDEC: + def >> rhs.param; + break; + case FUNC_ADJUST_GVAR_GVAR: + case FUNC_ADJUST_GVAR_SOURCE: { + std::string src_str; + getline(def, src_str, ','); + RawSource src; + Node(src_str) >> src; + rhs.param = src.toValue(); + } break; + } + } break; + case FuncRangeCheckInternalModule: + case FuncBindInternalModule: { + // DANGEROUS_FUNCTIONS... + // + module # ??? + std::string mod; + getline(def, mod, ','); + int module=0; + Node(mod) >> moduleLut >> module; + rhs.func = (AssignFunc)((int)rhs.func + module); + } break; + default: + break; + } + + if (fnHasEnable(rhs.func)) { + int en = 0; + def >> en; + rhs.enabled = en; + } else if(fnHasRepeat(rhs.func)) { + std::string repeat; + getline(def, repeat); + if (repeat == "1x") { + rhs.repeatParam = 0; + } else if (repeat == "!1x") { + rhs.repeatParam = 0xFF; + } else { + rhs.repeatParam = std::stoi(repeat); + } + } + + return true; +} +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_customfunctiondata.h b/companion/src/firmwares/edgetx/yaml_customfunctiondata.h new file mode 100644 index 000000000..00e4700e1 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_customfunctiondata.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "yaml_ops.h" +#include "customfunctiondata.h" + +namespace YAML +{ +template <> +struct convert { + static Node encode(const CustomFunctionData& rhs); + static bool decode(const Node& node, CustomFunctionData& rhs); +}; +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp index 5c4c1e3dd..ec1ee53d2 100644 --- a/companion/src/firmwares/edgetx/yaml_generalsettings.cpp +++ b/companion/src/firmwares/edgetx/yaml_generalsettings.cpp @@ -19,6 +19,13 @@ */ #include "yaml_generalsettings.h" +#include "yaml_customfunctiondata.h" +#include "yaml_trainerdata.h" +#include "yaml_calibdata.h" +#include "yaml_switchconfig.h" + +#include "eeprominterface.h" +#include "edgetxinterface.h" const YamlLookupTable beeperModeLut = { { GeneralSettings::BEEPER_QUIET, "mode_quiet" }, @@ -64,3 +71,219 @@ const YamlLookupTable antennaModeLut = { { GeneralSettings::ANTENNA_MODE_EXTERNAL, "MODE_EXTERNAL" }, { GeneralSettings::ANTENNA_MODE_INTERNAL_EXTERNAL, "MODE_INTERNAL_EXTERNAL" }, }; + +namespace YAML +{ + +ENUM_CONVERTER(GeneralSettings::BeeperMode, beeperModeLut); + +Node convert::encode(const GeneralSettings& rhs) +{ + Node node; + + node["version"] = CPN_CURRENT_SETTINGS_VERSION; + + // Radio calib + YamlCalibData calib(rhs.calibMid, rhs.calibSpanNeg, rhs.calibSpanPos); + node["calib"] = calib; + + node["currModel"] = rhs.currModelIndex; + node["currModelFilename"] = rhs.currModelFilename; + node["contrast"] = rhs.contrast; + node["vBatWarn"] = rhs.vBatWarn; + node["txVoltageCalibration"] = rhs.txVoltageCalibration; + + node["vBatMin"] = rhs.vBatMin + 90; + node["vBatMax"] = rhs.vBatMax + 120; + + node["backlightMode"] = backlightModeLut << rhs.backlightMode; + node["trainer"] = rhs.trainer; + node["view"] = rhs.view; + node["fai"] = (int)rhs.fai; + node["disableMemoryWarning"] = (int)rhs.disableMemoryWarning; + node["beepMode"] = rhs.beeperMode; + node["disableAlarmWarning"] = (int)rhs.disableAlarmWarning; + node["disableRssiPoweroffAlarm"] = (int)rhs.disableRssiPoweroffAlarm; + node["USBMode"] = rhs.usbMode; + node["jackMode"] = rhs.jackMode; + node["hapticMode"] = rhs.hapticMode; + node["stickMode"] = rhs.stickMode; + node["timezone"] = rhs.timezone; + node["adjustRTC"] = rhs.adjustRTC; + node["inactivityTimer"] = rhs.inactivityTimer; + node["telemetryBaudrate"] = rhs.telemetryBaudrate; // TODO: conversion??? + node["splashMode"] = rhs.splashMode; // TODO: B&W only + node["templateSetup"] = rhs.templateSetup; + node["hapticLength"] = rhs.hapticLength + 2; + node["speakerPitch"] = rhs.speakerPitch * 15; + node["hapticStrength"] = rhs.hapticStrength + 2; + node["beepLength"] = rhs.beeperLength + 2; + node["gpsFormat"] = rhs.gpsFormat; + node["speakerVolume"] = rhs.speakerVolume + 12; + node["backlightBright"] = rhs.backlightBright; + node["switchesDelay"] = rhs.switchesDelay; + node["globalTimer"] = rhs.globalTimer; + node["bluetoothName"] = rhs.bluetoothName; + node["bluetoothBaudrate"] = rhs.bluetoothBaudrate; + node["bluetoothMode"] = bluetoothModeLut << rhs.bluetoothMode; + node["countryCode"] = rhs.countryCode; + node["jitterFilter"] = (int)rhs.jitterFilter; + node["disableRtcWarning"] = (int)rhs.rtcCheckDisable; // TODO: verify + node["keysBacklight"] = (int)rhs.keysBacklight; + node["imperial"] = rhs.imperial; + node["ttsLanguage"] = rhs.ttsLanguage; + node["beepVolume"] = rhs.beepVolume + 2; + node["wavVolume"] = rhs.wavVolume + 2; + node["varioVolume"] = rhs.varioVolume + 2; + node["varioPitch"] = rhs.varioPitch * 10; + node["varioRange"] = rhs.varioRange * 15; + node["varioRepeat"] = rhs.varioRepeat; + node["backgroundVolume"] = rhs.backgroundVolume + 2; + node["auxSerialMode"] = uartModeLut << rhs.auxSerialMode; + node["aux2SerialMode"] = uartModeLut << rhs.aux2SerialMode; + node["antennaMode"] = antennaModeLut << rhs.antennaMode; + node["backlightColor"] = rhs.backlightColor; + + for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++) { + const CustomFunctionData& fn = rhs.customFn[i]; + if (!fn.isEmpty()) { + node["customFn"][std::to_string(i)] = fn; + } + } + + node["sticksConfig"] = YamlStickConfig(rhs.stickName); + node["switchConfig"] = YamlSwitchConfig(rhs.switchName, rhs.switchConfig); + node["potsConfig"] = YamlPotConfig(rhs.potName, rhs.potConfig); + node["slidersConfig"] = YamlSliderConfig(rhs.sliderName, rhs.sliderConfig); + + // Color lcd theme settings are not used in EdgeTx + // RadioTheme::ThemeData themeData; + + node["ownerRegistrationID"] = rhs.registrationId; + + // Gyro (for now only xlites) + node["gyroMax"] = rhs.gyroMax; + node["gyroOffset"] = rhs.gyroOffset; + + // OneBit sampling (X9D only?) + node["uartSampleMode"] = rhs.uartSampleMode; + + return node; +} + +bool convert::decode(const Node& node, GeneralSettings& rhs) +{ + if (!node.IsMap()) return false; + + // for (const auto& n : node) { + // qDebug() << QString::fromStdString(n.first.Scalar()); + // } + + // TODO: check board string and fetch Board instance + std::string board; + node["board"] >> board; + // TODO: we should be able to fetch the board based on 'board' + // auto fw = getCurrentFirmware(); + // if (fw) { + // qDebug() << "FW Id: " << fw->getId(); + // if (fw->getId() != ("edgetx-" + radioData.generalSettings.board)) { + // throw std::runtime_error("Wrong board"); + // } + // } + + node["version"] >> rhs.version; + + // Radio calib + YamlCalibData calib; + node["calib"] >> calib; + calib.copy(rhs.calibMid, rhs.calibSpanNeg, rhs.calibSpanPos); + + node["currModel"] >> rhs.currModelIndex; + node["currModelFilename"] >> rhs.currModelFilename; + node["contrast"] >> rhs.contrast; + node["vBatWarn"] >> rhs.vBatWarn; + node["txVoltageCalibration"] >> rhs.txVoltageCalibration; + + node["vBatMin"] >> ioffset_int(rhs.vBatMin, 90); + node["vBatMax"] >> ioffset_int(rhs.vBatMax, 120); + + node["backlightMode"] >> backlightModeLut >> rhs.backlightMode; + node["trainer"] >> rhs.trainer; + node["view"] >> rhs.view; + node["fai"] >> rhs.fai; + node["disableMemoryWarning"] >> rhs.disableMemoryWarning; + node["beepMode"] >> rhs.beeperMode; + node["disableAlarmWarning"] >> rhs.disableAlarmWarning; + node["disableRssiPoweroffAlarm"] >> rhs.disableRssiPoweroffAlarm; + node["USBMode"] >> rhs.usbMode; + node["jackMode"] >> rhs.jackMode; + node["hapticMode"] >> rhs.hapticMode; + node["stickMode"] >> rhs.stickMode; + node["timezone"] >> rhs.timezone; + node["adjustRTC"] >> rhs.adjustRTC; + node["inactivityTimer"] >> rhs.inactivityTimer; + node["telemetryBaudrate"] >> rhs.telemetryBaudrate; // TODO: conversion??? + node["splashMode"] >> rhs.splashMode; // TODO: B&W only + node["templateSetup"] >> rhs.templateSetup; + node["hapticLength"] >> ioffset_int(rhs.hapticLength, 2); + node["speakerPitch"] >> ifactor(rhs.speakerPitch, 15); + node["hapticStrength"] >> ioffset_int(rhs.hapticStrength, 2); + node["beepLength"] >> ioffset_int(rhs.beeperLength, 2); + node["gpsFormat"] >> rhs.gpsFormat; + node["speakerVolume"] >> ioffset_int(rhs.speakerVolume, 12); + node["backlightBright"] >> rhs.backlightBright; + node["switchesDelay"] >> rhs.switchesDelay; + node["globalTimer"] >> rhs.globalTimer; + node["bluetoothName"] >> rhs.bluetoothName; + node["bluetoothBaudrate"] >> rhs.bluetoothBaudrate; + node["bluetoothMode"] >> bluetoothModeLut >> rhs.bluetoothMode; + node["countryCode"] >> rhs.countryCode; + node["jitterFilter"] >> rhs.jitterFilter; + node["disableRtcWarning"] >> rhs.rtcCheckDisable; // TODO: verify + node["keysBacklight"] >> rhs.keysBacklight; + node["imperial"] >> rhs.imperial; + node["ttsLanguage"] >> rhs.ttsLanguage; + node["beepVolume"] >> ioffset_int(rhs.beepVolume, 2); + node["wavVolume"] >> ioffset_int(rhs.wavVolume, 2); + node["varioVolume"] >> ioffset_int(rhs.varioVolume, 2); + node["varioPitch"] >> ifactor(rhs.varioPitch, 10); + node["varioRange"] >> ifactor(rhs.varioRange, 15); + node["varioRepeat"] >> rhs.varioRepeat; + node["backgroundVolume"] >> ioffset_int(rhs.backgroundVolume, 2); + node["auxSerialMode"] >> uartModeLut >> rhs.auxSerialMode; + node["aux2SerialMode"] >> uartModeLut >> rhs.aux2SerialMode; + node["antennaMode"] >> antennaModeLut >> rhs.antennaMode; + node["backlightColor"] >> rhs.backlightColor; + node["customFn"] >> rhs.customFn; + + YamlStickConfig stickConfig; + node["sticksConfig"] >> stickConfig; + stickConfig.copy(rhs.stickName); + + YamlSwitchConfig switchConfig; + node["switchConfig"] >> switchConfig; + switchConfig.copy(rhs.switchName, rhs.switchConfig); + + YamlPotConfig potsConfig; + node["potsConfig"] >> potsConfig; + potsConfig.copy(rhs.potName, rhs.potConfig); + + YamlSliderConfig slidersConfig; + node["slidersConfig"] >> slidersConfig; + slidersConfig.copy(rhs.sliderName, rhs.sliderConfig); + + // Color lcd theme settings are not used in EdgeTx + // RadioTheme::ThemeData themeData; + + node["ownerRegistrationID"] >> rhs.registrationId; + + // Gyro (for now only xlites) + node["gyroMax"] >> rhs.gyroMax; + node["gyroOffset"] >> rhs.gyroOffset; + + // OneBit sampling (X9D only?) + node["uartSampleMode"] >> rhs.uartSampleMode; + + return true; +} +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_generalsettings.h b/companion/src/firmwares/edgetx/yaml_generalsettings.h index cd398631b..401f6e4a1 100644 --- a/companion/src/firmwares/edgetx/yaml_generalsettings.h +++ b/companion/src/firmwares/edgetx/yaml_generalsettings.h @@ -19,241 +19,15 @@ */ #include "yaml_ops.h" -#include "yaml_trainerdata.h" -#include "yaml_calibdata.h" -#include "yaml_switchconfig.h" - #include "generalsettings.h" -#include "eeprominterface.h" -#include "edgetxinterface.h" - -extern const YamlLookupTable beeperModeLut; -extern const YamlLookupTable backlightModeLut; -extern const YamlLookupTable bluetoothModeLut; -extern const YamlLookupTable uartModeLut; -extern const YamlLookupTable antennaModeLut; namespace YAML { - ENUM_CONVERTER(GeneralSettings::BeeperMode, beeperModeLut); - template<> struct convert { - static YAML::Node encode(const GeneralSettings& rhs) { - Node node; - - node["version"] = CPN_CURRENT_SETTINGS_VERSION; - - // Radio calib - YamlCalibData calib(rhs.calibMid, rhs.calibSpanNeg, rhs.calibSpanPos); - node["calib"] = calib; - - node["currModel"] = rhs.currModelIndex; - node["currModelFilename"] = rhs.currModelFilename; - node["contrast"] = rhs.contrast; - node["vBatWarn"] = rhs.vBatWarn; - node["txVoltageCalibration"] = rhs.txVoltageCalibration; - - node["vBatMin"] = rhs.vBatMin + 90; - node["vBatMax"] = rhs.vBatMax + 120; - - node["backlightMode"] = backlightModeLut << rhs.backlightMode; - node["trainer"] = rhs.trainer; - node["view"] = rhs.view; - node["fai"] = (int)rhs.fai; - node["disableMemoryWarning"] = (int)rhs.disableMemoryWarning; - node["beepMode"] = rhs.beeperMode; - node["disableAlarmWarning"] = (int)rhs.disableAlarmWarning; - node["disableRssiPoweroffAlarm"] = (int)rhs.disableRssiPoweroffAlarm; - node["USBMode"] = rhs.usbMode; - node["jackMode"] = rhs.jackMode; - node["hapticMode"] = rhs.hapticMode; - node["stickMode"] = rhs.stickMode; - node["timezone"] = rhs.timezone; - node["adjustRTC"] = rhs.adjustRTC; - node["inactivityTimer"] = rhs.inactivityTimer; - node["telemetryBaudrate"] = rhs.telemetryBaudrate; // TODO: conversion??? - node["splashMode"] = rhs.splashMode; // TODO: B&W only - node["templateSetup"] = rhs.templateSetup; - node["hapticLength"] = rhs.hapticLength + 2; - node["speakerPitch"] = rhs.speakerPitch * 15; - node["hapticStrength"] = rhs.hapticStrength + 2; - node["beepLength"] = rhs.beeperLength + 2; - node["gpsFormat"] = rhs.gpsFormat; - node["speakerVolume"] = rhs.speakerVolume + 12 ; - node["backlightBright"] = rhs.backlightBright; - node["switchesDelay"] = rhs.switchesDelay; - node["globalTimer"] = rhs.globalTimer; - node["bluetoothName"] = rhs.bluetoothName; - node["bluetoothBaudrate"] = rhs.bluetoothBaudrate; - node["bluetoothMode"] = bluetoothModeLut << rhs.bluetoothMode; - node["countryCode"] = rhs.countryCode; - node["jitterFilter"] = (int)rhs.jitterFilter; - node["disableRtcWarning"] = (int)rhs.rtcCheckDisable; // TODO: verify - node["keysBacklight"] = (int)rhs.keysBacklight; - node["imperial"] = rhs.imperial; - node["ttsLanguage"] = rhs.ttsLanguage; - node["beepVolume"] = rhs.beepVolume + 2; - node["wavVolume"] = rhs.wavVolume + 2; - node["varioVolume"] = rhs.varioVolume + 2; - node["varioPitch"] = rhs.varioPitch * 10; - node["varioRange"] = rhs.varioRange * 15; - node["varioRepeat"] = rhs.varioRepeat; - node["backgroundVolume"] = rhs.backgroundVolume + 2; - node["auxSerialMode"] = uartModeLut << rhs.auxSerialMode; - node["aux2SerialMode"] = uartModeLut << rhs.aux2SerialMode; - node["antennaMode"] = antennaModeLut << rhs.antennaMode; - node["backlightColor"] = rhs.backlightColor; - - // if (node["customFn"]) { - // const YAML::Node& cfn = node["customFn"]; - // for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++) { - // cfn[i] = rhs.customFn[i]; - // } - // } - - node["sticksConfig"] = YamlStickConfig(rhs.stickName); - node["switchConfig"] = YamlSwitchConfig(rhs.switchName, rhs.switchConfig); - node["potsConfig"] = YamlPotConfig(rhs.potName, rhs.potConfig); - node["slidersConfig"] = YamlSliderConfig(rhs.sliderName, rhs.sliderConfig); - - // Color lcd theme settings are not used in EdgeTx - // RadioTheme::ThemeData themeData; - - node["ownerRegistrationID"] = rhs.registrationId; - - // Gyro (for now only xlites) - node["gyroMax"] = rhs.gyroMax; - node["gyroOffset"] = rhs.gyroOffset; - - // OneBit sampling (X9D only?) - node["uartSampleMode"] = rhs.uartSampleMode; - - return node; - } - - static bool decode(const Node& node, GeneralSettings& rhs) { - - if (!node.IsMap()) return false; - - // for (const auto& n : node) { - // qDebug() << QString::fromStdString(n.first.Scalar()); - // } - - // TODO: check board string and fetch Board instance - std::string board; - node["board"] >> board; - // TODO: we should be able to fetch the board based on 'board' - // auto fw = getCurrentFirmware(); - // if (fw) { - // qDebug() << "FW Id: " << fw->getId(); - // if (fw->getId() != ("edgetx-" + radioData.generalSettings.board)) { - // throw std::runtime_error("Wrong board"); - // } - // } - - node["version"] >> rhs.version; - - // Radio calib - YamlCalibData calib; - node["calib"] >> calib; - calib.copy(rhs.calibMid, rhs.calibSpanNeg, rhs.calibSpanPos); - - node["currModel"] >> rhs.currModelIndex; - node["currModelFilename"] >> rhs.currModelFilename; - node["contrast"] >> rhs.contrast; - node["vBatWarn"] >> rhs.vBatWarn; - node["txVoltageCalibration"] >> rhs.txVoltageCalibration; - - node["vBatMin"] >> ioffset_int(rhs.vBatMin, 90); - node["vBatMax"] >> ioffset_int(rhs.vBatMax, 120); - - node["backlightMode"] >> backlightModeLut >> rhs.backlightMode; - node["trainer"] >> rhs.trainer; - node["view"] >> rhs.view; - node["fai"] >> rhs.fai; - node["disableMemoryWarning"] >> rhs.disableMemoryWarning; - node["beepMode"] >> rhs.beeperMode; - node["disableAlarmWarning"] >> rhs.disableAlarmWarning; - node["disableRssiPoweroffAlarm"] >> rhs.disableRssiPoweroffAlarm; - node["USBMode"] >> rhs.usbMode; - node["jackMode"] >> rhs.jackMode; - node["hapticMode"] >> rhs.hapticMode; - node["stickMode"] >> rhs.stickMode; - node["timezone"] >> rhs.timezone; - node["adjustRTC"] >> rhs.adjustRTC; - node["inactivityTimer"] >> rhs.inactivityTimer; - node["telemetryBaudrate"] >> rhs.telemetryBaudrate; // TODO: conversion??? - node["splashMode"] >> rhs.splashMode; // TODO: B&W only - node["templateSetup"] >> rhs.templateSetup; - node["hapticLength"] >> ioffset_int(rhs.hapticLength, 2); - node["speakerPitch"] >> ifactor(rhs.speakerPitch, 15); - node["hapticStrength"] >> ioffset_int(rhs.hapticStrength, 2); - node["beepLength"] >> ioffset_int(rhs.beeperLength, 2); - node["gpsFormat"] >> rhs.gpsFormat; - node["speakerVolume"] >> ioffset_int(rhs.speakerVolume, 12); - node["backlightBright"] >> rhs.backlightBright; - node["switchesDelay"] >> rhs.switchesDelay; - node["globalTimer"] >> rhs.globalTimer; - node["bluetoothName"] >> rhs.bluetoothName; - node["bluetoothBaudrate"] >> rhs.bluetoothBaudrate; - node["bluetoothMode"] >> bluetoothModeLut >> rhs.bluetoothMode; - node["countryCode"] >> rhs.countryCode; - node["jitterFilter"] >> rhs.jitterFilter; - node["disableRtcWarning"] >> rhs.rtcCheckDisable; // TODO: verify - node["keysBacklight"] >> rhs.keysBacklight; - node["imperial"] >> rhs.imperial; - node["ttsLanguage"] >> rhs.ttsLanguage; - node["beepVolume"] >> ioffset_int(rhs.beepVolume, 2); - node["wavVolume"] >> ioffset_int(rhs.wavVolume, 2); - node["varioVolume"] >> ioffset_int(rhs.varioVolume, 2); - node["varioPitch"] >> ifactor(rhs.varioPitch, 10); - node["varioRange"] >> ifactor(rhs.varioRange, 15); - node["varioRepeat"] >> rhs.varioRepeat; - node["backgroundVolume"] >> ioffset_int(rhs.backgroundVolume, 2); - node["auxSerialMode"] >> uartModeLut >> rhs.auxSerialMode; - node["aux2SerialMode"] >> uartModeLut >> rhs.aux2SerialMode; - node["antennaMode"] >> antennaModeLut >> rhs.antennaMode; - node["backlightColor"] >> rhs.backlightColor; - - // if (node["customFn"]) { - // const YAML::Node& cfn = node["customFn"]; - // for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++) { - // cfn[i] >> rhs.customFn[i]; - // } - // } - - YamlStickConfig stickConfig; - node["sticksConfig"] >> stickConfig; - stickConfig.copy(rhs.stickName); - - YamlSwitchConfig switchConfig; - node["switchConfig"] >> switchConfig; - switchConfig.copy(rhs.switchName, rhs.switchConfig); - - YamlPotConfig potsConfig; - node["potsConfig"] >> potsConfig; - potsConfig.copy(rhs.potName, rhs.potConfig); - - YamlSliderConfig slidersConfig; - node["slidersConfig"] >> slidersConfig; - slidersConfig.copy(rhs.sliderName, rhs.sliderConfig); - - // Color lcd theme settings are not used in EdgeTx - // RadioTheme::ThemeData themeData; - - node["ownerRegistrationID"] >> rhs.registrationId; - - // Gyro (for now only xlites) - node["gyroMax"] >> rhs.gyroMax; - node["gyroOffset"] >> rhs.gyroOffset; - - // OneBit sampling (X9D only?) - node["uartSampleMode"] >> rhs.uartSampleMode; - - return true; - } + static Node encode(const GeneralSettings& rhs); + static bool decode(const Node& node, GeneralSettings& rhs); }; } diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index d565b63b2..6350f313f 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -26,6 +26,7 @@ #include "yaml_curvedata.h" #include "yaml_moduledata.h" #include "yaml_logicalswitchdata.h" +#include "yaml_customfunctiondata.h" #include "modeldata.h" #include "output_data.h" @@ -323,7 +324,12 @@ Node convert::encode(const ModelData& rhs) } } - // customFn[] + for (int i = 0; i < CPN_MAX_SPECIAL_FUNCTIONS; i++) { + const CustomFunctionData& fn = rhs.customFn[i]; + if (!fn.isEmpty()) { + node["customFn"][std::to_string(i)] = fn; + } + } // swashRingData YamlThrTrace thrTrace(rhs.thrTraceSrc); @@ -405,7 +411,7 @@ bool convert::decode(const Node& node, ModelData& rhs) YamlReadCurvePoints(node["points"], rhs.curves); node["logicalSw"] >> rhs.logicalSw; - //node["customFn"] >> rhs.customFn; + node["customFn"] >> rhs.customFn; // swashRingData