diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt index 4d149548f..0a984b8f3 100644 --- a/companion/src/firmwares/CMakeLists.txt +++ b/companion/src/firmwares/CMakeLists.txt @@ -37,6 +37,8 @@ set(firmwares_SRCS edgetx/yaml_switchconfig.cpp edgetx/yaml_modeldata.cpp edgetx/yaml_rawswitch.cpp + edgetx/yaml_rawsource.cpp + edgetx/yaml_mixdata.cpp datahelpers.cpp customisation_data.cpp ) diff --git a/companion/src/firmwares/edgetx/yaml_mixdata.cpp b/companion/src/firmwares/edgetx/yaml_mixdata.cpp new file mode 100644 index 000000000..614497450 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_mixdata.cpp @@ -0,0 +1,192 @@ +/* + * 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_mixdata.h" +#include "yaml_rawswitch.h" +#include "yaml_rawsource.h" +#include "curvereference.h" + +// static const YamlLookupTable timerModeLut = { +// {TimerData::TIMERMODE_OFF, "OFF"}, +// {TimerData::TIMERMODE_ON, "ON"}, +// {TimerData::TIMERMODE_START, "START"}, +// {TimerData::TIMERMODE_THR, "THR"}, +// {TimerData::TIMERMODE_THR_REL, "THR_REL"}, +// {TimerData::TIMERMODE_THR_START, "THR_START"}, +// }; + +// static const YamlLookupTable trainerModeLut = { +// { TRAINER_MODE_OFF, "OFF" }, +// { TRAINER_MODE_MASTER_JACK, "MASTER_TRAINER_JACK" }, +// { TRAINER_MODE_SLAVE_JACK, "SLAVE" }, +// { TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE, "MASTER_SBUS_EXT" }, +// { TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE, "MASTER_CPPM_EXT" }, +// { TRAINER_MODE_MASTER_BATTERY_COMPARTMENT, "MASTER_BATT_COMP" }, +// { TRAINER_MODE_MASTER_BLUETOOTH, "MASTER_BT" }, +// { TRAINER_MODE_SLAVE_BLUETOOTH, "SLAVE_BT" }, +// { TRAINER_MODE_MULTI, "MASTER_MULTI" }, +// }; + +static const YamlLookupTable mixMultiplexLut = { + { MLTPX_ADD, "ADD" }, + { MLTPX_MUL, "MUL" }, + { MLTPX_REP, "REPL" }, +}; + +#define GVAR_SMALL 128 +#define CPN_GV1 1024 + +static int32_t readMixWeight(const std::string& val) +{ + if ((val.size() >= 4) + && (val[0] == '-') + && (val[1] == 'G') + && (val[2] == 'V') + && (val[3] >= '1') + && (val[3] <= '9')) { + + return -10000 - std::stoi(val.substr(3)); + } + + if ((val.size() >= 3) + && (val[0] == 'G') + && (val[1] == 'V') + && (val[2] >= '1') + && (val[2] <= '9')) { + + return 10000 + std::stoi(val.substr(2)); + } + + return std::stoi(val); +} + +static std::string writeMixWeight(int32_t sval) +{ + if (sval < -10000) { + int n = -sval - 10000; + return std::string("-GV") + std::to_string(n); + } else if (sval > 10000) { + int n = sval - 10000; + return std::string("GV") + std::to_string(n); + } + + return std::to_string(sval); +} + +static const YamlLookupTable dummy = {}; + +namespace YAML +{ +ENUM_CONVERTER(MltpxValue, mixMultiplexLut); + +template <> +struct convert { + static Node encode(const CurveReference& rhs) + { + Node node; + node["type"] = (int)rhs.type; + node["value"] = rhs.value; + return node; + } + + static bool decode(const Node& node, CurveReference& rhs) + { + // no symbolic value defined in radio + int type = 0; + node["type"] >> type; + rhs.type = (CurveReference::CurveRefType)type; + + node["value"] >> rhs.value; + return true; + } +}; + +Node convert::encode(const MixData& rhs) +{ + Node node; + node["destCh"] = rhs.destCh - 1; + + // node["srcRaw"] = rhs.srcRaw; // r_mixSrcRaw + + node["weight"] = writeMixWeight(rhs.weight); + node["swtch"] = rhs.swtch; + node["curve"] = rhs.curve; + node["delayUp"] = rhs.delayUp; + node["delayDown"] = rhs.delayDown; + node["speedUp"] = rhs.speedUp; + node["speedDown"] = rhs.speedDown; + node["carryTrim"] = rhs.carryTrim; + node["mltpx"] = rhs.mltpx; + node["mixWarn"] = rhs.mixWarn; + + // TODO: constant for number of flight modes + std::string fm_str; + for (int i=0; i<9; i++) { + uint32_t bit = (rhs.flightModes >> i) & 1; + fm_str += bit ? "1" : "0"; + } + node["flightModes"] = fm_str; + + node["offset"] = rhs.sOffset; // TODO: use writeMixWeight() + node["name"] = rhs.name; + return node; +} + +bool convert::decode(const Node& node, MixData& rhs) +{ + node["destCh"] >> ioffset_int((int&)rhs.destCh, -1); + node["srcRaw"] >> rhs.srcRaw; + + std::string weight_str; + node["weight"] >> weight_str; + if (!weight_str.empty()) { + rhs.weight = readMixWeight(weight_str); + } + + node["swtch"] >> rhs.swtch; + node["curve"] >> rhs.curve; + node["delayUp"] >> rhs.delayUp; + node["delayDown"] >> rhs.delayDown; + node["speedUp"] >> rhs.speedUp; + node["speedDown"] >> rhs.speedDown; + node["carryTrim"] >> rhs.carryTrim; + node["mltpx"] >> rhs.mltpx; + node["mixWarn"] >> rhs.mixWarn; + + if (node["flightModes"]) { + std::string fm_str; + node["flightModes"] >> fm_str; + + uint32_t bits = 0; + uint32_t mask = 1; + + for (uint32_t i = 0; i < fm_str.size(); i++) { + if (fm_str[i] == '1') bits |= mask; + mask <<= 1; + } + + rhs.flightModes = bits; + } + + node["offset"] >> rhs.sOffset; // TODO: use readMixWeight() + node["name"] >> rhs.name; + return true; +} +} diff --git a/companion/src/firmwares/edgetx/yaml_mixdata.h b/companion/src/firmwares/edgetx/yaml_mixdata.h new file mode 100644 index 000000000..1ef01db7a --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_mixdata.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 "mixdata.h" + +namespace YAML { + +template <> +struct convert { + static Node encode(const MixData& rhs); + static bool decode(const Node& node, MixData& rhs); +}; +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index c762ee5fa..2adb23b6e 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -19,8 +19,12 @@ */ #include "yaml_modeldata.h" +#include "yaml_rawswitch.h" +#include "yaml_mixdata.h" #include "modeldata.h" +#include + static const YamlLookupTable timerModeLut = { {TimerData::TIMERMODE_OFF, "OFF"}, {TimerData::TIMERMODE_ON, "ON"}, @@ -97,7 +101,14 @@ Node convert::encode(const ModelData& rhs) node["throttleReversed"] = (int)rhs.throttleReversed; // flightModeData[] - // mixData[] + for (int i=0; i::decode(const Node& node, ModelData& rhs) // flightModeData[] // mixData[] + node["mixData"] >> rhs.mixData; // limitData[] // inputNames[] // expoData[] diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.h b/companion/src/firmwares/edgetx/yaml_modeldata.h index 5150d25da..25b05a471 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.h +++ b/companion/src/firmwares/edgetx/yaml_modeldata.h @@ -19,12 +19,8 @@ */ #include "yaml_ops.h" -#include "yaml_rawswitch.h" - #include "modeldata.h" -#include - namespace YAML { template <> diff --git a/companion/src/firmwares/edgetx/yaml_ops.h b/companion/src/firmwares/edgetx/yaml_ops.h index 52f90082a..5597bba42 100644 --- a/companion/src/firmwares/edgetx/yaml_ops.h +++ b/companion/src/firmwares/edgetx/yaml_ops.h @@ -95,20 +95,25 @@ void operator >> (const YAML::Node& node, char (&value)[N]) template void operator>>(const YAML::Node& node, T (&value)[N]) { - if (!node.IsMap()) return;// false; + if (node.IsMap()) { + for (const auto& elmt : node) { + try { + int idx = std::stoi(elmt.first.Scalar()); + if (idx < 0 || idx >= N) return; // false; - for (const auto& elmt : node) { - try { - int idx = std::stoi(elmt.first.Scalar()); - if (idx < 0 || idx >= N) return;// false; - - elmt.second >> value[idx]; - } catch (...) { - //return false; - return; + elmt.second >> value[idx]; + } catch (...) { + // return false; + return; + } + } + } else if (node.IsSequence()) { + int idx = 0; + for (const auto& elmt : node) { + elmt >> value[idx]; + idx++; } } - //return true; } namespace YAML { diff --git a/companion/src/firmwares/edgetx/yaml_rawsource.cpp b/companion/src/firmwares/edgetx/yaml_rawsource.cpp new file mode 100644 index 000000000..426a9a743 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_rawsource.cpp @@ -0,0 +1,197 @@ +/* + * 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_rawsource.h" + +// SOURCE_TYPE_STICK +const YamlLookupTable analogSourceLut = { + { 0, "Rud" }, + { 1, "Ele" }, + { 2, "Thr" }, + { 3, "Ail" }, + { 4, "S1" }, + { 5, "6POS" }, + { 6, "S2" }, + { 7, "EXT1" }, { 7, "S3" }, // rename to use only S3 + { 8, "EXT2" }, { 8, "S4" }, // rename to use only S4 + // { 9, "EXT3" }, + // { 10, "EXT4" }, + { 9, "LS" }, + { 10, "RS" }, + { 11, "MOUSE1" }, + { 12, "MOUSE2" }, +}; + +// SOURCE_TYPE_TRIM +const YamlLookupTable trimSourceLut = { + { 0, "TrimRud" }, + { 1, "TrimEle" }, + { 2, "TrimThr" }, + { 3, "TrimAil" }, + { 4, "TrimT5" }, + { 5, "TrimT6" }, +}; + +// SOURCE_TYPE_CYC +const YamlLookupTable cycSourceLut = { + { 0, "CYC1" }, + { 1, "CYC2" }, + { 2, "CYC3" }, +}; + +// SOURCE_TYPE_MAX + // { MIXSRC_MAX, "MAX" }, + +const YamlLookupTable specialSourceLut = { + { 0, "TX_VOLTAGE" }, + { 1, "TX_TIME" }, + { 2, "ONE" }, + { 3, "TIMER1" }, + { 4, "TIMER2" }, + { 5, "TIMER3" }, + // TODO: { ???, "TX_GPS" }, +}; + +namespace YAML { + +//ENUM_CONVERTER(RawSourceType, sourceTypeLut); + +Node convert::encode(const RawSource& rhs) +{ + std::string src_str; + return Node(src_str); +} + +bool convert::decode(const Node& node, RawSource& rhs) +{ + std::string src_str = node.Scalar(); + const char* val = src_str.data(); + size_t val_len = src_str.size(); + + if (val_len > 0 && val[0] == 'I') { + + rhs = RawSource(SOURCE_TYPE_VIRTUAL_INPUT, std::stoi(src_str.substr(1))); + + } else if (val_len > 4 && + val[0] == 'l' && + val[1] == 'u' && + val[2] == 'a' && + val[3] == '(') { + + src_str = src_str.substr(4); + + size_t next_pos = 0; + int script = std::stoi(src_str, &next_pos); + + if (next_pos >= src_str.size()) return false; + src_str = src_str.substr(next_pos + 1); + + int output = std::stoi(src_str); + rhs = RawSource(SOURCE_TYPE_LUA_OUTPUT, script * 16 + output); + + } else if (val_len > 3 && + val[0] == 'l' && + val[1] == 's' && + val[2] == '(') { + + src_str = src_str.substr(3); + int ls = std::stoi(src_str); + rhs = RawSource(SOURCE_TYPE_CUSTOM_SWITCH, ls); + + } else if (val_len > 3 && + val[0] == 't' && + val[1] == 'r' && + val[2] == '(') { + + src_str = src_str.substr(3); + int tr = std::stoi(src_str); + rhs = RawSource(SOURCE_TYPE_PPM, tr); + + } else if (val_len > 3 && + val[0] == 'c' && + val[1] == 'h' && + val[2] == '(') { + + src_str = src_str.substr(3); + int ch = std::stoi(src_str); + rhs = RawSource(SOURCE_TYPE_CH, ch); + + } else if (val_len > 3 && + val[0] == 'g' && + val[1] == 'v' && + val[2] == '(') { + + src_str = src_str.substr(3); + int gv = std::stoi(src_str); + rhs = RawSource(SOURCE_TYPE_GVAR, gv); + + } else if (val_len > 5 && + val[0] == 't' && + val[1] == 'e' && + val[2] == 'l' && + val[3] == 'e' && + val[4] == '(') { + + src_str = src_str.substr(5); + + // parse sign + uint8_t sign = 0; + if (src_str[0] == '-') { + sign = 1; + src_str = src_str.substr(1); + } else if (src_str[0] == '+') { + sign = 2; + src_str = src_str.substr(1); + } + + int sensor = std::stoi(src_str); + rhs = RawSource(SOURCE_TYPE_TELEMETRY, sensor * 3 + sign); + + } else { + + YAML::Node conv = node >> analogSourceLut; + if (conv.IsScalar()) { + rhs.type = SOURCE_TYPE_STICK; + rhs.index = conv.as(); + } + + conv = node >> trimSourceLut; + if (conv.IsScalar()) { + rhs.type = SOURCE_TYPE_TRIM; + rhs.index = conv.as(); + } + + conv = node >> cycSourceLut; + if (conv.IsScalar()) { + rhs.type = SOURCE_TYPE_CYC; + rhs.index = conv.as(); + } + + conv = node >> specialSourceLut; + if (conv.IsScalar()) { + rhs.type = SOURCE_TYPE_SPECIAL; + rhs.index = conv.as(); + } + } + // TODO: raw analogs + + return true; +} +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_rawsource.h b/companion/src/firmwares/edgetx/yaml_rawsource.h new file mode 100644 index 000000000..6cf25ba82 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_rawsource.h @@ -0,0 +1,32 @@ +/* + * 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 "rawsource.h" + +namespace YAML { + +template <> +struct convert { + static Node encode(const RawSource& rhs); + static bool decode(const Node& node, RawSource& rhs); +}; + +}