| 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 |