11#include " c-sigprinter.h"
22
3+ // work buffer for all snprintf operations
4+ static const size_t WBUFF_LEN =2048 ;
5+ static char workbuff[WBUFF_LEN] = {0 };
6+
7+ // additional templates for expression generation
8+ static std::string msk[] = {" 0" ," 0x01U" ," 0x03U" ," 0x07U" ," 0x0FU" ," 0x1FU" ," 0x3FU" ," 0x7FU" ," 0xFFU" };
9+
10+ static inline int32_t ShiftByte (const SignalDescriptor_t* sig,int32_t bn)
11+ {
12+ return (sig->Order == BitLayout::kIntel ) ? (bn -1 ) : (bn +1 );
13+ }
314
415CSigPrinter::CSigPrinter ()
516{
17+ sigs_expr.clear ();
618}
719
820CSigPrinter::~CSigPrinter ()
921{
22+ sigs_expr.clear ();
1023}
1124
1225void CSigPrinter::AddMessage (const std::vector<MessageDescriptor_t*> message)
@@ -29,12 +42,172 @@ void CSigPrinter::AddMessage(const MessageDescriptor_t& message)
2942// add them to dedicated members, set signal stdint type
3043// and push it to vector
3144
45+ BuildCConvertExprs (nexpr);
46+
3247 sigs_expr.push_back (nexpr);
3348}
3449
50+ // This function determines what type will have struct
51+ // field for the @signal. It saves the <stdint> name
3552std::stringCSigPrinter::GetSignalType (const SignalDescriptor_t& signal)
3653{
3754 std::string ret =" " ;
3855
3956return ret;
4057}
58+
59+ int32_t CSigPrinter::BuildCConvertExprs (CiExpr_t* msg)
60+ {
61+ int32_t ret =0 ;
62+ std::string tmpstr;
63+
64+ msg->to_bytes .clear ();
65+ msg->to_signals .clear ();
66+ msg->to_bytes .resize (msg->msg .DLC );
67+
68+ // for each signal specific to_signal expression must be defined,
69+ // and during all signals processing, for each byte to_byte expression
70+ // must be collected
71+
72+ for (size_t i =0 ; i < msg->msg .Signals .size (); i++)
73+ {
74+ // there are two main goal of this code:
75+ // 1 - to generate bytes to signal C-expression, (_d - name of array).
76+ // For each signal there is only one byte reference. It's generated
77+ // once each function call for each signal
78+ //
79+ // 2 - to generate signals to each byte expression, (_m - name of struct with
80+ // signals). For each byte a 8 signals can be referenced. It's generated
81+ // consequently signal after signal (by adding chunks of expressions to @to_bytes
82+ // collection)
83+ //
84+ // signal expression is saved to vector @to_signals, which id must be
85+ // fully correlated to id of target signal. the final size of
86+ // @to_signals vector must be equal to size of Signals vector
87+ //
88+ // bytes expression is saved to vector @to_bytes, where id is the
89+ // byte number in frame payload (i.e. to_bytes.size() == frame.DLC)
90+ msg->to_signals .push_back (PrintSignalExpr (&msg->msg .Signals [i], msg->to_bytes ));
91+ }
92+
93+ return ret;
94+ }
95+
96+ std::stringCSigPrinter::PrintSignalExpr (SignalDescriptor_t* sig,
97+ std::vector<std::string>& to_bytes)
98+ {
99+ // value for collecting expression (to_signal)
100+ std::string tosigexpr;
101+
102+ uint16_t startb = (uint16_t )((sig->Order == BitLayout::kIntel ) ?
103+ (sig->StartBit + (sig->LengthBit -1 )) : (sig->StartBit ));
104+
105+ if (startb >63 )
106+ startb =63 ;
107+
108+ int32_t bn = startb /8 ;
109+
110+ // set valid to_byte prefix
111+ int32_t bbc = (startb %8 ) +1 ;
112+ int32_t slen = sig->LengthBit ;
113+
114+ if (bbc > slen)
115+ {
116+ snprintf (workbuff, WBUFF_LEN," ((_d[%d] >> %d) & (%s))" , bn, bbc - slen, msk[slen].c_str ());
117+ tosigexpr += workbuff;
118+
119+ snprintf (workbuff, WBUFF_LEN," ((_m->{%s} & (%s)) << %d)" , sig->Name .c_str (), msk[slen].c_str (),
120+ bbc - slen);
121+ AppendToByteLine (to_bytes[bn], workbuff);
122+ }
123+ else if (bbc == slen)
124+ {
125+ // no rolling bits
126+ snprintf (workbuff, WBUFF_LEN," (_d[%d] & (%s))" , bn, msk[slen].c_str ());
127+ tosigexpr += workbuff;
128+
129+ snprintf (workbuff, WBUFF_LEN," (_m->%s & (%s))" , sig->Name .c_str (), msk[slen].c_str ());
130+ AppendToByteLine (to_bytes[bn], workbuff);
131+ }
132+ else
133+ {
134+ std::string t64 =" " ;
135+ slen -= bbc;
136+
137+ if (slen >31 )
138+ {
139+ t64 =" (uint64_t)" ;
140+ }
141+
142+ snprintf (workbuff, WBUFF_LEN," (%s_d[%d] & (%s)) << %d)" , t64.c_str (), bn, msk[bbc].c_str (), slen);
143+ tosigexpr += workbuff;
144+
145+ snprintf (workbuff, WBUFF_LEN," ((_m->%s >> %d) & (%s))" , sig->Name .c_str (), slen,
146+ msk[bbc].c_str ());
147+ AppendToByteLine (to_bytes[bn], workbuff);
148+
149+ while ((slen -8 ) >=0 )
150+ {
151+ t64.clear ();
152+
153+ slen -=8 ;
154+
155+ bn =ShiftByte (sig, bn);
156+
157+ tosigexpr +=" |" ;
158+
159+ if (slen ==0 )
160+ {
161+ // last byte is aligned
162+ snprintf (workbuff, WBUFF_LEN," (_d[%d] & (%s))" , bn, msk[8 ].c_str ());
163+ tosigexpr += workbuff;
164+
165+ snprintf (workbuff, WBUFF_LEN," (_m->%s & (%s))" , sig->Name .c_str (), msk[8 ].c_str ());
166+ AppendToByteLine (to_bytes[bn], workbuff);
167+
168+ }
169+ else
170+ {
171+ if (slen >31 )
172+ {
173+ t64 =" (uint64_t)" ;
174+ }
175+
176+ snprintf (workbuff, WBUFF_LEN," (%s(_d[%d] & (%s)) << %d)" , t64.c_str (), bn, msk[8 ].c_str (), slen);
177+ tosigexpr += workbuff;
178+
179+
180+ snprintf (workbuff, WBUFF_LEN," ((_m->%s >> %d) & (%s))" , sig->Name .c_str (), slen, msk[8 ].c_str ());
181+ AppendToByteLine (to_bytes[bn], workbuff);
182+ }
183+ }
184+
185+ if (slen >0 )
186+ {
187+ bn =ShiftByte (sig, bn);
188+
189+ snprintf (workbuff, WBUFF_LEN," | ((_d[%d] >> %d) & (%s))" , bn,8 - slen, msk[slen].c_str ());
190+ tosigexpr += workbuff;
191+
192+ snprintf (workbuff, WBUFF_LEN," ((_m->%s & (%s)) << %d)" , sig->Name .c_str (), msk[slen].c_str (),
193+ 8 - slen);
194+ AppendToByteLine (to_bytes[bn], workbuff);
195+ }
196+ }
197+
198+ return tosigexpr;
199+ }
200+
201+ void CSigPrinter::AppendToByteLine (std::string& expr, std::string str)
202+ {
203+ if (expr.size () >0 )
204+ {
205+ // Not first appendingF
206+ expr +=" |" + str;
207+ }
208+ else
209+ {
210+ // First appending
211+ expr = str;
212+ }
213+ }