SENT unit tests (#4769)
* unit_tests: sent: zero-init * sent: SENT_SLOW_CHANNELS_MAX to header * unit_tests: sent: clock, falling edges * SENT: support and autodetect if device sends pause pulse Also rework tick time calculation * unit_tests: SENT: verbose debug on request * unit_tests: SENT: actual checks * unit_tests: SENT: extract common code for reuse * unit_test: SENT: add test with fuel pressue captured data * unit_test: SENT: add test with Ford ETB CLOSED captured data
This commit is contained in:
parent
79ca66cf5c
commit
64be738874
|
@ -37,10 +37,6 @@
|
|||
/* Decoder configuration */
|
||||
/*==========================================================================*/
|
||||
|
||||
|
||||
/* Maximum slow shannel mailboxes, DO NOT CHANGE */
|
||||
#define SENT_SLOW_CHANNELS_MAX 16
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Decoder */
|
||||
/*==========================================================================*/
|
||||
|
@ -62,7 +58,8 @@ void sent_channel::restart(void)
|
|||
{
|
||||
state = SENT_STATE_CALIB;
|
||||
pulseCounter = 0;
|
||||
initStatePulseCounter = 0;
|
||||
currentStatePulseCounter = 0;
|
||||
hasPausePulse = false;
|
||||
tickPerUnit = 0;
|
||||
|
||||
/* reset slow channels */
|
||||
|
@ -83,22 +80,37 @@ void sent_channel::restart(void)
|
|||
int sent_channel::Decoder(uint16_t clocks)
|
||||
{
|
||||
int ret = 0;
|
||||
int interval;
|
||||
|
||||
pulseCounter++;
|
||||
|
||||
/* special case - tick time calculation */
|
||||
if (state == SENT_STATE_CALIB) {
|
||||
/* Find longes pulse */
|
||||
if (clocks > tickPerUnit) {
|
||||
tickPerUnit = clocks;
|
||||
}
|
||||
/* ...this should be SYNC pulse */
|
||||
if (pulseCounter >= SENT_CALIBRATION_PULSES) {
|
||||
/* calculate Unit time from SYNC pulse */
|
||||
tickPerUnit = (tickPerUnit + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
|
||||
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);
|
||||
pulseCounter = 0;
|
||||
state = SENT_STATE_INIT;
|
||||
} else {
|
||||
/* some tickPerUnit calculated...
|
||||
* Check next 1 + 6 + 1 pulses if they are valid with current tickPerUnit */
|
||||
interval = (clocks + tickPerUnit / 2) / tickPerUnit - SENT_OFFSET_INTERVAL;
|
||||
if ((interval >= 0) && (interval <= SENT_MAX_INTERVAL)) {
|
||||
currentStatePulseCounter++;
|
||||
if (currentStatePulseCounter == SENT_MSG_PAYLOAD_SIZE) {
|
||||
pulseCounter = 0;
|
||||
currentStatePulseCounter = 0;
|
||||
state = SENT_STATE_INIT;
|
||||
}
|
||||
} else {
|
||||
currentStatePulseCounter = 0;
|
||||
tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
|
||||
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
|
||||
}
|
||||
}
|
||||
if (pulseCounter >= SENT_CALIBRATION_PULSES) {
|
||||
/* failed to calculate valid tickPerUnit, restart */
|
||||
restart();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,16 +122,22 @@ int sent_channel::Decoder(uint16_t clocks)
|
|||
|
||||
if (((100 * clocks) >= (syncClocks * 80)) &&
|
||||
((100 * clocks) <= (syncClocks * 120))) {
|
||||
initStatePulseCounter = 0;
|
||||
/* adjust unit time */
|
||||
tickPerUnit = (clocks + (SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL) / 2) /
|
||||
(SENT_SYNC_INTERVAL + SENT_OFFSET_INTERVAL);
|
||||
/* 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 */
|
||||
if (currentStatePulseCounter == 1) {
|
||||
hasPausePulse = true;
|
||||
}
|
||||
/* next state */
|
||||
currentStatePulseCounter = 0;
|
||||
state = SENT_STATE_STATUS;
|
||||
} else {
|
||||
initStatePulseCounter++;
|
||||
currentStatePulseCounter++;
|
||||
/* 3 frames skipped, no SYNC detected - recalibrate */
|
||||
if (initStatePulseCounter >= (9 * 3)) {
|
||||
if (currentStatePulseCounter >= (9 * 3)) {
|
||||
restart();
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +145,7 @@ int sent_channel::Decoder(uint16_t clocks)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int interval = (clocks + tickPerUnit / 2) / tickPerUnit - SENT_OFFSET_INTERVAL;
|
||||
interval = (clocks + tickPerUnit / 2) / tickPerUnit - SENT_OFFSET_INTERVAL;
|
||||
|
||||
if (interval < 0) {
|
||||
#if SENT_STATISTIC_COUNTERS
|
||||
|
@ -213,7 +231,7 @@ int sent_channel::Decoder(uint16_t clocks)
|
|||
#endif // SENT_STATISTIC_COUNTERS
|
||||
ret = -1;
|
||||
}
|
||||
state = SENT_STATE_SYNC;
|
||||
state = hasPausePulse ? SENT_STATE_PAUSE : SENT_STATE_SYNC;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -226,6 +244,9 @@ int sent_channel::Decoder(uint16_t clocks)
|
|||
ret = -1;
|
||||
}
|
||||
break;
|
||||
case SENT_STATE_PAUSE:
|
||||
state = SENT_STATE_SYNC;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#define SENT_CHANNELS_NUM 4 // Number of sent channels
|
||||
#endif
|
||||
|
||||
/* Maximum slow shannel mailboxes, DO NOT CHANGE */
|
||||
#define SENT_SLOW_CHANNELS_MAX 16
|
||||
|
||||
/* collect statistic */
|
||||
#define SENT_STATISTIC_COUNTERS 1
|
||||
|
||||
|
@ -24,6 +27,7 @@ typedef enum
|
|||
SENT_STATE_SIG2_DATA2,
|
||||
SENT_STATE_SIG2_DATA3,
|
||||
SENT_STATE_CRC,
|
||||
SENT_STATE_PAUSE,
|
||||
} SENT_STATE_enum;
|
||||
|
||||
struct sent_channel_stat {
|
||||
|
@ -42,8 +46,9 @@ private:
|
|||
/* Unit interval in timer clocks - adjusted on SYNC */
|
||||
uint32_t tickPerUnit = 0;
|
||||
uint32_t pulseCounter = 0;
|
||||
/* pulses skipped in init state while waiting for SYNC */
|
||||
uint32_t initStatePulseCounter = 0;
|
||||
/* pulses skipped in init or calibration state while waiting for SYNC */
|
||||
uint32_t currentStatePulseCounter = 0;
|
||||
bool hasPausePulse = false;
|
||||
|
||||
/* fast channel shift register*/
|
||||
uint32_t rxReg;
|
||||
|
@ -70,7 +75,7 @@ public:
|
|||
struct {
|
||||
uint16_t data;
|
||||
uint8_t id;
|
||||
} scMsg[16];
|
||||
} scMsg[SENT_SLOW_CHANNELS_MAX];
|
||||
|
||||
/* Statistic counters */
|
||||
#if SENT_STATISTIC_COUNTERS
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -2,14 +2,13 @@
|
|||
#include "logicdata_csv_reader.h"
|
||||
#include "sent_logic.h"
|
||||
|
||||
TEST(sent, testFordIdle) {
|
||||
static int sentTest_feedWithFile(sent_channel &channel, const char *file)
|
||||
{
|
||||
int lineCount = 0;
|
||||
int printDebug = 0;
|
||||
CsvReader reader(1, 0);
|
||||
|
||||
reader.open("tests/sent/resources/ford-sent-idle.csv");
|
||||
|
||||
sent_channel channel;
|
||||
|
||||
int lineCount = 0;
|
||||
reader.open(file);
|
||||
|
||||
double prevTimeStamp;
|
||||
|
||||
|
@ -19,18 +18,89 @@ TEST(sent, testFordIdle) {
|
|||
lineCount++;
|
||||
|
||||
if (lineCount == 1) {
|
||||
// get first timestamp
|
||||
prevTimeStamp = stamp;
|
||||
continue;
|
||||
}
|
||||
double diff = stamp - prevTimeStamp;
|
||||
// we care only about falling edges
|
||||
if (value < 0.5) {
|
||||
double diff = stamp - prevTimeStamp;
|
||||
|
||||
// todo: proper mult
|
||||
channel.Decoder(diff * 10'000'000);
|
||||
// On STM32 we are running timer on 1/4 of cpu clock. Cpu clock is 168 MHz
|
||||
channel.Decoder(diff * 168'000'000 / 4);
|
||||
|
||||
prevTimeStamp = stamp;
|
||||
prevTimeStamp = stamp;
|
||||
}
|
||||
|
||||
if (((lineCount % 100) == 0) && (printDebug)) {
|
||||
int ret;
|
||||
uint8_t stat;
|
||||
uint16_t sig0, sig1;
|
||||
|
||||
ret = channel.GetSignals(&stat, &sig0, &sig1);
|
||||
if (ret == 0) {
|
||||
printf("SENT status 0x%01x, signals: 0x%03x, 0x%03x\n", stat, sig0, sig1);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("testFordIdle: Got %d lines\n", lineCount);
|
||||
|
||||
ASSERT_TRUE(lineCount > 100);
|
||||
if (printDebug) {
|
||||
uint8_t stat;
|
||||
uint16_t sig0, sig1;
|
||||
|
||||
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);
|
||||
//}
|
||||
}
|
||||
|
||||
#if SENT_STATISTIC_COUNTERS
|
||||
sent_channel_stat &statistic = channel.statistic;
|
||||
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("Sync errors %d\n", statistic.SyncErr);
|
||||
#endif
|
||||
}
|
||||
|
||||
return lineCount;
|
||||
}
|
||||
|
||||
TEST(sent, testFordIdle) {
|
||||
static sent_channel channel;
|
||||
int lineCount = sentTest_feedWithFile(channel, "tests/sent/resources/ford-sent-idle.csv");
|
||||
ASSERT_TRUE(lineCount > 100);
|
||||
#if SENT_STATISTIC_COUNTERS
|
||||
sent_channel_stat &statistic = channel.statistic;
|
||||
ASSERT_TRUE(statistic.RestartCnt == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(sent, testFordClosed) {
|
||||
static sent_channel channel;
|
||||
int lineCount = sentTest_feedWithFile(channel, "tests/sent/resources/ford-sent-closed.csv");
|
||||
ASSERT_TRUE(lineCount > 100);
|
||||
#if SENT_STATISTIC_COUNTERS
|
||||
sent_channel_stat &statistic = channel.statistic;
|
||||
/* TODO: bad captured data or real problem? */
|
||||
ASSERT_TRUE(statistic.RestartCnt <= 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(sent, testFuelPressure) {
|
||||
static sent_channel channel;
|
||||
int lineCount = sentTest_feedWithFile(channel, "tests/sent/resources/SENT-fuel-pressure.csv");
|
||||
ASSERT_TRUE(lineCount > 100);
|
||||
#if SENT_STATISTIC_COUNTERS
|
||||
sent_channel_stat &statistic = channel.statistic;
|
||||
ASSERT_TRUE(statistic.RestartCnt == 0);
|
||||
/* TODO: add more checks? Check data? */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue