diff --git a/src/codegen/c-main-generator.cpp b/src/codegen/c-main-generator.cpp index dc9c5ae..a372d03 100644 --- a/src/codegen/c-main-generator.cpp +++ b/src/codegen/c-main-generator.cpp @@ -794,7 +794,7 @@ void CiMainGenerator::PrintPackCommonText(const std::string& arrtxt, const CiExp { // this function will print body of 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 +842,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; } + } + + // Generate packing code for each byte in the CAN message + for (size_t i = 0; i < sgs->to_bytes.size(); i++) + { - fwriter.Append(" %s[%d] |= (uint8_t) ( %s );", arrtxt.c_str(), i, sgs->to_bytes[i].c_str()); + if (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. 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 +929,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-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/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" ; +