Skip to content

Fix multiplex sig unpack #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
178 changes: 145 additions & 33 deletions src/codegen/c-main-generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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();");
Expand All @@ -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(),
Expand All @@ -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("{");
Expand All @@ -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(),
Expand Down Expand Up @@ -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("");
Expand All @@ -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();
}
}

}
4 changes: 3 additions & 1 deletion src/codegen/c-main-generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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;
};
Loading