GCC Code Coverage Report


Directory: ./
File: firmware/libfirmware/sent/src/sent_decoder.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 89.1% 196 0 220
Functions: 100.0% 16 0 16
Branches: 83.0% 93 0 112
Decisions: 81.8% 72 - 88

Line Branch Decision Exec Source
1 /*
2 * sent_decoder.cpp
3 *
4 * SENT protocol decoder
5 *
6 * TODO support MAF sensors like 04E906051 see https://github.com/rusefi/rusefi-hardware/issues/146
7 *
8 * @date Oct 01, 2022
9 * @author Andrey Gusakov <dron0gus@gmail.com>, (c) 2022-2024
10 */
11
12 #include <stddef.h>
13 #include "sent_decoder.h"
14
15 /*==========================================================================*/
16 /* Misc helpers. */
17 /*==========================================================================*/
18 #define BIT(n) (UINT32_C(1) << (n))
19
20 /*==========================================================================*/
21 /* Protocol definitions. */
22 /*==========================================================================*/
23
24 /* Signals only */
25 #define SENT_MSG_DATA_SIZE 6
26 /* Status + two 12-bit signals + CRC: 8 pulses */
27 #define SENT_MSG_PAYLOAD_SIZE (1 + SENT_MSG_DATA_SIZE + 1) // Size of payload
28 /* Sync + Status + Signals + CRC: 9 pulses */
29 #define SENT_MSG_TOTAL (1 + SENT_MSG_PAYLOAD_SIZE)
30
31 #define SENT_OFFSET_INTERVAL 12
32 #define SENT_SYNC_INTERVAL (56 - SENT_OFFSET_INTERVAL) // 56 ticks - 12
33
34 #define SENT_MIN_INTERVAL 12
35 #define SENT_MAX_INTERVAL 15
36
37 #define SENT_CRC_SEED 0x05
38
39 /* use 3 full frames + one additional pulse for unit time calibration */
40 #define SENT_CALIBRATION_PULSES (1 + 3 * SENT_MSG_PAYLOAD_SIZE)
41
42 /*==========================================================================*/
43 /* Decoder configuration */
44 /*==========================================================================*/
45
46 /*==========================================================================*/
47 /* Decoder */
48 /*==========================================================================*/
49
50 /* Helpers for Msg manipulations */
51 /* nibbles order: status, sig0_MSN, sig0_MidN, sig0_LSN, sig1_MSN, sig1_MidN, sig1_LSN, CRC */
52 /* we shift rxReg left for 4 bits on each nibble received and put newest nibble
53 * in [3:0] bits of rxReg, so when full message is received:
54 * CRC is [3:0] - nibble 7
55 * status is [31:28] - nibble 0
56 * sig0 is [27:16], sig1 is [15:4] */
57 #define MsgGetNibble(msg, n) (((msg) >> (4 * (7 - (n)))) & 0xf)
58 #define MsgGetStat(msg) MsgGetNibble(msg, 0)
59 #define MsgGetSig0(msg) (((msg) >> (4 * 4)) & 0xfff)
60 #define MsgGetSig1(msg) (((msg) >> (1 * 4)) & 0xfff)
61 #define MsgGetCrc(msg) MsgGetNibble(msg, 7)
62
63 /* convert CPU ticks to float Us */
64 #define TicksToUs(ticks) ((float)(ticks) * 1000.0 * 1000.0 / CORE_CLOCK)
65
66 2 void sent_channel::restart() {
67 2 state = SENT_STATE_CALIB;
68 2 pulseCounter = 0;
69 2 currentStatePulseCounter = 0;
70 2 pausePulseReceived = false;
71 2 tickPerUnit = 0;
72
73 /* reset slow channels */
74 2 SlowChannelDecoderReset();
75
76 #if SENT_STATISTIC_COUNTERS
77 2 statistic.ShortIntervalErr = 0;
78 2 statistic.LongIntervalErr = 0;
79 2 statistic.SyncErr = 0;
80 2 statistic.CrcErrCnt = 0;
81 2 statistic.FrameCnt = 0;
82 2 statistic.PauseCnt = 0;
83 2 statistic.sc12 = 0;
84 2 statistic.sc16 = 0;
85 2 statistic.scCrcErr = 0;
86 2 statistic.RestartCnt++;
87 #endif
88 2 }
89
90 16407 void sent_channel::calcTickPerUnit(uint32_t clocks) {
91 /* int division with rounding */
92 16407 tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
93 (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
94 16407 }
95
96 147580 float sent_channel::getTickTime() {
97 147580 return tickPerUnit;
98 }
99
100 33594 bool sent_channel::isSyncPulse(uint32_t clocks)
101 {
102 /* check if pulse looks like sync with allowed +/-20% deviation */
103 33594 uint32_t syncClocks = (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) * tickPerUnit;
104
105
2/2
✓ Branch 0 taken 21486 times.
✓ Branch 1 taken 12108 times.
2/2
✓ Decision 'true' taken 16343 times.
✓ Decision 'false' taken 17251 times.
33594 if (((100 * clocks) >= (syncClocks * 80)) &&
106
2/2
✓ Branch 0 taken 16343 times.
✓ Branch 1 taken 5143 times.
21486 ((100 * clocks) <= (syncClocks * 120)))
107 16343 return 1;
108
109 17251 return 0;
110 }
111
112 147571 int sent_channel::FastChannelDecoder(uint32_t clocks) {
113 147571 pulseCounter++;
114
115 /* special case - tick time calculation */
116
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 147414 times.
2/2
✓ Decision 'true' taken 157 times.
✓ Decision 'false' taken 147414 times.
147571 if (state == SENT_STATE_CALIB) {
117
3/4
✓ Branch 0 taken 145 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 145 times.
2/2
✓ Decision 'true' taken 12 times.
✓ Decision 'false' taken 145 times.
157 if ((tickPerUnit == 0) || (currentStatePulseCounter == 0)) {
118 /* invalid or not yet calculated tickPerUnit */
119 12 calcTickPerUnit(clocks);
120 /* lets assume this is sync pulse... */
121 12 currentStatePulseCounter = 1;
122 } else {
123 /* some tickPerUnit calculated...
124 * Check next 1 + 6 + 1 pulses if they are valid with current tickPerUnit */
125 145 int checkInterval = (clocks + tickPerUnit / 2) / tickPerUnit - SENT_OFFSET_INTERVAL;
126
4/4
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 93 times.
✓ Branch 3 taken 51 times.
2/2
✓ Decision 'true' taken 93 times.
✓ Decision 'false' taken 52 times.
145 if ((checkInterval >= 0) && (checkInterval <= SENT_MAX_INTERVAL)) {
127 93 currentStatePulseCounter++;
128 /* Should end up with CRC pulse */
129
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 82 times.
2/2
✓ Decision 'true' taken 11 times.
✓ Decision 'false' taken 82 times.
93 if (currentStatePulseCounter == (1 + SENT_MSG_PAYLOAD_SIZE)) {
130 11 pulseCounter = 0;
131 11 currentStatePulseCounter = 0;
132 11 state = SENT_STATE_INIT;
133 }
134 } else {
135 52 currentStatePulseCounter = 1;
136 52 calcTickPerUnit(clocks);
137 }
138 }
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 157 times.
157 if (pulseCounter >= SENT_CALIBRATION_PULSES) {
140 /* failed to calculate valid tickPerUnit, restart */
141 restart();
142 }
143 157 return 0;
144 }
145
146 /* special case for out-of-sync state */
147
2/2
✓ Branch 0 taken 1892 times.
✓ Branch 1 taken 145522 times.
2/2
✓ Decision 'true' taken 1892 times.
✓ Decision 'false' taken 145522 times.
147414 if (state == SENT_STATE_INIT) {
148
2/2
✓ Branch 1 taken 326 times.
✓ Branch 2 taken 1566 times.
2/2
✓ Decision 'true' taken 326 times.
✓ Decision 'false' taken 1566 times.
1892 if (isSyncPulse(clocks)) {
149 /* adjust unit time */
150 326 calcTickPerUnit(clocks);
151 /* we get here from calibration phase. calibration phase end with CRC nibble
152 * if we had to skip ONE pulse before we get sync - that means device may send pause
153 * pulse in between of messages */
154 326 pausePulseReceived = false;
155
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 298 times.
2/2
✓ Decision 'true' taken 28 times.
✓ Decision 'false' taken 298 times.
326 if (currentStatePulseCounter == 1) {
156 28 pausePulseReceived = true;
157 }
158 /* next state */
159 326 currentStatePulseCounter = 0;
160 326 state = SENT_STATE_STATUS;
161 } else {
162 1566 currentStatePulseCounter++;
163 /* 3 frames skipped, no SYNC detected - recalibrate */
164
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1564 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1564 times.
1566 if (currentStatePulseCounter >= (SENT_MSG_TOTAL * 3)) {
165 2 restart();
166 }
167 }
168 /* done for this pulse */
169 1892 return 0;
170 }
171
172 145522 int interval = (clocks + tickPerUnit / 2) / tickPerUnit - SENT_OFFSET_INTERVAL;
173
174
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 145243 times.
2/2
✓ Decision 'true' taken 279 times.
✓ Decision 'false' taken 145243 times.
145522 if (interval < 0) {
175 #if SENT_STATISTIC_COUNTERS
176 279 statistic.ShortIntervalErr++;
177 #endif //SENT_STATISTIC_COUNTERS
178 279 state = SENT_STATE_INIT;
179 279 return -1;
180 }
181
182
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 20250 times.
✓ Branch 2 taken 16310 times.
✓ Branch 3 taken 108683 times.
✗ Branch 4 not taken.
145243 switch(state)
183 {
184 case SENT_STATE_CALIB:
185 case SENT_STATE_INIT:
186 /* handled above, should not get in here */
187 return -1;
188
189
1/1
✓ Decision 'true' taken 20250 times.
20250 case SENT_STATE_SYNC:
190
2/2
✓ Branch 1 taken 15374 times.
✓ Branch 2 taken 4876 times.
2/2
✓ Decision 'true' taken 15374 times.
✓ Decision 'false' taken 4876 times.
20250 if (isSyncPulse(clocks))
191 {
192 /* measured tick interval will be used until next sync pulse */
193 15374 calcTickPerUnit(clocks);
194 15374 rxReg = 0;
195 15374 state = SENT_STATE_STATUS;
196 }
197 else
198 {
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4876 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 4876 times.
4876 if (pausePulseReceived) {
200 #if SENT_STATISTIC_COUNTERS
201 // Increment sync interval err count
202 statistic.SyncErr++;
203 if (interval > SENT_SYNC_INTERVAL)
204 {
205 statistic.LongIntervalErr++;
206 }
207 else
208 {
209 statistic.ShortIntervalErr++;
210 }
211 #endif // SENT_STATISTIC_COUNTERS
212 /* wait for next sync and recalibrate tickPerUnit */
213 state = SENT_STATE_INIT;
214 return -1;
215 } else {
216 /* This is possibly pause pulse */
217 /* TODO: check:
218 * Minimum Length 12 ticks (equivalent to a nibble with 0 value) - this is already checked
219 * Maximum Length 768 ticks (3 * 256) */
220 #if SENT_STATISTIC_COUNTERS
221 4876 statistic.PauseCnt++;
222 #endif // SENT_STATISTIC_COUNTERS
223 4876 pausePulseReceived = true;
224 }
225 }
226 20250 return 0;
227
228
1/1
✓ Decision 'true' taken 16310 times.
16310 case SENT_STATE_STATUS:
229 /* it is possible that pause pulse was threaded as sync and we are here with sync pulse */
230
6/6
✓ Branch 0 taken 11452 times.
✓ Branch 1 taken 4858 times.
✓ Branch 3 taken 643 times.
✓ Branch 4 taken 10809 times.
✓ Branch 5 taken 643 times.
✓ Branch 6 taken 15667 times.
2/2
✓ Decision 'true' taken 643 times.
✓ Decision 'false' taken 15667 times.
16310 if ((pausePulseReceived == false) && isSyncPulse(clocks)) {
231 #if SENT_STATISTIC_COUNTERS
232 643 statistic.PauseCnt++;
233 #endif // SENT_STATISTIC_COUNTERS
234 /* measured tick interval will be used until next sync pulse */
235 643 calcTickPerUnit(clocks);
236 643 return 0;
237 }
238 // fallthrough
239 case SENT_STATE_SIG1_DATA1:
240 case SENT_STATE_SIG1_DATA2:
241 case SENT_STATE_SIG1_DATA3:
242 case SENT_STATE_SIG2_DATA1:
243 case SENT_STATE_SIG2_DATA2:
244 case SENT_STATE_SIG2_DATA3:
245 case SENT_STATE_CRC:
246
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 124312 times.
2/2
✓ Decision 'true' taken 38 times.
✓ Decision 'false' taken 124312 times.
124350 if (interval > SENT_MAX_INTERVAL)
247 {
248 #if SENT_STATISTIC_COUNTERS
249 38 statistic.LongIntervalErr++;
250 #endif
251
252 38 state = SENT_STATE_INIT;
253 38 return -1;
254 }
255
256 124312 rxReg = (rxReg << 4) | (uint32_t)interval;
257
258
2/2
✓ Branch 0 taken 108880 times.
✓ Branch 1 taken 15432 times.
2/2
✓ Decision 'true' taken 108880 times.
✓ Decision 'false' taken 15432 times.
124312 if (state != SENT_STATE_CRC)
259 {
260 /* TODO: refactor */
261 108880 state = (SENT_STATE_enum)((int)state + 1);
262 108880 return 0;
263 }
264
265 #if SENT_STATISTIC_COUNTERS
266 15432 statistic.FrameCnt++;
267 #endif // SENT_STATISTIC_COUNTERS
268 15432 pausePulseReceived = false;
269 15432 state = SENT_STATE_SYNC;
270 /* CRC check */
271 /* TODO: find correct way to calculate CRC */
272 15432 if ((MsgGetCrc(rxReg) == crc4(rxReg)) ||
273
5/6
✓ Branch 0 taken 12252 times.
✓ Branch 1 taken 3180 times.
✓ Branch 3 taken 4436 times.
✓ Branch 4 taken 7816 times.
✓ Branch 5 taken 15432 times.
✗ Branch 6 not taken.
19868 (MsgGetCrc(rxReg) == crc4_gm(rxReg)) ||
274
1/2
✓ Branch 1 taken 4436 times.
✗ Branch 2 not taken.
4436 (MsgGetCrc(rxReg) == crc4_gm_v2(rxReg)))
275 {
276 /* Full packet with correct CRC has been received */
277 15432 rxLast = rxReg;
278 15432 hasValidFast = true;
279 /* TODO: add timestamp? */
280 15432 return 1;
281 }
282 else
283 {
284 #if SENT_STATISTIC_COUNTERS
285 statistic.CrcErrCnt++;
286 #endif // SENT_STATISTIC_COUNTERS
287 return -1;
288 }
289 return 0;
290 }
291
292 return 0;
293 }
294
295 147571 int sent_channel::Decoder(uint32_t clocks, uint8_t flags) {
296 int ret;
297
298 #if SENT_STATISTIC_COUNTERS
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147571 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 147571 times.
147571 if (flags & SENT_FLAG_HW_OVERFLOW) {
300 statistic.hwOverflowCnt++;
301 }
302 #endif
303
304 /* TODO: handle flags */
305 (void)flags;
306
307 147571 ret = FastChannelDecoder(clocks);
308
2/2
✓ Branch 0 taken 15432 times.
✓ Branch 1 taken 132139 times.
2/2
✓ Decision 'true' taken 15432 times.
✓ Decision 'false' taken 132139 times.
147571 if (ret > 0) {
309 /* valid packet received, can process slow channels */
310 15432 SlowChannelDecoder();
311
2/2
✓ Branch 0 taken 317 times.
✓ Branch 1 taken 131822 times.
2/2
✓ Decision 'true' taken 317 times.
✓ Decision 'false' taken 131822 times.
132139 } else if (ret < 0) {
312 /* packet is incorrect, reset slow channel state machine */
313 317 SlowChannelDecoderReset();
314 }
315
316 147571 return ret;
317 }
318
319 15450 int sent_channel::GetMsg(uint32_t* rx) {
320
2/2
✓ Branch 0 taken 15441 times.
✓ Branch 1 taken 9 times.
2/2
✓ Decision 'true' taken 15441 times.
✓ Decision 'false' taken 9 times.
15450 if (rx) {
321 15441 *rx = rxLast;
322 }
323
324
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 15449 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 15449 times.
15450 if (!hasValidFast) {
325 1 return -1;
326 }
327 /* TODO: add check for time since last message received */
328 15449 return 0;
329 }
330
331 15441 int sent_channel::GetSignals(uint8_t *pStat, uint16_t *pSig0, uint16_t *pSig1) {
332 15441 uint32_t rx;
333
1/1
✓ Branch 1 taken 15441 times.
15441 int ret = GetMsg(&rx);
334
335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15441 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 15441 times.
15441 if (ret < 0) {
336 return ret;
337 }
338
339 /* NOTE different MSB packing for sig0 and sig1
340 * is it protocol-defined or device-specific?
341 * Also looks like some devices send 16 + 8 bit, not 12 + 12 */
342
1/2
✓ Branch 0 taken 15441 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 15441 times.
✗ Decision 'false' not taken.
15441 if (pStat) {
343 15441 *pStat = MsgGetStat(rx);
344 }
345
346
1/2
✓ Branch 0 taken 15441 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 15441 times.
✗ Decision 'false' not taken.
15441 if (pSig0) {
347 15441 uint16_t tmp = MsgGetSig0(rx);
348 15441 *pSig0 = tmp;
349 }
350
351
1/2
✓ Branch 0 taken 15441 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 15441 times.
✗ Decision 'false' not taken.
15441 if (pSig1) {
352 15441 uint16_t tmp = MsgGetSig1(rx);
353 /* swap */
354 15441 tmp = ((tmp >> 8) & 0x00f) |
355 15441 ((tmp << 8) & 0xf00) |
356 15441 (tmp & 0x0f0);
357 15441 *pSig1 = tmp;
358 }
359
360 15441 return 0;
361 }
362
363 319 int sent_channel::StoreSlowChannelValue(uint8_t id, uint16_t data)
364 {
365 size_t i;
366
367 /* Update already allocated messagebox? */
368
2/2
✓ Branch 0 taken 2499 times.
✓ Branch 1 taken 47 times.
2/2
✓ Decision 'true' taken 2499 times.
✓ Decision 'false' taken 47 times.
2546 for (i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
369
4/4
✓ Branch 1 taken 1301 times.
✓ Branch 2 taken 1198 times.
✓ Branch 4 taken 272 times.
✓ Branch 5 taken 1029 times.
2/2
✓ Decision 'true' taken 272 times.
✓ Decision 'false' taken 2227 times.
2499 if ((scMsg[i].valid) && (scMsg[i].id == id)) {
370 272 scMsg[i].data = data;
371 272 return 0;
372 }
373 }
374
375 /* New message? Allocate messagebox */
376
1/2
✓ Branch 0 taken 353 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 353 times.
✗ Decision 'false' not taken.
353 for (i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
377
2/2
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 306 times.
2/2
✓ Decision 'true' taken 47 times.
✓ Decision 'false' taken 306 times.
353 if (scMsg[i].valid == false)
378 {
379 47 scMsg[i].data = data;
380 47 scMsg[i].id = id;
381 47 scMsg[i].valid = true;
382 47 return 0;
383 }
384 }
385
386 /* No free mailboxes for new ID */
387 return -1;
388 }
389
390 2304 int sent_channel::GetSlowChannelValue(uint8_t id)
391 {
392 size_t i;
393
394
2/2
✓ Branch 0 taken 73070 times.
✓ Branch 1 taken 2273 times.
2/2
✓ Decision 'true' taken 73070 times.
✓ Decision 'false' taken 2273 times.
75343 for (i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
395
4/4
✓ Branch 1 taken 7633 times.
✓ Branch 2 taken 65437 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 7602 times.
2/2
✓ Decision 'true' taken 31 times.
✓ Decision 'false' taken 73039 times.
73070 if ((scMsg[i].valid) && (scMsg[i].id == id)) {
396 31 return scMsg[i].data;
397 }
398 }
399
400 /* not found */
401 2273 return -1;
402 }
403
404 15432 int sent_channel::SlowChannelDecoder()
405 {
406 /* bit 2 and bit 3 from status nibble are used to transfer short messages */
407 15432 bool b2 = !!(MsgGetStat(rxLast) & BIT(2));
408 15432 bool b3 = !!(MsgGetStat(rxLast) & BIT(3));
409
410 /* shift in new data */
411 15432 scShift2 = (scShift2 << 1) | b2;
412 15432 scShift3 = (scShift3 << 1) | b3;
413 15432 scCrcShift = (scCrcShift << 2) | ((uint32_t)b2 << 1) | b3;
414
415 if (1) {
416 /* Short Serial Message format */
417
418 /* 0b1000.0000.0000.0000? */
419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15432 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 15432 times.
15432 if ((scShift3 & 0xffff) == 0x8000) {
420 /* Done receiving */
421
422 /* TODO: add crc check */
423
424 uint8_t id = (scShift2 >> 12) & 0x0f;
425 uint16_t data = (scShift2 >> 4) & 0xff;
426
427 return StoreSlowChannelValue(id, data);
428 }
429 }
430 if (1) {
431 /* Enhanced Serial Message format */
432
433 /* 0b11.1111.0xxx.xx0x.xxx0 ? */
434
2/2
✓ Branch 0 taken 319 times.
✓ Branch 1 taken 15113 times.
2/2
✓ Decision 'true' taken 319 times.
✓ Decision 'false' taken 15113 times.
15432 if ((scShift3 & 0x3f821) == 0x3f000) {
435 /* C-flag: configuration bit is used to indicate 16 bit format */
436 319 bool sc16Bit = !!(scShift3 & (1 << 10));
437
438 319 uint8_t crc = (scShift2 >> 12) & 0x3f;
439 #if SENT_STATISTIC_COUNTERS
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 319 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 319 times.
319 if (sc16Bit) {
441 statistic.sc16++;
442 } else {
443 319 statistic.sc12++;
444 }
445 #endif
446
1/2
✓ Branch 1 taken 319 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 319 times.
✗ Decision 'false' not taken.
319 if (crc == crc6(scCrcShift)) {
447
1/2
✓ Branch 0 taken 319 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 319 times.
✗ Decision 'false' not taken.
319 if (!sc16Bit) {
448 /* 12 bit message, 8 bit ID */
449 319 uint8_t id = ((scShift3 >> 1) & 0x0f) |
450 319 ((scShift3 >> 2) & 0xf0);
451 319 uint16_t data = scShift2 & 0x0fff; /* 12 bit */
452
453 319 return StoreSlowChannelValue(id, data);
454 } else {
455 /* 16 bit message, 4 bit ID */
456 uint8_t id = (scShift3 >> 6) & 0x0f;
457 uint16_t data = (scShift2 & 0x0fff) |
458 (((scShift3 >> 1) & 0x0f) << 12);
459
460 return StoreSlowChannelValue(id, data);
461 }
462 } else {
463 #if SENT_STATISTIC_COUNTERS
464 statistic.scCrcErr++;
465 #endif
466 }
467 }
468 }
469
470 15113 return 0;
471 }
472
473 319 void sent_channel::SlowChannelDecoderReset()
474 {
475 /* packet is incorrect, reset slow channel state machine */
476 319 scShift2 = 0;
477 319 scShift3 = 0;
478
479
2/2
✓ Branch 0 taken 10208 times.
✓ Branch 1 taken 319 times.
2/2
✓ Decision 'true' taken 10208 times.
✓ Decision 'false' taken 319 times.
10527 for (size_t i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
480 10208 scMsg[i].valid = false;
481 }
482 319 }
483
484 /* This is correct for Si7215 */
485 /* This CRC is calculated for WHOLE message expect last nibble (CRC) */
486 15432 uint8_t sent_channel::crc4(uint32_t data)
487 {
488 size_t i;
489 15432 uint8_t crc = SENT_CRC_SEED; // initialize checksum with seed "0101"
490 15432 const uint8_t CrcLookup[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
491
492
2/2
✓ Branch 0 taken 108024 times.
✓ Branch 1 taken 15432 times.
2/2
✓ Decision 'true' taken 108024 times.
✓ Decision 'false' taken 15432 times.
123456 for (i = 0; i < 7; i++) {
493 108024 crc = crc ^ MsgGetNibble(data, i);
494 108024 crc = CrcLookup[crc];
495 }
496
497 15432 return crc;
498 }
499
500 /* TODO: double check two following and use same CRC routine? */
501
502 /* This is correct for GM throttle body */
503 /* This CRC is calculated for message expect status nibble and minus CRC nibble */
504 12252 uint8_t sent_channel::crc4_gm(uint32_t data)
505 {
506 size_t i;
507 12252 uint8_t crc = SENT_CRC_SEED; // initialize checksum with seed "0101"
508 12252 const uint8_t CrcLookup[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
509
510
2/2
✓ Branch 0 taken 73512 times.
✓ Branch 1 taken 12252 times.
2/2
✓ Decision 'true' taken 73512 times.
✓ Decision 'false' taken 12252 times.
85764 for (i = 1; i < 7; i++) {
511 73512 crc = CrcLookup[crc];
512 73512 crc = (crc ^ MsgGetNibble(data, i)) & 0xf;
513 }
514
515 12252 return crc;
516 }
517
518 /* This is correct for GDI fuel pressure sensor */
519 /* This CRC is calculated for message expect status nibble and minus CRC nibble */
520 4436 uint8_t sent_channel::crc4_gm_v2(uint32_t data)
521 {
522 size_t i;
523 4436 uint8_t crc = SENT_CRC_SEED; // initialize checksum with seed "0101"
524 4436 const uint8_t CrcLookup[16] = {0, 13, 7, 10, 14, 3, 9, 4, 1, 12, 6, 11, 15, 2, 8, 5};
525
526
2/2
✓ Branch 0 taken 26616 times.
✓ Branch 1 taken 4436 times.
2/2
✓ Decision 'true' taken 26616 times.
✓ Decision 'false' taken 4436 times.
31052 for (i = 1; i < 7; i++) {
527 26616 crc = CrcLookup[crc];
528 26616 crc = (crc ^ MsgGetNibble(data, i)) & 0xf;
529 }
530 // One more round with 0 as input
531 4436 crc = CrcLookup[crc];
532
533 4436 return crc;
534 }
535
536 319 uint8_t sent_channel::crc6(uint32_t data)
537 {
538 size_t i;
539 /* Seed 0x15 (21) */
540 319 uint8_t crc = 0x15;
541 /* CRC table for poly = 0x59 (x^6 + x^4 + x^3 + 1) */
542 319 const uint8_t crc6_table[64] = {
543 0, 25, 50, 43, 61, 36, 15, 22, 35, 58, 17, 8, 30, 7, 44, 53,
544 31, 6, 45, 52, 34, 59, 16, 9, 60, 37, 14, 23, 1, 24, 51, 42,
545 62, 39, 12, 21, 3, 26, 49, 40, 29, 4, 47, 54, 32, 57, 18, 11,
546 33, 56, 19, 10, 28, 5, 46, 55, 2, 27, 48, 41, 63, 38, 13, 20 };
547
548
2/2
✓ Branch 0 taken 1276 times.
✓ Branch 1 taken 319 times.
2/2
✓ Decision 'true' taken 1276 times.
✓ Decision 'false' taken 319 times.
1595 for (i = 0; i < 4; i++) {
549 1276 uint8_t tmp = (data >> (24 - 6 * (i + 1))) & 0x3f;
550 1276 crc = tmp ^ crc6_table[crc];
551 }
552 // Extra round with 0 input
553 319 crc = 0 ^ crc6_table[crc];
554
555 319 return crc;
556 }
557