SENT updates (#4774)

* SENT: simplify

* SENT: add crc6 routine, check crc for slow channels enhanced messages

* SENT: helper to get Slow Channel values

* SENT: getTickTime() report tick unit time

* unit_tests: SENT: update tests
This commit is contained in:
Andrey G 2022-11-13 00:57:20 +03:00 committed by GitHub
parent 3def9396de
commit 27166f4b23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 44 deletions

View File

@ -54,6 +54,9 @@
#define MsgGetSig1(msg) (((msg) >> (1 * 4)) & 0xfff)
#define MsgGetCrc(msg) MsgGetNibble(msg, 7)
/* convert CPU ticks to float Us */
#define TicksToUs(ticks) ((float)(ticks) * 1000.0 * 1000.0 / CORE_CLOCK)
void sent_channel::restart(void)
{
state = SENT_STATE_CALIB;
@ -73,10 +76,24 @@ void sent_channel::restart(void)
statistic.SyncErr = 0;
statistic.CrcErrCnt = 0;
statistic.FrameCnt = 0;
statistic.sc = 0;
statistic.scCrcErr = 0;
statistic.RestartCnt++;
#endif
}
uint32_t sent_channel::calcTickPerUnit(uint32_t clocks)
{
/* int division with rounding */
return (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
}
float sent_channel::getTickTime(void)
{
return tickPerUnit;
}
int sent_channel::Decoder(uint16_t clocks)
{
int ret = 0;
@ -89,8 +106,7 @@ int sent_channel::Decoder(uint16_t clocks)
if (tickPerUnit == 0) {
/* no tickPerUnit calculated yet
* lets assume this is sync pulse... */
tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
tickPerUnit = calcTickPerUnit(clocks);
} else {
/* some tickPerUnit calculated...
* Check next 1 + 6 + 1 pulses if they are valid with current tickPerUnit */
@ -104,8 +120,7 @@ int sent_channel::Decoder(uint16_t clocks)
}
} else {
currentStatePulseCounter = 0;
tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
tickPerUnit = calcTickPerUnit(clocks);
}
}
if (pulseCounter >= SENT_CALIBRATION_PULSES) {
@ -123,8 +138,7 @@ int sent_channel::Decoder(uint16_t clocks)
if (((100 * clocks) >= (syncClocks * 80)) &&
((100 * clocks) <= (syncClocks * 120))) {
/* adjust unit time */
tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
tickPerUnit = calcTickPerUnit(clocks);
/* we get here from calibration phase. calibration phase end with CRC nibble
* if we had to skip ONE pulse before we get sync - that means device sends pause
* pulses in between of messages */
@ -167,8 +181,7 @@ int sent_channel::Decoder(uint16_t clocks)
if (interval == SENT_SYNC_INTERVAL)
{// sync interval - 56 ticks
/* measured tick interval will be used until next sync pulse */
tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
tickPerUnit = calcTickPerUnit(clocks);
rxReg = 0;
state = SENT_STATE_STATUS;
}
@ -306,9 +319,9 @@ int sent_channel::GetSignals(uint8_t *pStat, uint16_t *pSig0, uint16_t *pSig1)
return 0;
}
int sent_channel::SlowChannelStore(uint8_t id, uint16_t data)
int sent_channel::StoreSlowChannelValue(uint8_t id, uint16_t data)
{
int i;
size_t i;
/* Update already allocated messagebox? */
for (i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
@ -333,6 +346,20 @@ int sent_channel::SlowChannelStore(uint8_t id, uint16_t data)
return -1;
}
int sent_channel::GetSlowChannelValue(uint8_t id)
{
size_t i;
for (i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
if ((scMsgFlags & BIT(i)) && (scMsg[i].id == id)) {
return scMsg[i].data;
}
}
/* not found */
return -1;
}
int sent_channel::SlowChannelDecoder()
{
/* bit 2 and bit 3 from status nibble are used to transfer short messages */
@ -342,6 +369,7 @@ int sent_channel::SlowChannelDecoder()
/* shift in new data */
scShift2 = (scShift2 << 1) | b2;
scShift3 = (scShift3 << 1) | b3;
scCrcShift = (scCrcShift << 2) | ((uint32_t)b2 << 1) | b3;
if (1) {
/* Short Serial Message format */
@ -355,7 +383,7 @@ int sent_channel::SlowChannelDecoder()
uint8_t id = (scShift2 >> 12) & 0x0f;
uint16_t data = (scShift2 >> 4) & 0xff;
return SlowChannelStore(id, data);
return StoreSlowChannelValue(id, data);
}
}
if (1) {
@ -365,29 +393,33 @@ int sent_channel::SlowChannelDecoder()
if ((scShift3 & 0x3f821) == 0x3f000) {
uint8_t id;
/* C-flag: configuration bit is used to indicate 16 bit format */
bool sc16Bit = !!(scShift3 & (1 << 10));
if (!sc16Bit) {
/* 12 bit message, 8 bit ID */
uint8_t crc = (scShift2 >> 12) & 0x3f;
#if SENT_STATISTIC_COUNTERS
statistic.sc++;
#endif
if (crc == crc6(scCrcShift)) {
/* C-flag: configuration bit is used to indicate 16 bit format */
bool sc16Bit = !!(scShift3 & (1 << 10));
if (!sc16Bit) {
/* 12 bit message, 8 bit ID */
id = ((scShift3 >> 1) & 0x0f) |
((scShift3 >> 2) & 0xf0);
uint16_t data = scShift2 & 0x0fff; /* 12 bit */
/* TODO: add crc check */
/* TODO: add crc check */
return StoreSlowChannelValue(id, data);
} else {
/* 16 bit message, 4 bit ID */
id = (scShift3 >> 6) & 0x0f;
uint16_t data = (scShift2 & 0x0fff) |
(((scShift3 >> 1) & 0x0f) << 12);
id = ((scShift3 >> 1) & 0x0f) |
((scShift3 >> 2) & 0xf0);
uint16_t data = scShift2 & 0x0fff; /* 12 bit */
/* TODO: add crc check */
return SlowChannelStore(id, data);
return StoreSlowChannelValue(id, data);
}
} else {
/* 16 bit message, 4 bit ID */
/* TODO: add crc check */
id = (scShift3 >> 6) & 0x0f;
uint16_t data = (scShift2 & 0x0fff) |
(((scShift3 >> 1) & 0x0f) << 12);
return SlowChannelStore(id, data);
#if SENT_STATISTIC_COUNTERS
statistic.scCrcErr++;
#endif
}
}
}
@ -447,15 +479,34 @@ uint8_t sent_channel::crc4_gm_v2(uint32_t data)
return crc;
}
uint8_t sent_channel::crc6(uint32_t data)
{
size_t i;
/* Seed 0x15 (21) */
uint8_t crc = 0x15;
/* CRC table for poly = 0x59 (x^6 + x^4 + x^3 + 1) */
const uint8_t crc6_table[64] = {
0, 25, 50, 43, 61, 36, 15, 22, 35, 58, 17, 8, 30, 7, 44, 53,
31, 6, 45, 52, 34, 59, 16, 9, 60, 37, 14, 23, 1, 24, 51, 42,
62, 39, 12, 21, 3, 26, 49, 40, 29, 4, 47, 54, 32, 57, 18, 11,
33, 56, 19, 10, 28, 5, 46, 55, 2, 27, 48, 41, 63, 38, 13, 20 };
for (i = 0; i < 4; i++) {
uint8_t tmp = (data >> (24 - 6 * (i + 1))) & 0x3f;
crc = tmp ^ crc6_table[crc];
}
// Extra cound with 0 input
crc = 0 ^ crc6_table[crc];
return crc;
}
#endif // EFI_PROD_CODE || EFI_UNIT_TEST
#if EFI_PROD_CODE
static sent_channel channels[SENT_CHANNELS_NUM];
/* convert CPU ticks to float Us */
#define TicksToUs(ticks) ((float)(ticks) * 1000.0 * 1000.0 / CORE_CLOCK)
void sent_channel::Info(void)
{
int i;
@ -463,7 +514,7 @@ void sent_channel::Info(void)
uint8_t stat;
uint16_t sig0, sig1;
efiPrintf("Unit time %d CPU ticks %f uS", tickPerUnit, TicksToUs(tickPerUnit));
efiPrintf("Unit time %d CPU ticks %f uS", tickPerUnit, TicksToUs(getTickTime()));
efiPrintf("Total pulses %d", pulseCounter);
if (GetSignals(&stat, &sig0, &sig1) == 0) {
@ -483,6 +534,7 @@ void sent_channel::Info(void)
efiPrintf("Restarts %d", statistic.RestartCnt);
efiPrintf("Interval errors %d short, %d long", statistic.ShortIntervalErr, statistic.LongIntervalErr);
efiPrintf("Total frames %d with CRC error %d (%f%%)", statistic.FrameCnt, statistic.CrcErrCnt, statistic.CrcErrCnt * 100.0 / statistic.FrameCnt);
efiPrintf("Total slow channel messages %d with crc6 errors %d (%f%%)", statistic.sc, statistic.scCrcErr, statistic.scCrcErr * 100.0 / statistic.sc);
efiPrintf("Sync errors %d", statistic.SyncErr);
#endif
}

View File

@ -37,6 +37,10 @@ struct sent_channel_stat {
uint32_t CrcErrCnt;
uint32_t FrameCnt;
uint32_t RestartCnt;
/* Slow channel */
uint32_t sc;
uint32_t scCrcErr;
};
class sent_channel {
@ -59,14 +63,20 @@ private:
uint16_t scMsgFlags;
uint32_t scShift2; /* shift register for bit 2 from status nibble */
uint32_t scShift3; /* shift register for bit 3 from status nibble */
/* Slow channel decoder */
int SlowChannelStore(uint8_t id, uint16_t data);
uint32_t scCrcShift; /* shift regiter for special order for CRC6 calculation */
/* Slow channel decoder and helpers */
int StoreSlowChannelValue(uint8_t id, uint16_t data);
int SlowChannelDecoder(void);
/* CRC */
uint8_t crc4(uint32_t data);
uint8_t crc4_gm(uint32_t data);
uint8_t crc4_gm_v2(uint32_t data);
/* Slow channel CRC6 */
uint8_t crc6(uint32_t data);
/* calc unit tick time from sync pulse */
uint32_t calcTickPerUnit(uint32_t clocks);
void restart(void);
@ -93,6 +103,12 @@ public:
* sig1 is niblles 5 .. 3, where niblle 5 is MSB */
int GetSignals(uint8_t *pStat, uint16_t *pSig0, uint16_t *pSig1);
/* Get slow channel value for given ID 8*/
int GetSlowChannelValue(uint8_t id);
/* Current tick time in CPU/timer clocks */
float getTickTime(void);
/* Show status */
void Info(void);
};

View File

@ -2,6 +2,11 @@
#include "logicdata_csv_reader.h"
#include "sent_logic.h"
// On STM32 we are running timer on 1/4 of cpu clock. Cpu clock is 168 MHz
#define CORE_CLOCK 168'000'000
#define TIMER_CLOCK (CORE_CLOCK / 4)
#define TicksToUs(ticks) ((float)(ticks) * 1000.0 * 1000.0 / TIMER_CLOCK)
static int sentTest_feedWithFile(sent_channel &channel, const char *file)
{
int lineCount = 0;
@ -26,8 +31,7 @@ static int sentTest_feedWithFile(sent_channel &channel, const char *file)
if (value < 0.5) {
double diff = stamp - prevTimeStamp;
// On STM32 we are running timer on 1/4 of cpu clock. Cpu clock is 168 MHz
channel.Decoder(diff * 168'000'000 / 4);
channel.Decoder(diff * TIMER_CLOCK);
prevTimeStamp = stamp;
}
@ -43,21 +47,25 @@ static int sentTest_feedWithFile(sent_channel &channel, const char *file)
}
}
}
printf("testFordIdle: Got %d lines\n", lineCount);
if (printDebug) {
uint8_t stat;
uint16_t sig0, sig1;
printf("Unit time %f uS\n", TicksToUs(channel.getTickTime()));
if (channel.GetSignals(&stat, &sig0, &sig1) == 0) {
printf("Last valid fast msg Status 0x%01x Sig0 0x%03x Sig1 0x%03x\n", stat, sig0, sig1);
}
printf("Slow channels:\n");
for (int i = 0; i < SENT_SLOW_CHANNELS_MAX; i++) {
//if (scMsgFlags & BIT(i)) {
printf(" ID %d: %d\n", channel.scMsg[i].id, channel.scMsg[i].data);
//}
/* run for all possible slow channel IDs (8 bit) */
for (int i = 0; i < 256; i++) {
int value;
value = channel.GetSlowChannelValue(i);
if (value < 0)
continue;
printf(" ID %d: %d\n", i, value);
}
#if SENT_STATISTIC_COUNTERS
@ -65,6 +73,7 @@ static int sentTest_feedWithFile(sent_channel &channel, const char *file)
printf("Restarts %d\n", statistic.RestartCnt);
printf("Interval errors %d short, %d long\n", statistic.ShortIntervalErr, statistic.LongIntervalErr);
printf("Total frames %d with CRC error %d (%f%%)\n", statistic.FrameCnt, statistic.CrcErrCnt, statistic.CrcErrCnt * 100.0 / statistic.FrameCnt);
printf("Total slow channel messages %d with crc6 errors %d (%f%%)\n", statistic.sc, statistic.scCrcErr, statistic.scCrcErr * 100.0 / statistic.sc);
printf("Sync errors %d\n", statistic.SyncErr);
#endif
}