From fbd0fb6d5f38f7a12f3bebb4a7fb14bd3e6bfb7c Mon Sep 17 00:00:00 2001 From: Loïc Collignon Date: Thu, 16 Mar 2017 09:54:02 +0100 Subject: wip: generation of a configuration for can_signaling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I35b31a98e87943a4e2fcad06561fec7a347b8483 Signed-off-by: Loïc Collignon --- src/main.cpp | 246 +++++++++++++++++++++++++++++++------- src/openxc/can_bus.cpp | 4 +- src/openxc/can_bus.hpp | 15 ++- src/openxc/can_message.cpp | 41 +++++-- src/openxc/can_message.hpp | 17 +-- src/openxc/diagnostic_message.cpp | 4 +- src/openxc/diagnostic_message.hpp | 4 +- src/openxc/message_set.cpp | 38 +++--- src/openxc/message_set.hpp | 11 +- src/openxc/signal.cpp | 14 ++- src/openxc/signal.hpp | 7 +- 11 files changed, 295 insertions(+), 106 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 042781c8..3de298a5 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,160 @@ #define EXIT_COMMAND_LINE_ERROR 2 #define EXIT_PROGRAM_ERROR 3 +template +struct generator +{ + T v_; + std::string line_prefix_; + generator(T v, std::string line_prefix = "") : v_{v}, line_prefix_{line_prefix} {} +}; + +template <> +struct generator +{ + const openxc::signal& v_; + std::uint32_t index_; + std::string line_prefix_; + generator(const openxc::signal& v, std::uint32_t index, std::string line_prefix = "") + : v_{v}, index_{index}, line_prefix_{line_prefix} + { + } +}; + +template +generator gen(const T& v, std::string line_prefix = "") { return generator(v, line_prefix); } + +generator gen(const openxc::signal& v, std::uint32_t index, std::string line_prefix = "") +{ + return generator(v, index, line_prefix); +} + +template +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ << v.v_; + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ << (v.v_ ? "true" : "false"); + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ << std::showpoint << v.v_ << "f"; + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ << '\"' << v.v_ << '\"'; + return o; +} + +template +std::ostream& operator<<(std::ostream& o, const generator>& v) +{ + o << v.line_prefix_ << "{\n"; + auto sz = v.v_.size(); + for(const T& i : v.v_) + { + o << gen(i, v.line_prefix_ + '\t'); + if (sz > 1) o << ","; + --sz; + o << '\n'; + } + o << v.line_prefix_ << '}'; + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ + << '{' + << "0, " + << gen(v.v_.name()) << ", " + << v.v_.buses().size() << ", " + << v.v_.messages().size() << ", " + << std::accumulate( + std::begin(v.v_.messages()), + std::end(v.v_.messages()), + 0, + [](int sum, const openxc::can_message& p) { return sum + p.signals().size(); } + ) << ", " + << v.v_.commands().size() << ", " + << v.v_.diagnostic_messages().size() << "}"; + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ + << "can_message_definition_t(" + << "0, " + << gen(v.v_.bus()) << ", " + << v.v_.id() << ", " + << "can_message_format_t::STANDARD, " + << "frequency_clock_t(" << gen(v.v_.max_frequency()) << "), " + << gen(v.v_.force_send_changed()) + << ')'; + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator>>& v) +{ + o << v.line_prefix_ << "{\n"; + std::uint32_t c1 = v.v_.size(); + for(const auto& state : v.v_) + { + std::uint32_t c2 = state.second.size(); + for(const auto& i : state.second) + { + o << v.line_prefix_ << "\t" << "{" << i << ", " << gen(state.first) << "}"; + if (c1 > 1 || c2 > 1) o << ','; + o << '\n'; + --c2; + } + --c1; + } + o << v.line_prefix_ << "}"; + return o; +} + +template <> +std::ostream& operator<<(std::ostream& o, const generator& v) +{ + o << v.line_prefix_ << "{\n" + << v.line_prefix_ << "\t0,\n" + << v.line_prefix_ << "\t" << v.index_ << ",\n" + << v.line_prefix_ << "\t" << gen(v.v_.generic_name()) << ",\n" + << v.line_prefix_ << "\t" << v.v_.bit_position() << ",\n" + << v.line_prefix_ << "\t" << v.v_.bit_size() << ",\n" + << v.line_prefix_ << "\t" << gen(v.v_.factor()) << ", \n" + << v.line_prefix_ << "\t" << v.v_.offset() << ", \n" + << v.line_prefix_ << "\t" << "0,\n" + << v.line_prefix_ << "\t" << "0,\n" + << v.line_prefix_ << "\tfrequency_clock_t(" << gen(v.v_.max_frequency()) << "),\n" + << v.line_prefix_ << "\t" << gen(v.v_.send_same()) << ",\n" + << v.line_prefix_ << "\t" << gen(v.v_.force_send_changed()) << ",\n" + << gen(v.v_.states(), v.line_prefix_ + '\t') << ",\n" + << v.line_prefix_ << '\t' << gen(v.v_.writable()) << ",\n" + << v.line_prefix_ << '\t' << (v.v_.decoder().size() ? v.v_.decoder() : "nullptr") << ",\n" + << v.line_prefix_ << '\t' << (v.v_.encoder().size() ? v.v_.encoder() : "nullptr") << ",\n" + << v.line_prefix_ << '\t' << "false\n" + << v.line_prefix_ << "}"; + return o; +} + + /// @brief Generate the configuration code. /// @param[in] header Content to be inserted as a header. /// @param[in] footer Content to be inserted as a footer. @@ -21,53 +175,41 @@ /// @param[in] out Stream to write on. void generate(const std::string& header, const std::string& footer, const openxc::message_set& message_set, std::ostream& out) { + out << "#include \"configuration.hpp\"\n" + << "#include \"can/can-decoder.hpp\"\n\n"; + if (header.size()) out << header << "\n"; - else out << "#pragma once\n\n"; - - out << "namespace generated {\n" - << " class configuration_generated\n" + + out << "configuration_t::configuration_t()\n" + << " : can_message_set_" << gen(message_set) << '\n' + << " , can_message_definition_\n" << " {\n" - << " private:\n" - << " can_message_set_t can_message_set_;\n" - << " std::vector> can_message_definition_;\n" - << " std::vector> can_signals_;\n" - << " std::vector> obd2_signals_;\n" - << " public:\n" - << " configuration_generated()\n" - << " : message_set_{0, \"" - << message_set.name() << "\", " - << message_set.buses().size() << ", " - << message_set.messages().size() << ", " - << std::accumulate( - std::begin(message_set.messages()), - std::end(message_set.messages()), - 0, - [](int sum, const std::map::value_type& p) { return sum + p.second.signals().size(); } - ) << ", " - << message_set.commands().size() << ", " - << message_set.diagnostic_messages().size() << "}\n" - << " , can_message_definition_{\n"; - - std::uint32_t count = message_set.messages().size(); - for(const std::map::value_type& m : message_set.messages()) + << gen(message_set.messages(), "\t\t") << '\n' + << " }\n" + << " , can_signals_\n" + << " {\n"; + std::uint32_t message_count = message_set.messages().size(); + std::uint32_t index = 0; + for(const openxc::can_message& m : message_set.messages()) { - out << " {{\"" << m.second.bus() << "\", " - << m.first << ", " - << "can_message_format_t::STANDARD, frequency_clock_t(), false}}"; - if (count > 1) out << ","; - out << "\n"; - --count; + out << " {\n"; + std::uint32_t signal_count = m.signals().size(); + for(const openxc::signal& s : m.signals()) + { + out << gen(s, index, " "); + if (signal_count > 1) out << ','; + --signal_count; + out << '\n'; + } + out << " }"; + if (index + 1 < message_count) out << ','; + ++index; + out << '\n'; } - out << " }\n"; - - - out << " , can_signals_" << "..." << "\n" - << " , obd2_signals_" << "..." << "\n" - << " {\n" - << " }\n" - << " };\n" + out << " }\n" + << " //, obd2_signals_{" << "/*...*/" << "}\n" + << "{\n" << "}\n\n"; - out << footer << std::endl; } @@ -118,7 +260,7 @@ nlohmann::json read_json(const std::string& file) /// @return Exit code, zero if success. int main(int argc, char** argv) { - std::ios::sync_with_stdio(false); + //std::ios::sync_with_stdio(false); try { @@ -149,11 +291,23 @@ int main(int argc, char** argv) } bpo::notify(vm); - - std::string header = read_file(header_file); + + std::stringstream header; + header << read_file(header_file); + std::string footer = read_file(footer_file); openxc::message_set message_set; message_set.from_json(read_json(message_set_file)); + + boost::filesystem::path message_set_path(message_set_file); + message_set_path.remove_filename(); + for(const auto& s : message_set.extra_sources()) + { + boost::filesystem::path extra_source(s); + if (!extra_source.is_complete()) extra_source = message_set_path / extra_source; + header << "\n// >>>>> " << s << " >>>>>\n" << read_file(extra_source.string()) << "\n// <<<<< " << s << " <<<<<\n"; + } + std::ofstream out; if (output_file.size()) { @@ -166,7 +320,7 @@ int main(int argc, char** argv) } } - generate(header, footer, message_set, output_file.size() ? out : std::cout); + generate(header.str(), footer, message_set, output_file.size() ? out : std::cout); } catch (bpo::required_option& e) diff --git a/src/openxc/can_bus.cpp b/src/openxc/can_bus.cpp index 545a6c5c..0a968a9e 100755 --- a/src/openxc/can_bus.cpp +++ b/src/openxc/can_bus.cpp @@ -22,7 +22,7 @@ namespace openxc return raw_writable_; } - std::uint32_t can_bus::max_message_frequency() const + float can_bus::max_message_frequency() const { return max_message_frequency_; } @@ -38,7 +38,7 @@ namespace openxc speed_ = j.count("speed") ? j["speed"].get() : 0; raw_can_mode_ = j.count("raw_can_mode") ? j["raw_can_mode"].get() : can_bus_mode::off; raw_writable_ = j.count("raw_writable") ? j["raw_writable"].get() : false; - max_message_frequency_ = j.count("max_message_frequency") ? j["max_message_frequency"].get() : 0; + max_message_frequency_ = j.count("max_message_frequency") ? j["max_message_frequency"].get() : 0; force_send_changed_ = j.count("force_send_changed") ? j["force_send_changed"].get() : false; } diff --git a/src/openxc/can_bus.hpp b/src/openxc/can_bus.hpp index db8e0250..74e1273f 100755 --- a/src/openxc/can_bus.hpp +++ b/src/openxc/can_bus.hpp @@ -15,20 +15,19 @@ namespace openxc class can_bus { private: - std::uint32_t controller_; - std::uint32_t speed_; - can_bus_mode raw_can_mode_; - bool raw_writable_; - std::uint32_t max_message_frequency_; - bool force_send_changed_; + std::uint32_t controller_; + std::uint32_t speed_; + can_bus_mode raw_can_mode_; + bool raw_writable_; + float max_message_frequency_; + bool force_send_changed_; public: - std::uint32_t controller() const; std::uint32_t speed() const; can_bus_mode raw_can_mode() const; bool raw_writable() const; - std::uint32_t max_message_frequency() const; + float max_message_frequency() const; bool force_send_changed() const; void from_json(const nlohmann::json& j); diff --git a/src/openxc/can_message.cpp b/src/openxc/can_message.cpp index d42d1efa..fab5a85f 100755 --- a/src/openxc/can_message.cpp +++ b/src/openxc/can_message.cpp @@ -2,6 +2,16 @@ namespace openxc { + std::string can_message::id() const + { + return id_; + } + + void can_message::id(const std::string& id) + { + id_ = id; + } + std::string can_message::bus() const { return bus_; @@ -12,7 +22,7 @@ namespace openxc return bit_numbering_inverted_; } - const std::map& can_message::signals() const + const std::vector& can_message::signals() const { return signals_; } @@ -32,12 +42,12 @@ namespace openxc return enabled_; } - std::uint32_t can_message::max_frequency() const + float can_message::max_frequency() const { return max_frequency_; } - std::uint32_t can_message::max_signal_frequency() const + float can_message::max_signal_frequency() const { return max_signal_frequency_; } @@ -56,14 +66,25 @@ namespace openxc { bus_ = j.count("bus") ? j["bus"].get() : ""; bit_numbering_inverted_ = j.count("bit_numbering_inverted") ? j["bit_numbering_inverted"].get() : false; - signals_= j.count("signals") ? j["signals"].get>() : std::map(); name_ = j.count("name") ? j["name"].get() : ""; handlers_ = j.count("handlers") ? j["handlers"].get>() : std::vector(); enabled_ = j.count("enabled") ? j["enabled"].get() : true; - max_frequency_ = j.count("max_frequency") ? j["max_frequency"].get() : 0; - max_signal_frequency_ = j.count("max_signal_frequency") ? j["max_signal_frequency"].get() : 0; + max_frequency_ = j.count("max_frequency") ? j["max_frequency"].get() : 0; + max_signal_frequency_ = j.count("max_signal_frequency") ? j["max_signal_frequency"].get() : 0; force_send_changed_ = j.count("force_send_changed") ? j["force_send_changed"].get() : true; force_send_changed_signals_ = j.count("force_send_changed_signals") ? j["force_send_changed_signals"].get() : false; + + if(j.count("signals")) + { + std::map signals = j["signals"]; + for(const auto& s : signals) + { + signal sig = s.second.get(); + sig.id(s.first); + signals_.push_back(sig); + } + } + } std::uint32_t can_message::get_signals_count() const @@ -91,9 +112,15 @@ namespace openxc { j = p.to_json(); } - + void from_json(const nlohmann::json& j, can_message& p) { p.from_json(j); } + + void from_json(const nlohmann::json& j, can_message& p, const std::string& id) + { + p.from_json(j); + p.id(id); + } } diff --git a/src/openxc/can_message.hpp b/src/openxc/can_message.hpp index 57bd23fd..3f7b0181 100755 --- a/src/openxc/can_message.hpp +++ b/src/openxc/can_message.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include "signal.hpp" @@ -12,26 +11,29 @@ namespace openxc class can_message { private: + std::string id_; std::string bus_; bool bit_numbering_inverted_; - std::map signals_; + std::vector signals_; std::string name_; std::vector handlers_; bool enabled_; - std::uint32_t max_frequency_; - std::uint32_t max_signal_frequency_; + float max_frequency_; + float max_signal_frequency_; bool force_send_changed_; bool force_send_changed_signals_; public: + std::string id() const; + void id(const std::string& id); std::string bus() const; bool bit_numbering_inverted() const; - const std::map& signals() const; + const std::vector& signals() const; std::string name() const; std::vector handlers() const; bool enabled() const; - std::uint32_t max_frequency() const; - std::uint32_t max_signal_frequency() const; + float max_frequency() const; + float max_signal_frequency() const; bool force_send_changed() const; bool force_send_changed_signals() const; @@ -43,4 +45,5 @@ namespace openxc void to_json(nlohmann::json& j, const can_message& p); void from_json(const nlohmann::json& j, can_message& p); + void from_json(const nlohmann::json& j, can_message& p, const std::string& id); } diff --git a/src/openxc/diagnostic_message.cpp b/src/openxc/diagnostic_message.cpp index 44b21c64..3881abef 100755 --- a/src/openxc/diagnostic_message.cpp +++ b/src/openxc/diagnostic_message.cpp @@ -17,7 +17,7 @@ namespace openxc return mode_; } - std::uint32_t diagnostic_message::frequency() const + float diagnostic_message::frequency() const { return frequency_; } @@ -47,7 +47,7 @@ namespace openxc bus_ = j.count("bus") ? j["bus"].get() : ""; id_ = j.count("id") ? j["id"].get() : 0; mode_ = j.count("mode") ? j["mode"].get() : 1; - frequency_ = j.count("frequency") ? j["frequency"].get() : 0; + frequency_ = j.count("frequency") ? j["frequency"].get() : 0; pid_ = j.count("pid") ? j["pid"].get() : 0; name_ = j.count("name") ? j["name"].get() : ""; decoder_ = j.count("decoder") ? j["decoder"].get() : ""; diff --git a/src/openxc/diagnostic_message.hpp b/src/openxc/diagnostic_message.hpp index 33b41e61..1ceba1bd 100755 --- a/src/openxc/diagnostic_message.hpp +++ b/src/openxc/diagnostic_message.hpp @@ -11,7 +11,7 @@ namespace openxc std::string bus_; std::uint32_t id_; std::uint32_t mode_; - std::uint32_t frequency_; + float frequency_; std::uint32_t pid_; std::string name_; std::string decoder_; @@ -20,7 +20,7 @@ namespace openxc std::string bus() const; std::uint32_t id() const; std::uint32_t mode() const; - std::uint32_t frequency() const; + float frequency() const; std::uint32_t pid() const; std::string name() const; std::string decoder() const; diff --git a/src/openxc/message_set.cpp b/src/openxc/message_set.cpp index 7f3d2fbb..c47c45f8 100755 --- a/src/openxc/message_set.cpp +++ b/src/openxc/message_set.cpp @@ -30,7 +30,7 @@ namespace openxc return bit_numbering_inverted_; } - std::uint32_t message_set::max_message_frequency() const + float message_set::max_message_frequency() const { return max_message_frequency_; } @@ -60,7 +60,7 @@ namespace openxc return buses_; } - const std::map& message_set::messages() const + const std::vector& message_set::messages() const { return messages_; } @@ -84,25 +84,6 @@ namespace openxc { return commands_; } - - std::string message_set::to_initializer() const - { - std::uint32_t signal_count = 0; - for(const auto& m : messages_) - { - signal_count += m.second.get_signals_count(); - } - - std::stringstream ss; - ss << "{0, " - << "\"" << name_ << "\", " - << buses_.size() << ", " - << messages_.size() << ", " - << signal_count << ", " - << commands_.size() << ", " - << diagnostic_messages_.size() << "}"; - return ss.str(); - } void message_set::from_json(const nlohmann::json& j) { @@ -114,14 +95,25 @@ namespace openxc initializers_ = j.count("initializers") ? j["initializers"].get>() : std::vector(); loopers_ = j.count("loopers") ? j["loopers"].get>() : std::vector(); buses_ = j.count("buses") ? j["buses"].get>() : std::map(); - messages_ = j.count("messages") ? j["messages"].get>() : std::map(); + //messages_ = j.count("messages") ? j["messages"].get>() : std::map(); diagnostic_messages_ = j.count("diagnostic_messages") ? j["diagnostic_messages"].get>() : std::vector(); mappings_ = j.count("mappings") ? j["mappings"].get>() : std::vector(); extra_sources_ = j.count("extra_sources") ? j["extra_sources"].get>() : std::vector(); commands_ = j.count("commands") ? j["commands"].get>() : std::vector(); + + + if (j.count("messages")) + { + std::map messages = j["messages"]; + for(const std::map::value_type& m : messages) + { + can_message cm = m.second.get(); + cm.id(m.first); + messages_.push_back(cm); + } + } } - nlohmann::json message_set::to_json() const { nlohmann::json j; diff --git a/src/openxc/message_set.hpp b/src/openxc/message_set.hpp index 37b40fc4..935817ee 100755 --- a/src/openxc/message_set.hpp +++ b/src/openxc/message_set.hpp @@ -18,13 +18,14 @@ namespace openxc private: std::string name_; bool bit_numbering_inverted_; - std::uint32_t max_message_frequency_; + float max_message_frequency_; can_bus_mode raw_can_mode_; std::vector parents_; std::vector initializers_; std::vector loopers_; std::map buses_; - std::map messages_; + //std::map messages_; + std::vector messages_; std::vector diagnostic_messages_; std::vector mappings_; std::vector extra_sources_; @@ -37,20 +38,18 @@ namespace openxc std::string name() const; bool bit_numbering_inverted() const; - std::uint32_t max_message_frequency() const; + float max_message_frequency() const; can_bus_mode raw_can_mode() const; const std::vector& parents() const; const std::vector& initializers() const; const std::vector& loopers() const; const std::map& buses() const; - const std::map& messages() const; + const std::vector& messages() const; const std::vector& diagnostic_messages() const; const std::vector& mappings() const; const std::vector& extra_sources() const; const std::vector& commands() const; - std::string to_initializer() const; - void from_json(const nlohmann::json& j); nlohmann::json to_json() const; }; diff --git a/src/openxc/signal.cpp b/src/openxc/signal.cpp index 9406112c..6c3ff82a 100755 --- a/src/openxc/signal.cpp +++ b/src/openxc/signal.cpp @@ -2,6 +2,18 @@ namespace openxc { + std::string signal::id() const + { + return id_; + } + + void signal::id(const std::string& id) + { + id_ = id; + } + + void id(const std::string& id); + std::string signal::generic_name() const { return generic_name_; @@ -47,7 +59,7 @@ namespace openxc return states_; } - std::uint32_t signal::max_frequency() const + float signal::max_frequency() const { return max_frequency_; } diff --git a/src/openxc/signal.hpp b/src/openxc/signal.hpp index f4b6683b..64dba75e 100755 --- a/src/openxc/signal.hpp +++ b/src/openxc/signal.hpp @@ -11,6 +11,7 @@ namespace openxc class signal { private: + std::string id_; std::string generic_name_; std::uint32_t bit_position_; std::uint32_t bit_size_; @@ -20,12 +21,14 @@ namespace openxc bool ignore_; bool enabled_; std::map> states_; - std::uint32_t max_frequency_; + float max_frequency_; bool send_same_; bool force_send_changed_; bool writable_; std::string encoder_; public: + std::string id() const; + void id(const std::string& id); std::string generic_name() const; std::uint32_t bit_position() const; std::uint32_t bit_size() const; @@ -35,7 +38,7 @@ namespace openxc bool ignore() const; bool enabled() const; const std::map>& states() const; - std::uint32_t max_frequency() const; + float max_frequency() const; bool send_same() const; bool force_send_changed() const; bool writable() const; -- cgit