diff --git a/firmware/hw_layer/drivers/sent/sent.cpp b/firmware/hw_layer/drivers/sent/sent.cpp index 9632681586..37e37d2ead 100644 --- a/firmware/hw_layer/drivers/sent/sent.cpp +++ b/firmware/hw_layer/drivers/sent/sent.cpp @@ -7,11 +7,12 @@ * @author Andrey Gusakov , (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 } diff --git a/firmware/hw_layer/drivers/sent/sent_logic.h b/firmware/hw_layer/drivers/sent/sent_logic.h new file mode 100644 index 0000000000..23f537273d --- /dev/null +++ b/firmware/hw_layer/drivers/sent/sent_logic.h @@ -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); +}; diff --git a/unit_tests/logicdata_csv_reader.cpp b/unit_tests/logicdata_csv_reader.cpp index a0fae3bf2b..ab99181f4f 100644 --- a/unit_tests/logicdata_csv_reader.cpp +++ b/unit_tests/logicdata_csv_reader.cpp @@ -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 = ð->engine; diff --git a/unit_tests/tests/sent/test_sent.cpp b/unit_tests/tests/sent/test_sent.cpp new file mode 100644 index 0000000000..fb6fe9e914 --- /dev/null +++ b/unit_tests/tests/sent/test_sent.cpp @@ -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); +} diff --git a/unit_tests/tests/tests.mk b/unit_tests/tests/tests.mk index e54e289d28..cd0532315b 100644 --- a/unit_tests/tests/tests.mk +++ b/unit_tests/tests/tests.mk @@ -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 \