Ford SENT ETB bench test in NJ #4745

we shall unit test SENT
This commit is contained in:
Andrey 2022-11-07 00:06:42 -05:00
parent 6d3e71fae3
commit a25c9ab520
5 changed files with 149 additions and 96 deletions

View File

@ -7,11 +7,12 @@
* @author Andrey Gusakov <dron0gus@gmail.com>, (c) 2022
*/
#if EFI_PROD_CODE
#if EFI_PROD_CODE || EFI_UNIT_TEST
#include "pch.h"
#include "sent.h"
#include "sent_logic.h"
/*==========================================================================*/
/* Protocol definitions. */
@ -36,12 +37,6 @@
/* Decoder configuration */
/*==========================================================================*/
#ifndef SENT_CHANNELS_NUM
#define SENT_CHANNELS_NUM 4 // Number of sent channels
#endif
/* collect statistic */
#define SENT_STATISTIC_COUNTERS 1
/* Maximum slow shannel mailboxes, DO NOT CHANGE */
#define SENT_SLOW_CHANNELS_MAX 16
@ -63,92 +58,6 @@
#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)
typedef enum
{
SENT_STATE_CALIB = 0,
SENT_STATE_INIT,
SENT_STATE_SYNC,
SENT_STATE_STATUS,
SENT_STATE_SIG1_DATA1,
SENT_STATE_SIG1_DATA2,
SENT_STATE_SIG1_DATA3,
SENT_STATE_SIG2_DATA1,
SENT_STATE_SIG2_DATA2,
SENT_STATE_SIG2_DATA3,
SENT_STATE_CRC,
} SENT_STATE_enum;
struct sent_channel_stat {
uint32_t ShortIntervalErr;
uint32_t LongIntervalErr;
uint32_t SyncErr;
uint32_t CrcErrCnt;
uint32_t FrameCnt;
uint32_t RestartCnt;
};
class sent_channel {
private:
SENT_STATE_enum state = SENT_STATE_CALIB;
/* Unit interval in timer clocks - adjusted on SYNC */
uint32_t tickPerUnit;
uint32_t pulseCounter;
/* pulses skipped in init state while waiting for SYNC */
uint32_t initStatePulseCounter;
/* fast channel shift register*/
uint32_t rxReg;
/* fast channel last received valid message */
uint32_t rxLast;
/* slow channel shift registers and flags */
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);
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);
void restart(void);
public:
/* slow channel data */
struct {
uint16_t data;
uint8_t id;
} scMsg[16];
/* Statistic counters */
#if SENT_STATISTIC_COUNTERS
sent_channel_stat statistic;
#endif // SENT_STATISTIC_COUNTERS
/* Decoder */
int Decoder(uint16_t clocks);
/* Get last raw message */
int GetMsg(uint32_t* rx);
/* Unpack last valid message to status, signal0 and signal1
* Note:
* sig0 is nibbles 0 .. 2, where nibble 0 is MSB
* sig1 is niblles 5 .. 3, where niblle 5 is MSB */
int GetSignals(uint8_t *pStat, uint16_t *pSig0, uint16_t *pSig1);
/* Show status */
void Info(void);
};
static sent_channel channels[SENT_CHANNELS_NUM];
void sent_channel::restart(void)
{
state = SENT_STATE_CALIB;
@ -517,6 +426,15 @@ uint8_t sent_channel::crc4_gm_v2(uint32_t data)
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;
@ -543,7 +461,7 @@ void sent_channel::Info(void)
#if SENT_STATISTIC_COUNTERS
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 frames %d with CRC error %d (%f%%)", statistic.FrameCnt, statistic.CrcErrCnt, statistic.CrcErrCnt * 100.0 / statistic.FrameCnt);
efiPrintf("Sync errors %d", statistic.SyncErr);
#endif
}

View File

@ -0,0 +1,93 @@
/**
* sent_logic.h
*/
#pragma once
#ifndef SENT_CHANNELS_NUM
#define SENT_CHANNELS_NUM 4 // Number of sent channels
#endif
/* collect statistic */
#define SENT_STATISTIC_COUNTERS 1
typedef enum
{
SENT_STATE_CALIB = 0,
SENT_STATE_INIT,
SENT_STATE_SYNC,
SENT_STATE_STATUS,
SENT_STATE_SIG1_DATA1,
SENT_STATE_SIG1_DATA2,
SENT_STATE_SIG1_DATA3,
SENT_STATE_SIG2_DATA1,
SENT_STATE_SIG2_DATA2,
SENT_STATE_SIG2_DATA3,
SENT_STATE_CRC,
} SENT_STATE_enum;
struct sent_channel_stat {
uint32_t ShortIntervalErr;
uint32_t LongIntervalErr;
uint32_t SyncErr;
uint32_t CrcErrCnt;
uint32_t FrameCnt;
uint32_t RestartCnt;
};
class sent_channel {
private:
SENT_STATE_enum state = SENT_STATE_CALIB;
/* Unit interval in timer clocks - adjusted on SYNC */
uint32_t tickPerUnit;
uint32_t pulseCounter;
/* pulses skipped in init state while waiting for SYNC */
uint32_t initStatePulseCounter;
/* fast channel shift register*/
uint32_t rxReg;
/* fast channel last received valid message */
uint32_t rxLast;
/* slow channel shift registers and flags */
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);
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);
void restart(void);
public:
/* slow channel data */
struct {
uint16_t data;
uint8_t id;
} scMsg[16];
/* Statistic counters */
#if SENT_STATISTIC_COUNTERS
sent_channel_stat statistic;
#endif // SENT_STATISTIC_COUNTERS
/* Decoder */
int Decoder(uint16_t clocks);
/* Get last raw message */
int GetMsg(uint32_t* rx);
/* Unpack last valid message to status, signal0 and signal1
* Note:
* sig0 is nibbles 0 .. 2, where nibble 0 is MSB
* sig1 is niblles 5 .. 3, where niblle 5 is MSB */
int GetSignals(uint8_t *pStat, uint16_t *pSig0, uint16_t *pSig1);
/* Show status */
void Info(void);
};

View File

@ -40,7 +40,11 @@ bool CsvReader::haveMore() {
return result;
}
double CsvReader::readTimestampAndValues(double *v) {
/**
* @param values reference of values array to modify
* @return timestamp of current line
*/
double CsvReader::readTimestampAndValues(double *values) {
const char s[2] = ",";
char *line = buffer;
@ -49,12 +53,13 @@ double CsvReader::readTimestampAndValues(double *v) {
for (size_t i = 0; i < m_triggerCount; i++) {
char *triggerToken = trim(strtok(nullptr, s));
v[i] = std::stod(triggerToken);
values[i] = std::stod(triggerToken);
}
return timeStamp;
}
// todo: separate trigger handling from csv file processing
void CsvReader::processLine(EngineTestHelper *eth) {
Engine *engine = &eth->engine;

View File

@ -0,0 +1,36 @@
#include "pch.h"
#include "logicdata_csv_reader.h"
#include "sent_logic.h"
TEST(sent, testFordIdle) {
CsvReader reader(1, 0);
reader.open("tests/sent/resources/ford-sent-idle.csv");
sent_channel channel;
int lineCount = 0;
double prevTimeStamp;
while (reader.haveMore()) {
double value = 0;
double stamp = reader.readTimestampAndValues(&value);
lineCount++;
if (lineCount == 1) {
prevTimeStamp = stamp;
continue;
}
double diff = stamp - prevTimeStamp;
// todo: proper mult
channel.Decoder(diff * 10'000'000);
prevTimeStamp = stamp;
}
printf("testFordIdle: Got %d lines\n", lineCount);
ASSERT_TRUE(lineCount > 100);
}

View File

@ -25,6 +25,7 @@ TESTS_SRC_CPP = \
tests/trigger/test_nissan_vq_vvt.cpp \
tests/trigger/test_override_gaps.cpp \
tests/trigger/test_injection_scheduling.cpp \
tests/sent/test_sent.cpp \
tests/ignition_injection/injection_mode_transition.cpp \
tests/ignition_injection/test_startOfCrankingPrimingPulse.cpp \
tests/ignition_injection/test_multispark.cpp \