diff --git a/companion/src/firmwares/CMakeLists.txt b/companion/src/firmwares/CMakeLists.txt index 0a984b8f3..926ad2da8 100644 --- a/companion/src/firmwares/CMakeLists.txt +++ b/companion/src/firmwares/CMakeLists.txt @@ -39,6 +39,8 @@ set(firmwares_SRCS edgetx/yaml_rawswitch.cpp edgetx/yaml_rawsource.cpp edgetx/yaml_mixdata.cpp + edgetx/yaml_expodata.cpp + edgetx/yaml_curvedata.cpp datahelpers.cpp customisation_data.cpp ) diff --git a/companion/src/firmwares/edgetx/yaml_curvedata.cpp b/companion/src/firmwares/edgetx/yaml_curvedata.cpp new file mode 100644 index 000000000..ec02f0b38 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_curvedata.cpp @@ -0,0 +1,106 @@ +/* + * 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_curvedata.h" + +// CurveHeader curves[MAX_CURVES]; +// int8_t points[MAX_CURVE_POINTS]; + +void YamlReadCurvePoints(const YAML::Node& node, CurveData* curves) +{ + int pidx = 0; + for (int i = 0; i < CPN_MAX_CURVES; i++) { + CurveData& curve = curves[i]; + for (int j = 0; j < curve.count; j++) { + std::string pidx_str = std::to_string(pidx++); + if (node[pidx_str]) { + int y = 0; + node[pidx_str]["val"] >> y; + curve.points[j].y = (int8_t)y; + } + } + if (curve.type == CurveData::CURVE_TYPE_CUSTOM) { + // Custom curve: X points are trailing Y points + curve.points[0].x = -100; + for (int k = 1; k < curve.count - 1; k++) { + std::string pidx_str = std::to_string(pidx++); + if (node[pidx_str]) { + int x = 0; + node[pidx_str]["val"] >> x; + curve.points[k].x = (int8_t)x; + } + } + curve.points[curve.count - 1].x = +100; + } else { + // Standard curve: X points are generated + for (int k = 0; k < curve.count; k++) { + curve.points[k].x = -100 + (200 * k) / (curve.count - 1); + } + } + } +} + +void YamlWriteCurvePoints(YAML::Node& node, const CurveData* curves) +{ + int pidx = 0; + for (int i = 0; i < CPN_MAX_CURVES; i++) { + + //TODO: assert max number of points + // and raise exception + + const CurveData& curve = curves[i]; + if (!curve.isEmpty()) { + for (int k = 0; k < curve.count; k++) { + node[std::to_string(pidx++)]["val"] = (int)curve.points[k].y; + } + if (curve.type == CurveData::CURVE_TYPE_CUSTOM) { + for (int k = 1; k < curve.count - 1; k++) { + node[std::to_string(pidx++)]["val"] = (int)curve.points[k].x; + } + } + } else { + pidx += 5; + } + } +} + +namespace YAML +{ +Node convert::encode(const CurveData& rhs) +{ + Node node; + node["type"] = (int)rhs.type; + node["smooth"] = (int)rhs.smooth; + node["points"] = rhs.count - 5; + node["name"] = rhs.name; + return node; +} + +bool convert::decode(const Node& node, CurveData& rhs) +{ + int curve_type = 0; + node["type"] >> curve_type; + rhs.type = (CurveData::CurveType)curve_type; + node["smooth"] >> rhs.smooth; + node["points"] >> ioffset_int(rhs.count, -5); + node["name"] >> rhs.name; + return true; +} +} diff --git a/companion/src/firmwares/edgetx/yaml_curvedata.h b/companion/src/firmwares/edgetx/yaml_curvedata.h new file mode 100644 index 000000000..c33e7eeab --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_curvedata.h @@ -0,0 +1,34 @@ +/* + * 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 "curvedata.h" + +void YamlReadCurvePoints(const YAML::Node& node, CurveData* curves); +void YamlWriteCurvePoints(YAML::Node& node, const CurveData* curves); + +namespace YAML +{ +template <> +struct convert { + static Node encode(const CurveData& rhs); + static bool decode(const Node& node, CurveData& rhs); +}; +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_expodata.cpp b/companion/src/firmwares/edgetx/yaml_expodata.cpp new file mode 100644 index 000000000..2a4987022 --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_expodata.cpp @@ -0,0 +1,67 @@ +/* + * 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_expodata.h" +#include "yaml_mixdata.h" +#include "yaml_rawswitch.h" +#include "yaml_rawsource.h" +#include "curvereference.h" + +namespace YAML +{ +Node convert::encode(const ExpoData& rhs) +{ + Node node; + node["srcRaw"] = rhs.srcRaw; + node["scale"] = rhs.scale; + node["mode"] = rhs.mode; // InputMode + node["chn"] = rhs.chn; + node["swtch"] = rhs.swtch; + node["flightModes"] = YamlWriteFlightModes(rhs.flightModes); + node["weight"] = YamlWriteMixWeight(rhs.weight); + node["offset"] = rhs.offset; // YamlWriteMixWeight + node["curve"] = rhs.curve; + node["carryTrim"] = rhs.carryTrim; + node["name"] = rhs.name; + return node; +} + +bool convert::decode(const Node& node, ExpoData& rhs) +{ + node["srcRaw"] >> rhs.srcRaw; + node["scale"] >> rhs.scale; + node["mode"] >> rhs.mode; // InputMode + node["chn"] >> rhs.chn; + node["swtch"] >> rhs.swtch; + if (node["flightModes"]) { + rhs.flightModes = YamlReadFlightModes(node["flightModes"]); + } + if (node["weight"]) { + rhs.weight = YamlReadMixWeight(node["weight"]); + } + if (node["offset"]) { + rhs.offset = YamlReadMixWeight(node["offset"]); + } + node["curve"] >> rhs.curve; + node["carryTrim"] >> rhs.carryTrim; + node["name"] >> rhs.name; + return true; +} +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_expodata.h b/companion/src/firmwares/edgetx/yaml_expodata.h new file mode 100644 index 000000000..1495bce6d --- /dev/null +++ b/companion/src/firmwares/edgetx/yaml_expodata.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 "input_data.h" + +namespace YAML +{ +template <> +struct convert { + static Node encode(const ExpoData& rhs); + static bool decode(const Node& node, ExpoData& rhs); +}; +} // namespace YAML diff --git a/companion/src/firmwares/edgetx/yaml_mixdata.cpp b/companion/src/firmwares/edgetx/yaml_mixdata.cpp index 4fbb0daa3..979539228 100644 --- a/companion/src/firmwares/edgetx/yaml_mixdata.cpp +++ b/companion/src/firmwares/edgetx/yaml_mixdata.cpp @@ -53,8 +53,9 @@ static const YamlLookupTable mixMultiplexLut = { #define GVAR_SMALL 128 #define CPN_GV1 1024 -static int32_t readMixWeight(const std::string& val) +int32_t YamlReadMixWeight(const YAML::Node& node) { + std::string val = node.as(); if ((val.size() >= 4) && (val[0] == '-') && (val[1] == 'G') @@ -77,7 +78,7 @@ static int32_t readMixWeight(const std::string& val) return std::stoi(val); } -static std::string writeMixWeight(int32_t sval) +std::string YamlWriteMixWeight(int32_t sval) { if (sval < -10000) { int n = -sval - 10000; @@ -90,6 +91,30 @@ static std::string writeMixWeight(int32_t sval) return std::to_string(sval); } +uint32_t YamlReadFlightModes(const YAML::Node& node) +{ + std::string fm_str = node.as(); + 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; + } + return bits; +} + +std::string YamlWriteFlightModes(uint32_t val) +{ + std::string fm_str; + // TODO: constant for number of flight modes + for (int i=0; i<9; i++) { + uint32_t bit = (val >> i) & 1; + fm_str += bit ? "1" : "0"; + } + return fm_str; +} + static const YamlLookupTable dummy = {}; namespace YAML @@ -120,7 +145,7 @@ Node convert::encode(const MixData& rhs) Node node; node["destCh"] = rhs.destCh - 1; node["srcRaw"] = rhs.srcRaw; - node["weight"] = writeMixWeight(rhs.weight); + node["weight"] = YamlWriteMixWeight(rhs.weight); node["swtch"] = rhs.swtch; node["curve"] = rhs.curve; node["delayUp"] = rhs.delayUp; @@ -130,16 +155,8 @@ Node convert::encode(const MixData& rhs) 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["flightModes"] = YamlWriteFlightModes(rhs.flightModes); + node["offset"] = YamlWriteMixWeight(rhs.sOffset); node["name"] = rhs.name; return node; } @@ -148,11 +165,8 @@ 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); + if (node["weight"]) { + rhs.weight = YamlReadMixWeight(node["weight"]); } node["swtch"] >> rhs.swtch; node["curve"] >> rhs.curve; @@ -163,23 +177,12 @@ bool convert::decode(const Node& node, MixData& rhs) 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; + rhs.flightModes = YamlReadFlightModes(node["flightModes"]); + } + if (node["offset"]) { + rhs.sOffset = YamlReadMixWeight(node["offset"]); } - - 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 index 2c20166a8..0b08702f6 100644 --- a/companion/src/firmwares/edgetx/yaml_mixdata.h +++ b/companion/src/firmwares/edgetx/yaml_mixdata.h @@ -21,6 +21,13 @@ #include "yaml_ops.h" #include "mixdata.h" +int32_t YamlReadMixWeight(const YAML::Node& node); +std::string YamlWriteMixWeight(int32_t sval); + +uint32_t YamlReadFlightModes(const YAML::Node& node); +std::string YamlWriteFlightModes(uint32_t val); + + namespace YAML { template <> diff --git a/companion/src/firmwares/edgetx/yaml_modeldata.cpp b/companion/src/firmwares/edgetx/yaml_modeldata.cpp index 83ebbdab2..f2697eeb6 100644 --- a/companion/src/firmwares/edgetx/yaml_modeldata.cpp +++ b/companion/src/firmwares/edgetx/yaml_modeldata.cpp @@ -22,6 +22,9 @@ #include "yaml_rawswitch.h" #include "yaml_mixdata.h" #include "yaml_rawsource.h" +#include "yaml_expodata.h" +#include "yaml_curvedata.h" + #include "modeldata.h" #include "output_data.h" #include "eeprominterface.h" @@ -283,9 +286,30 @@ Node convert::encode(const ModelData& rhs) } } - // inputNames[] - // expoData[] - // curves[] + node["inputNames"] = + convert_array::encode( + rhs.inputNames); + + for (int i = 0; i < CPN_MAX_EXPOS; i++) { + const ExpoData& expo = rhs.expoData[i]; + if (!expo.isEmpty()) { + Node expoNode; + expoNode = expo; + node["expoData"].push_back(expoNode); + } + } + + for (int i = 0; i < CPN_MAX_CURVES; i++) { + const CurveData& curve = rhs.curves[i]; + if (!curve.isEmpty()) { + node["curves"][std::to_string(i)] = curve; + } + } + + YAML::Node points; + YamlWriteCurvePoints(points, rhs.curves); + node["points"] = points; + // logicalSw[] // customFn[] // swashRingData @@ -357,9 +381,13 @@ bool convert::decode(const Node& node, ModelData& rhs) node["mixData"] >> rhs.mixData; node["limitData"] >> rhs.limitData; - // inputNames[] - // expoData[] + node["inputNames"] >> rhs.inputNames; + node["expoData"] >> rhs.expoData; + // curves[] + node["curves"] >> rhs.curves; + YamlReadCurvePoints(node["points"], rhs.curves); + // logicalSw[] // customFn[] diff --git a/companion/src/firmwares/edgetx/yaml_ops.h b/companion/src/firmwares/edgetx/yaml_ops.h index 17e04173e..09d2f9783 100644 --- a/companion/src/firmwares/edgetx/yaml_ops.h +++ b/companion/src/firmwares/edgetx/yaml_ops.h @@ -95,6 +95,7 @@ void operator >> (const YAML::Node& node, char (&value)[N]) template void operator>>(const YAML::Node& node, T (&value)[N]) { + if (!node) return; if (node.IsMap()) { for (const auto& elmt : node) { try {