diff --git a/src/app.cpp b/src/app.cpp index 4810d9b..1d464e8 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -145,7 +145,7 @@ void CoderApp::GenerateCode() if (ret) { - cigen.Generate(scanner.dblist, fscreator.FS); + cigen.Generate(scanner.dblist, fscreator.FS, Params.is_multiplex_enabled); } else { @@ -283,8 +283,8 @@ void CoderApp::PrintHelp() std::cout << " -nofmon:\t no ***-fmon.c generation" << std::endl; std::cout << std::endl; std::cout << " -driverdir\t the output path (-out) will be appended by driver name" << std::endl; - std::cout << " -gendate\t the generation date will be included in the header comment section of the source file." << - std::endl; + std::cout << " -gendate\t the generation date will be included in the header comment section of the source file." << std::endl; + std::cout << " -multiplex or -muxgen\t enable multiplex signal packing/unpacking code generation based on multiplexor master signal values for multiplexed signals." << std::endl; std::cout << std::endl; std::cout << "examples:" << std::endl; @@ -295,10 +295,7 @@ void CoderApp::PrintHelp() << std::endl; std::cout << "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils -rw" << std::endl; - - std::cout << - "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils" << std::endl; - + std::cout << "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb -nodeutils" << std::endl; std::cout << "./dbccoder -dbc /home/user/docs/driveshaft.dbc -out /home/user/docs/gen/ -drvname drivedb" << std::endl; std::cout << std::endl; } diff --git a/src/codegen/c-main-generator.cpp b/src/codegen/c-main-generator.cpp index dc9c5ae..b6440fa 100644 --- a/src/codegen/c-main-generator.cpp +++ b/src/codegen/c-main-generator.cpp @@ -31,8 +31,11 @@ const char* extend_func_body = " return ((val ^ m) - m);\n" "}\n\n"; -void CiMainGenerator::Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd) +void CiMainGenerator::Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd, bool mux_enabled) { + // set multiplexor master signal values is enabled for multiplexed signals + is_multiplex_enabled = mux_enabled; + // Load income messages to sig printer sigprt.LoadMessages(dlist.msgs); @@ -678,55 +681,106 @@ void CiMainGenerator::WriteSigStructField(const SignalDescriptor_t& sig, bool bi void CiMainGenerator::WriteUnpackBody(const CiExpr_t* sgs) { + // Find the master multiplex signal (if any) + const SignalDescriptor_t* masterSignal = nullptr; + size_t masterSignalIndex = 0; + for (size_t i = 0; i < sgs->msg.Signals.size(); ++i) + { + if (sgs->msg.Signals[i].Multiplex == MultiplexType::kMaster) + { + masterSignal = &sgs->msg.Signals[i]; + masterSignalIndex = i; + break; + } + } + + // If there's a master multiplex signal, unpack it first to get its value + if (masterSignal) + { + const char* masterSname = masterSignal->Name.c_str(); + auto masterExpr = sgs->to_signals[masterSignalIndex]; + fwriter.Append(" _m->%s = (%s) ( %s );", masterSname, + PrintType((int)masterSignal->TypeRo).c_str(), masterExpr.c_str()); + } + + // Unpack the rest of the signals for (size_t num = 0; num < sgs->to_signals.size(); num++) { + const auto& signal = sgs->msg.Signals[num]; auto expr = sgs->to_signals[num]; - // for code shortening - const char* sname = sgs->msg.Signals[num].Name.c_str(); + // Skip the master signal as we've already handled it + if (&signal == masterSignal) + { + continue; + } + + const char* sname = signal.Name.c_str(); - if (sgs->msg.Signals[num].Signed) + // Check if the signal is multiplexed + bool isMultiplexed = (signal.Multiplex == MultiplexType::kMulValue); + + // Generate the if statement only if multiplex is enabled + if (is_multiplex_enabled && isMultiplexed) + { + fwriter.Append(" if (_m->%s == %d) {", masterSignal->Name.c_str(), signal.MultiplexValue); + } + + // Set the indentation level based on whether the signal is multiplexed + const char* indent = (is_multiplex_enabled && isMultiplexed) ? " " : " "; + + // Unpack the signal + if (signal.Signed) { - fwriter.Append(" _m->%s = (%s) %s(( %s ), %d);", - sname, PrintType((int)sgs->msg.Signals[num].TypeRo).c_str(), - ext_sig_func_name, expr.c_str(), (int32_t)sgs->msg.Signals[num].LengthBit); + fwriter.Append("%s_m->%s = (%s) %s(( %s ), %d);", + indent, sname, PrintType((int)signal.TypeRo).c_str(), + ext_sig_func_name, expr.c_str(), (int32_t)signal.LengthBit); } else { - fwriter.Append(" _m->%s = (%s) ( %s );", sname, - PrintType((int)sgs->msg.Signals[num].TypeRo).c_str(), expr.c_str()); + fwriter.Append("%s_m->%s = (%s) ( %s );", indent, + sname, PrintType((int)signal.TypeRo).c_str(), expr.c_str()); } - // print sigfloat conversion - if (!sgs->msg.Signals[num].IsSimpleSig) + // Handle physical value conversion if needed + if (!signal.IsSimpleSig) { fwriter.Append("#ifdef %s", fdesc->gen.usesigfloat_def.c_str()); - if (sgs->msg.Signals[num].IsDoubleSig) + if (signal.IsDoubleSig) { - // for double signals (sigfloat_t) type cast - fwriter.Append(" _m->%s = (sigfloat_t)(%s_%s_fromS(_m->%s));", - sgs->msg.Signals[num].NameFloat.c_str(), fdesc->gen.DRVNAME.c_str(), sname, sname); + fwriter.Append("%s_m->%s = (sigfloat_t)(%s_%s_fromS(_m->%s));", + indent, signal.NameFloat.c_str(), fdesc->gen.DRVNAME.c_str(), sname, sname); } else { - fwriter.Append(" _m->%s = (%s) %s_%s_fromS(_m->%s);", - sgs->msg.Signals[num].NameFloat.c_str(), - PrintType((int)sgs->msg.Signals[num].TypePhys).c_str(), + fwriter.Append("%s_m->%s = (%s) %s_%s_fromS(_m->%s);", + indent, signal.NameFloat.c_str(), + PrintType((int)signal.TypePhys).c_str(), fdesc->gen.DRVNAME.c_str(), sname, sname); } fwriter.Append("#endif // %s", fdesc->gen.usesigfloat_def.c_str()); - fwriter.Append(); + fwriter.Append(""); } - else if (num + 1 == sgs->to_signals.size()) + // Close the if statement if the signal was multiplexed and if multiplexing is enabled + if (is_multiplex_enabled && isMultiplexed) { - // last signal without phys part, put \n manually - fwriter.Append(""); + fwriter.Append(" }"); + } + + // Add a newline after processing the last signal + if (num + 1 == sgs->to_signals.size()) + { + // No newline if the last signal was a multiplexed signal, as it already has a newline + if (signal.IsSimpleSig) { + fwriter.Append(""); + } } } + // Additional monitor and checksum logic, unchanged fwriter.Append("#ifdef %s", fdesc->gen.usemon_def.c_str()); fwriter.Append(" _m->mon1.dlc_error = (dlc_ < %s_DLC);", sgs->msg.Name.c_str()); fwriter.Append(" _m->mon1.last_cycle = GetSystemTick();"); @@ -735,20 +789,17 @@ void CiMainGenerator::WriteUnpackBody(const CiExpr_t* sgs) if (sgs->msg.RollSig != nullptr) { - // Put rolling monitor here fwriter.Append("#ifdef %s", fdesc->gen.useroll_def.c_str()); fwriter.Append(" _m->mon1.roll_error = (_m->%s != _m->%s_expt);", sgs->msg.RollSig->Name.c_str(), sgs->msg.RollSig->Name.c_str()); fwriter.Append(" _m->%s_expt = (_m->%s + 1) & (0x%02XU);", sgs->msg.RollSig->Name.c_str(), sgs->msg.RollSig->Name.c_str(), (1 << sgs->msg.RollSig->LengthBit) - 1); - // Put rolling monitor here fwriter.Append("#endif // %s", fdesc->gen.useroll_def.c_str()); fwriter.Append(); } if (sgs->msg.CsmSig != nullptr) { - // Put checksum check function call here fwriter.Append("#ifdef %s", fdesc->gen.usecsm_def.c_str()); fwriter.Append(" _m->mon1.csm_error = (((uint8_t)GetFrameHash(_d, %s_DLC, %s_CANID, %s, %d)) != (_m->%s));", sgs->msg.Name.c_str(), sgs->msg.Name.c_str(), sgs->msg.CsmMethod.c_str(), @@ -767,6 +818,7 @@ void CiMainGenerator::WriteUnpackBody(const CiExpr_t* sgs) fwriter.Append(" return %s_CANID;", sgs->msg.Name.c_str()); } + void CiMainGenerator::WritePackStructBody(const CiExpr_t* sgs) { fwriter.Append("{"); @@ -792,9 +844,9 @@ void CiMainGenerator::WritePackArrayBody(const CiExpr_t* sgs) void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExpr_t* sgs) { - // this function will print body of packing function + // this function will print the body of the packing function - // pring array content clearin loop + // print array content clearing loop fwriter.Append(" uint8_t i; for (i = 0u; i < %s(%s_DLC); %s[i++] = %s);", prt_dlcValidateMacroName.c_str(), sgs->msg.Name.c_str(), arrtxt.c_str(), @@ -842,14 +894,75 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp fwriter.Append(); } - for (size_t i = 0; i < sgs->to_bytes.size(); i++) + // Find the master multiplex signal (if any) + const SignalDescriptor_t* masterSignal = nullptr; + for (const auto& sig : sgs->msg.Signals) { - if (sgs->to_bytes[i].size() < 2) + if (sig.Multiplex == MultiplexType::kMaster) { - continue; + masterSignal = &sig; + break; } + } - fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str()); + // Generate packing code for each byte in the CAN message + for (size_t i = 0; i < sgs->to_bytes.size(); i++) + { + if (is_multiplex_enabled && masterSignal) + { + bool first = true; + // Handle the case where only a master multiplexor signal exists and there are no other kMulValue signal types in the CAN msg. + // There may or may not be other normal signals in the CAN msg. + if (sgs->mux_values.size() == 0) + { + // Filter out any empty bytes in the CAN msg. + if ( !sgs->to_bytes[i].empty() ) + { + fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str()); + } + } + else + { + // handle the case where there is a mux master and kMulValue (and other normal signals) in the CAN msg. + for (size_t mux_idx = 0; mux_idx < sgs->mux_values.size(); ++mux_idx) + { + int mux_val = sgs->mux_values[mux_idx]; + if (sgs->to_bytes_mux[i].size() > mux_idx && !sgs->to_bytes_mux[i][mux_idx].empty()) + { + if (first) + { + fwriter.Append(" if (_m->%s == %d) {", masterSignal->Name.c_str(), mux_val); + first = false; + } + else + { + fwriter.Append(" else if (_m->%s == %d) {", masterSignal->Name.c_str(), mux_val); + } + fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes_mux[i][mux_idx].c_str()); + fwriter.Append(" }"); + } + } + // Add the final else block for the case where no expected multiplex value matches. Just encode all signals in the byte. + if (!first) + { + fwriter.Append(" else {"); + if ( !sgs->to_bytes[i].empty() ) + { + fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str()); + } + fwriter.Append(" }"); + } + } + } + else + { + // Handle for when there is no master multiplexor signal or when multiplexing is disabled. + // Just pack the signal values from all signals making up this byte. + if ( !sgs->to_bytes[i].empty() ) + { + fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str()); + } + } } fwriter.Append(""); @@ -868,5 +981,4 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp fwriter.Append("#endif // %s", fdesc->gen.usecsm_def.c_str()); fwriter.Append(); } -} - +} \ No newline at end of file diff --git a/src/codegen/c-main-generator.h b/src/codegen/c-main-generator.h index 33cbc96..c56edc4 100644 --- a/src/codegen/c-main-generator.h +++ b/src/codegen/c-main-generator.h @@ -10,7 +10,7 @@ class CiMainGenerator { public: - void Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd); + void Generate(DbcMessageList_t& dlist, const AppSettings_t& fsd, bool mux_enabled); private: @@ -39,4 +39,6 @@ class CiMainGenerator { // Macro for frame DLC validation std::string prt_dlcValidateMacroName; const AppSettings_t* fdesc; + // Bool to turn on or off code generation based on multiplexor master signal values is enabled for multiplexed signals. + bool is_multiplex_enabled; }; diff --git a/src/codegen/c-sigprinter.cpp b/src/codegen/c-sigprinter.cpp index 3ea51cd..3bb53b4 100644 --- a/src/codegen/c-sigprinter.cpp +++ b/src/codegen/c-sigprinter.cpp @@ -1,5 +1,6 @@ #include #include +#include // For std::find #include "c-sigprinter.h" #include "helpers/formatter.h" #include "conf-and-limits.h" @@ -42,6 +43,9 @@ void CSigPrinter::LoadMessage(const MessageDescriptor_t& message) nexpr->msg = message; + // Find the multiplexor master signal in the message + FindMultiplexorValues(message, nexpr->mux_values); + // do for this new expr to_byte and to_field expression building, // add them to dedicated members, set signal stdint type // and push it to vector @@ -130,7 +134,14 @@ int32_t CSigPrinter::BuildCConvertExprs(CiExpr_t* msgprinter) msgprinter->to_bytes.clear(); msgprinter->to_signals.clear(); + msgprinter->to_bytes_mux.clear(); msgprinter->to_bytes.resize(msgprinter->msg.DLC); + // Resize the to_bytes_mux vector to the number of bytes in the message for the first dimension + // and the number of multiplexor values msgprinter->mux_values.size() for the second dimension. + for (size_t i = 0; i < msgprinter->msg.DLC; i++) + { + msgprinter->to_bytes_mux.push_back(std::vector(msgprinter->mux_values.size())); + } // for each signal specific to_signal expression must be defined, // and during all signals processing, for each byte to_byte expression @@ -154,22 +165,35 @@ int32_t CSigPrinter::BuildCConvertExprs(CiExpr_t* msgprinter) // // bytes expression is saved to vector @to_bytes, where id is the // byte number in frame payload (i.e. to_bytes.size() == frame.DLC) - msgprinter->to_signals.push_back(PrintSignalExpr(&msgprinter->msg.Signals[i], msgprinter->to_bytes)); + msgprinter->to_signals.push_back(PrintSignalExpr(&msgprinter->msg.Signals[i], msgprinter->mux_values, msgprinter->to_bytes, msgprinter->to_bytes_mux)); } if (msgprinter->msg.CsmSig != nullptr) { std::vector v(8); + std::vector> v2(8); + // resize the v2 vector to the number of multiplex values + for (size_t i = 0; i < 8; i++) + { + v2[i].resize(msgprinter->mux_values.size()); + } - PrintSignalExpr(msgprinter->msg.CsmSig, v); + PrintSignalExpr(msgprinter->msg.CsmSig, msgprinter->mux_values, v, v2); for (uint8_t i = 0; i < v.size() && i < 8; i++) { - if (v[i].size() > 0) + // As long as the checksum signal is not a multiplex signal. + if (msgprinter->msg.CsmSig->Multiplex != MultiplexType::kMulValue) { - msgprinter->msg.CsmToByteExpr = v[i]; - msgprinter->msg.CsmByteNum = i; - break; + if (v[i].size() > 0) + { + msgprinter->msg.CsmToByteExpr = v[i]; + msgprinter->msg.CsmByteNum = i; + break; + } + } else { + printf("Error in DBC file !!!! Checksum signal cannot be a multiplexor signal."); + ret = -1; } } } @@ -177,14 +201,14 @@ int32_t CSigPrinter::BuildCConvertExprs(CiExpr_t* msgprinter) return ret; } -std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vector& to_bytes) +std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, const std::vector mux_values, std::vector& to_bytes, std::vector>& to_bytes_mux) { // value for collecting expression (to_signal) std::string tosigexpr; if (to_bytes.size() == 0) { - // return empty line is bytes count somehow equals 0 + // return empty line if bytes count somehow equals 0 return "Error in DBC file !!!! Dlc of this message must be greater."; } @@ -206,9 +230,20 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec return to_bytes[0]; } + // Find the multiplexor index if the signal is multiplexed + int mux_ind = -1; + if (sig->Multiplex == MultiplexType::kMulValue) + { + auto it = std::find(mux_values.begin(), mux_values.end(), sig->MultiplexValue); + if (it != mux_values.end()) + { + mux_ind = std::distance(mux_values.begin(), it); + } + } + // set valid to_byte prefix - int32_t bbc = (startb % 8) + 1; - int32_t slen = sig->LengthBit; + int32_t bbc = (startb % 8) + 1; // Byte bit + int32_t slen = sig->LengthBit; // Signal length in bits if (bbc > slen) { @@ -217,6 +252,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec snprintf(workbuff, WBUFF_LEN, "((_m->%s & (%s)) << %dU)", sig->Name.c_str(), msk[slen].c_str(), bbc - slen); AppendToByteLine(to_bytes[bn], workbuff); + + AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff); } else if (bbc == slen) { @@ -226,6 +263,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec snprintf(workbuff, WBUFF_LEN, "(_m->%s & (%s))", sig->Name.c_str(), msk[slen].c_str()); AppendToByteLine(to_bytes[bn], workbuff); + + AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff); } else { @@ -243,6 +282,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec snprintf(workbuff, WBUFF_LEN, "((_m->%s >> %dU) & (%s))", sig->Name.c_str(), slen, msk[bbc].c_str()); AppendToByteLine(to_bytes[bn], workbuff); + AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff); + while ((slen - 8) >= 0) { t64.clear(); @@ -270,6 +311,7 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec snprintf(workbuff, WBUFF_LEN, "(_m->%s & (%s))", sig->Name.c_str(), msk[8].c_str()); AppendToByteLine(to_bytes[bn], workbuff); + AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff); } else { @@ -283,6 +325,8 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec snprintf(workbuff, WBUFF_LEN, "((_m->%s >> %dU) & (%s))", sig->Name.c_str(), slen, msk[8].c_str()); AppendToByteLine(to_bytes[bn], workbuff); + + AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff); } } @@ -293,15 +337,32 @@ std::string CSigPrinter::PrintSignalExpr(const SignalDescriptor_t* sig, std::vec snprintf(workbuff, WBUFF_LEN, " | ((_d[%d] >> %dU) & (%s))", bn, 8 - slen, msk[slen].c_str()); tosigexpr += workbuff; - snprintf(workbuff, WBUFF_LEN, "((_m->%s & (%s)) << %dU)", sig->Name.c_str(), msk[slen].c_str(), - 8 - slen); + snprintf(workbuff, WBUFF_LEN, "((_m->%s & (%s)) << %dU)", sig->Name.c_str(), msk[slen].c_str(), 8 - slen); AppendToByteLine(to_bytes[bn], workbuff); + + AppendToAllMuxValues(to_bytes_mux[bn], mux_ind, workbuff); } } return tosigexpr; } +void CSigPrinter::AppendToAllMuxValues(std::vector& to_bytes_mux, int mux_ind, const std::string& workbuff) +{ + if (mux_ind >= 0) + { + AppendToByteLine(to_bytes_mux[mux_ind], workbuff); + } + else + { + // Append to all multiplexor values if the signal is not multiplexed + for (size_t i = 0; i < to_bytes_mux.size(); ++i) + { + AppendToByteLine(to_bytes_mux[i], workbuff); + } + } +} + void CSigPrinter::AppendToByteLine(std::string& expr, std::string str) { if (expr.size() > 0) @@ -315,3 +376,41 @@ void CSigPrinter::AppendToByteLine(std::string& expr, std::string str) expr = str; } } + +void CSigPrinter::FindMultiplexorValues(const MessageDescriptor_t& message, std::vector& mux_values) +{ + // Clear the vectors to ensure they are empty before filling them + mux_values.clear(); + + // First, find the master multiplexor signal + SignalDescriptor_t* master_signal = nullptr; + for (const auto& signal : message.Signals) + { + if (signal.Multiplex == MultiplexType::kMaster) + { + master_signal = const_cast(&signal); + break; + } + } + + // If there's no master multiplexor signal, return + if (!master_signal) + { + return; + } + + // Now find all multiplex values + for (const auto& signal : message.Signals) + { + if (signal.Multiplex == MultiplexType::kMulValue) + { + // Extract and add to the list of total possible multiplex values for the CAN message. + int mux_value = signal.MultiplexValue; // Extract the multiplexor value this signal corresponds to + // If the multiplexor value is not already in the list, add it + if (std::find(mux_values.begin(), mux_values.end(), mux_value) == mux_values.end()) + { + mux_values.push_back(mux_value); + } + } + } +} \ No newline at end of file diff --git a/src/codegen/c-sigprinter.h b/src/codegen/c-sigprinter.h index 7f19b8b..a7094b0 100644 --- a/src/codegen/c-sigprinter.h +++ b/src/codegen/c-sigprinter.h @@ -18,8 +18,11 @@ class CSigPrinter { private: int32_t BuildCConvertExprs(CiExpr_t* msg); - std::string PrintSignalExpr(const SignalDescriptor_t* sig, std::vector& to_bytes); + std::string PrintSignalExpr(const SignalDescriptor_t* sig, const std::vector mux_values, std::vector& to_bytes, std::vector>& to_bytes_mux); + + void AppendToAllMuxValues(std::vector& to_bytes_mux, int mux_ind, const std::string& workbuff); void AppendToByteLine(std::string& expr, std::string str); + void FindMultiplexorValues(const MessageDescriptor_t& message, std::vector& mux_values); }; diff --git a/src/options-parser.cpp b/src/options-parser.cpp index ee77391..499569d 100644 --- a/src/options-parser.cpp +++ b/src/options-parser.cpp @@ -86,6 +86,10 @@ OptionsParser::GenOptions OptionsParser::GetOptions(int argc, char** argv) { retpairs.add_gen_date = true; } + else if (temppairs[i].first.compare("-multiplex") == 0 || temppairs[i].first.compare("-muxgen") == 0) + { + retpairs.is_multiplex_enabled = true; + } } return retpairs; diff --git a/src/options-parser.h b/src/options-parser.h index d2b1c8d..aaa800d 100644 --- a/src/options-parser.h +++ b/src/options-parser.h @@ -48,6 +48,9 @@ class OptionsParser { /// @brief help is requested bool is_help{false}; + + /// @brief Code generation based on multiplexor master signal values is enabled for multiplexed signals. + bool is_multiplex_enabled{false}; }; /// @brief Parses arguments and theirs optional values diff --git a/src/parser/dbclineparser.cpp b/src/parser/dbclineparser.cpp index d676f16..8703c8d 100644 --- a/src/parser/dbclineparser.cpp +++ b/src/parser/dbclineparser.cpp @@ -212,6 +212,9 @@ bool DbcLineParser::ParseSignalLine(SignalDescriptor_t* sig, const std::string& else { sig->Multiplex = MultiplexType::kMulValue; + // Multiplex value e.g m0, m1, m2... + // Convert to integer + sig->MultiplexValue = atoi(halfs[2].c_str() + 1); } } } diff --git a/src/types/c-expr.h b/src/types/c-expr.h index 996cca8..25f0a48 100644 --- a/src/types/c-expr.h +++ b/src/types/c-expr.h @@ -18,4 +18,19 @@ typedef struct // frame fields to data bytes std::vector to_bytes; + // another field containing expressions for converting + // frame fields to data bytes, but includes a different expression + // for each potential multiplexor value. + // i.e if the master multiplexor signal is 0, the first expression + // should be used, if it is 1, the second expression is used, etc. + // First dimension is the byte index, second dimension is the multiplexor value. + std::vector> to_bytes_mux; + // Store the corresponding multiplexor values for each expression + // since multiplexor values are not necessarily contiguous, we need + // to store the values explicitly. This vector should have the same + // size as the second dim of the to_bytes_mux and each element corresponds to the multiplexor + // value for the corresponding expression in to_bytes_mux. + // i.e to_bytes_mux[0 to 7].size() == mux_values.size() + std::vector mux_values; + } CiExpr_t; \ No newline at end of file diff --git a/src/types/message.h b/src/types/message.h index 275b9fc..fe284c0 100644 --- a/src/types/message.h +++ b/src/types/message.h @@ -91,6 +91,8 @@ typedef struct MultiplexType Multiplex; + uint32_t MultiplexValue; + } SignalDescriptor_t; typedef struct diff --git a/test/testdb2.dbc b/test/testdb2.dbc new file mode 100644 index 0000000..edb2890 --- /dev/null +++ b/test/testdb2.dbc @@ -0,0 +1,109 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: MCU VMU + + +BO_ 1096 MUX_SIG_TEST1: 8 MCU + SG_ mux8_sig1 m8 : 8|8@1+ (1,0) [1|3] "" VMU + SG_ mux8_sig2 m8 : 16|15@1+ (0.125,0) [0|4090] "V" VMU + SG_ mux7_sig1 m7 : 8|8@1+ (1,0) [1|3] "" VMU + SG_ mux7_sig2 m7 : 16|15@1+ (0.125,0) [0|4090] "V" VMU + SG_ mux6_sig1 m6 : 8|48@1+ (1,0) [0|0] "" VMU + SG_ mux0_sig1 m0 : 32|8@1+ (1,0) [0|0] "" VMU + SG_ mux0_sig2 m0 : 24|8@1+ (1,0) [0|0] "" VMU + SG_ mux5_sig1 m5 : 8|48@1+ (1,0) [0|0] "" VMU + SG_ mux4_sig4 m4 : 8|32@1+ (1,0) [0|0] "" VMU + SG_ mux4_sig3 m3 : 24|16@1+ (1,0) [0|0] "" VMU + SG_ mux0_sig3 m0 : 16|8@1+ (1,0) [0|0] "" VMU + SG_ mux0_sig4 m0 : 8|8@1+ (1,0) [0|0] "" VMU + SG_ mux2_sig1 m2 : 8|16@1+ (1,-32767) [0|32760] "RPM" VMU + SG_ mux1_sig1 m1 : 8|15@1+ (0.125,0) [0|4090] "Nm" VMU + SG_ mux3_sig1 m3 : 16|8@1+ (1,0) [0|0] "" VMU + SG_ mux3_sig2 m3 : 8|8@1+ (1,0) [0|0] "" VMU + SG_ mux_master M : 0|7@1+ (1,0) [0|0] "" VMU + SG_ signal1 : 7|1@1+ (1,0) [0|0] "" VMU + +BO_ 1091 SIG_TEST1: 5 MCU + SG_ signal1 : 36|4@1+ (1,0) [0|15] "" VMU + SG_ signal2 : 0|16@1+ (1,0) [0|65535] "" VMU + +BO_ 66 MUX_SIG_TEST2: 5 VMU + SG_ mux4_sig1 m4 : 16|16@1+ (1,-32767) [4294934536|32760] "RPM" Vector__XXX + SG_ mux4_sig2 m4 : 0|16@1+ (0.125,-4096) [4294963206|4090] "Nm" Vector__XXX + SG_ mux1_sig1 m1 : 0|16@1+ (0.125,-4096) [4294963206|4090] "Nm" MCU + SG_ mux3_sig3 m3 : 0|16@1+ (0.125,-4096) [0|4090] "V" MCU + SG_ signal1 : 36|4@1+ (1,0) [0|15] "" MCU + SG_ mux2_sig1 m2 : 16|16@1+ (1,-32767) [4294934536|32760] "RPM" MCU + SG_ mux_master M : 32|3@1+ (1,0) [1|7] "" MCU + +BO_ 65 MUX_SIG_TEST3: 6 VMU + SG_ signal1 : 6|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ max_master M : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ mux1_sig1 m1 : 3|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ signal2 : 5|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ signal3 : 24|16@1+ (1,-32767) [4294934536|32760] "RPM" Vector__XXX + SG_ mux1_sig2 m1 : 8|16@1+ (0.125,-4096) [4294963206|4090] "Nm" Vector__XXX + SG_ mux0_sig1 m0 : 6|1@1+ (1,0) [0|0] "" MCU + SG_ mux0_sig2 m0 : 8|16@1+ (0.125,-4096) [0|4090] "V" MCU + SG_ mux0_sig3 m0 : 3|2@1+ (1,0) [1|3] "" MCU + SG_ signal4 : 44|4@1+ (1,0) [0|15] "" MCU + SG_ mux0_sig4 m0 : 8|16@1+ (0.125,-4096) [4294963206|4090] "Nm" MCU + SG_ signal5 : 0|3@1+ (1,0) [0|3] "" MCU + +BO_ 1093 SIG_TEST2: 3 MCU + SG_ mux_master M : 0|7@1+ (1,0) [0|127] "" VMU + + + +BA_DEF_ EV_ "Version" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "Version" "1.0"; +BA_DEF_DEF_ "BusType" ""; +BA_ "BusType" "CAN"; +VAL_ 1096 mux8_sig1 1 "Mode1" 2 "Mode2" 3 "Mode3" ; +VAL_ 1096 mux7_sig1 1 "Mode1" 2 "Mode2" 3 "Mode3" ; +VAL_ 1096 mux_master 0 "Mode0" 1 "Mode1" 2 "Mode2" 3 "Mode3" 4 "Mode4" 5 "Mode5" 6 "Mode6" 7 "Mode7" 8 "Mode8" ; +VAL_ 1096 signal1 0 "Mode0" 1 "Mode1" ; +VAL_ 66 mux_master 1 "Mode1" 2 "Mode2" 3 "Mode3" 4 "Mode4" 5 "Reserved" 6 "Reserved" 7 "Reserved" ; +VAL_ 65 signal1 0 "mode0" 1 "mode1" ; +VAL_ 65 max_master 1 "ON" 0 "OFF" ; +VAL_ 65 mux1_sig1 1 "Mode1" ; +VAL_ 65 signal2 0 "mode0" 1 "mode1" ; +VAL_ 65 mux0_sig1 1 "invalid" 0 "valid" ; +VAL_ 65 mux0_sig3 1 "mode1" 2 "mode2" 3 "mode3" ; +VAL_ 65 signal5 0 "mode0" 1 "mode1" 3 "mode3" 4 "mode4" ; +VAL_ 1093 mux_master 0 "mode0" ; +