diff --git a/firmware/hw_layer/sensors/CJ125.cpp b/firmware/hw_layer/sensors/CJ125.cpp index 07d97d0b31..9472597703 100644 --- a/firmware/hw_layer/sensors/CJ125.cpp +++ b/firmware/hw_layer/sensors/CJ125.cpp @@ -47,10 +47,6 @@ static SPIConfig cj125spicfg = { NULL, /* HW dependent part.*/ NULL, 0, SPI_CR1_MSTR | SPI_CR1_CPHA | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2 }; - -// Chip diagnostics register contents -static volatile int diag = 0; - // Current values static volatile float vUa = 0.0f; static volatile float vUr = 0.0f; @@ -169,7 +165,7 @@ static uint32_t get16bitFromVoltage(float v) { static void cjPrintData(void) { #ifdef CJ125_DEBUG - scheduleMsg(logger, "cj125: state=%d diag=0x%x (vUa=%.3f vUr=%.3f) (vUaCal=%.3f vUrCal=%.3f)", state, diag, vUa, vUr, vUaCal, vUrCal); + scheduleMsg(logger, "cj125: state=%d diag=0x%x (vUa=%.3f vUr=%.3f) (vUaCal=%.3f vUrCal=%.3f)", state, globalInstance.diag, vUa, vUr, vUaCal, vUrCal); #endif } @@ -217,31 +213,18 @@ static void cjSetMode(cj125_mode_e m) { mode = m; } -static void cjIdentify(void) { - // read Ident register - int ident = cjReadRegister(IDENT_REG_RD) & CJ125_IDENT_MASK; +class RealSpi : public Cj125SpiStream { +public: + uint8_t ReadRegister(uint8_t reg) override { + return cjReadRegister(reg); + } - // set initial registers - cjWriteRegister(INIT_REG1_WR, CJ125_INIT1_NORMAL_17); - cjWriteRegister(INIT_REG2_WR, CJ125_INIT2_DIAG); - // check if regs are ok - int init1 = cjReadRegister(INIT_REG1_RD); - int init2 = cjReadRegister(INIT_REG2_RD); + void WriteRegister(uint8_t regAddr, uint8_t regValue) { + cjWriteRegister(regAddr, regValue); + } +}; - diag = cjReadRegister(DIAG_REG_RD); - scheduleMsg(logger, "cj125: Check ident=0x%x diag=0x%x init1=0x%x init2=0x%x", ident, diag, init1, init2); - if (ident != CJ125_IDENT) { - scheduleMsg(logger, "cj125: Error! Wrong ident! Cannot communicate with CJ125!"); - } - if (init1 != CJ125_INIT1_NORMAL_17 || init2 != CJ125_INIT2_DIAG) { - scheduleMsg(logger, "cj125: Error! Cannot set init registers! Cannot communicate with CJ125!"); - } -#if 0 - if (diag != CJ125_DIAG_NORM) { - scheduleMsg(logger, "cj125: Diag error!"); - } -#endif -} +static RealSpi spi; static void cjUpdateAnalogValues() { #if EFI_PROD_CODE @@ -257,7 +240,7 @@ static void cjUpdateAnalogValues() { } static void cjCalibrate(void) { - cjIdentify(); + globalInstance.cjIdentify(); scheduleMsg(logger, "cj125: Starting calibration..."); cjSetMode(CJ125_MODE_CALIBRATION); @@ -299,7 +282,7 @@ static void cjCalibrate(void) { chThdSleepMilliseconds(CJ125_CALIBRATION_DELAY); #endif // check if everything is ok - diag = cjReadRegister(DIAG_REG_RD); + globalInstance.diag = cjReadRegister(DIAG_REG_RD); cjUpdateAnalogValues(); cjPrintData(); @@ -321,7 +304,7 @@ static void cjStart(DECLARE_ENGINE_PARAMETER_SIGNATURE) { return; } - cjIdentify(); + globalInstance.cjIdentify(); // Load calibration values #if EFI_PROD_CODE @@ -434,7 +417,7 @@ static bool cj125periodic(CJ125 *instance DECLARE_ENGINE_PARAMETER_SUFFIX) { cjSetMode(CJ125_MODE_NORMAL_17); } - diag = cjReadRegister(DIAG_REG_RD); + globalInstance.diag = cjReadRegister(DIAG_REG_RD); // check heater state if (vUr > CJ125_UR_PREHEAT_THR || instance->heaterDuty < CJ125_PREHEAT_MIN_DUTY) { @@ -605,12 +588,14 @@ void cjPostState(TunerStudioOutputChannels *tsOutputChannels) { tsOutputChannels->debugFloatField6 = vUaCal; tsOutputChannels->debugFloatField7 = vUrCal; tsOutputChannels->debugIntField1 = globalInstance.state; - tsOutputChannels->debugIntField2 = diag; + tsOutputChannels->debugIntField2 = globalInstance.diag; } #endif /* EFI_TUNER_STUDIO */ void initCJ125(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) { logger = sharedLogger; + globalInstance.spi = &spi; + globalInstance.logger = sharedLogger; if (!CONFIGB(isCJ125Enabled)) return; diff --git a/firmware/hw_layer/sensors/CJ125.h b/firmware/hw_layer/sensors/CJ125.h index defa9bd2bb..7c7ec03c42 100644 --- a/firmware/hw_layer/sensors/CJ125.h +++ b/firmware/hw_layer/sensors/CJ125.h @@ -10,13 +10,6 @@ #include "CJ125_logic.h" -// CJ125 SPI Registers -#define IDENT_REG_RD 0x48 // Read Identity Register -#define INIT_REG1_WR 0x56 // Write To Initialization Register 1 -#define INIT_REG2_WR 0x5A // Write To Initialization Register 2 -#define INIT_REG1_RD 0x6C // Read Initialization Register 1 -#define DIAG_REG_RD 0x78 // Read Diagnostics Register -#define INIT_REG2_RD 0x7E // Read Initialization Register 2 /********************************************************************************** * Courtesy "Turbo SOB" @@ -81,19 +74,6 @@ 11 = No Failure ***********************************************************************************/ -#define CJ125_INIT1_NORMAL_8 0x88 // 0b10001000 (Normal mode, Amplification 8) -#define CJ125_INIT1_NORMAL_17 0x89 // 0b10001001 (Normal mode, Amplification 17) -#define CJ125_INIT1_CALBRT 0x9D // 0b10011101 (Calibration mode, LA=1, RA=1) - -#define CJ125_INIT2_NORMAL 0x00 // 0b00000000, (Normal mode) -#define CJ125_INIT2_DIAG 0x10 // 0b00010000, (Extended diagnostics mode, SET_DIA_Q=1) -#define CJ125_INIT2_RESET 0x40 // 0b01000000, SRESET=1 - -#define CJ125_DIAG_NORM 0xFF // no errors - -#define CJ125_IDENT 0x60 // 96 -#define CJ125_IDENT_MASK 0xF8 - #define CJ125_CALIBRATION_DELAY 1000 // 1 sec #define CJ125_TICK_DELAY 20 // 20 ms #define CJ125_IDLE_TICK_DELAY 1000 // 1 sec diff --git a/firmware/hw_layer/sensors/CJ125_logic.cpp b/firmware/hw_layer/sensors/CJ125_logic.cpp index f4e036f8e5..8aaa2ada50 100644 --- a/firmware/hw_layer/sensors/CJ125_logic.cpp +++ b/firmware/hw_layer/sensors/CJ125_logic.cpp @@ -45,3 +45,29 @@ void CJ125::StartHeaterControl(pwm_gen_callback *stateChangeCallback DECLARE_ENG &wboHeaterPin, CJ125_HEATER_PWM_FREQ, 0.0f, stateChangeCallback); SetIdleHeater(PASS_ENGINE_PARAMETER_SIGNATURE); } + +void CJ125::cjIdentify(void) { + // read Ident register + int ident = spi->ReadRegister(IDENT_REG_RD) & CJ125_IDENT_MASK; + + // set initial registers + spi->WriteRegister(INIT_REG1_WR, CJ125_INIT1_NORMAL_17); + spi->WriteRegister(INIT_REG2_WR, CJ125_INIT2_DIAG); + // check if regs are ok + int init1 = spi->ReadRegister(INIT_REG1_RD); + int init2 = spi->ReadRegister(INIT_REG2_RD); + + diag = spi->ReadRegister(DIAG_REG_RD); + scheduleMsg(logger, "cj125: Check ident=0x%x diag=0x%x init1=0x%x init2=0x%x", ident, diag, init1, init2); + if (ident != CJ125_IDENT) { + scheduleMsg(logger, "cj125: Error! Wrong ident! Cannot communicate with CJ125!"); + } + if (init1 != CJ125_INIT1_NORMAL_17 || init2 != CJ125_INIT2_DIAG) { + scheduleMsg(logger, "cj125: Error! Cannot set init registers! Cannot communicate with CJ125!"); + } +#if 0 + if (diag != CJ125_DIAG_NORM) { + scheduleMsg(logger, "cj125: Diag error!"); + } +#endif +} diff --git a/firmware/hw_layer/sensors/CJ125_logic.h b/firmware/hw_layer/sensors/CJ125_logic.h index 9c50824ec2..5aa4d92376 100644 --- a/firmware/hw_layer/sensors/CJ125_logic.h +++ b/firmware/hw_layer/sensors/CJ125_logic.h @@ -44,12 +44,23 @@ typedef enum { CJ125_MODE_CALIBRATION, } cj125_mode_e; +class Cj125SpiStream { +public: + virtual uint8_t ReadRegister(uint8_t regAddr) = 0; + virtual void WriteRegister(uint8_t regAddr, uint8_t regValue) = 0; +}; + class CJ125 { public: CJ125(); + Cj125SpiStream *spi = NULL; + Logging *logger = NULL; SimplePwm wboHeaterControl; + // Chip diagnostics register contents + volatile int diag = 0; + efitick_t startHeatingNt; efitick_t prevNt; float heaterDuty = 0.0f; @@ -67,6 +78,7 @@ public: void SetHeater(float value DECLARE_ENGINE_PARAMETER_SUFFIX); void SetIdleHeater(DECLARE_ENGINE_PARAMETER_SIGNATURE); void StartHeaterControl(pwm_gen_callback *stateChangeCallback DECLARE_ENGINE_PARAMETER_SUFFIX); + void cjIdentify(void); }; // Heater params for Idle(cold), Preheating and Control stages @@ -83,4 +95,25 @@ public: #define CJ125_HEATER_LIMITING_VOLTAGE 12.0f // Do not allow more than 90% heating for high battery voltage (>12V). #define CJ125_HEATER_LIMITING_RATE 0.92f // This prevents sensor overheating. +// CJ125 SPI Registers +#define IDENT_REG_RD 0x48 // Read Identity Register +#define INIT_REG1_WR 0x56 // Write To Initialization Register 1 +#define INIT_REG2_WR 0x5A // Write To Initialization Register 2 +#define INIT_REG1_RD 0x6C // Read Initialization Register 1 +#define DIAG_REG_RD 0x78 // Read Diagnostics Register +#define INIT_REG2_RD 0x7E // Read Initialization Register 2 + +#define CJ125_IDENT 0x60 // 96 +#define CJ125_IDENT_MASK 0xF8 + +#define CJ125_INIT1_NORMAL_8 0x88 // 0b10001000 (Normal mode, Amplification 8) +#define CJ125_INIT1_NORMAL_17 0x89 // 0b10001001 (Normal mode, Amplification 17) +#define CJ125_INIT1_CALBRT 0x9D // 0b10011101 (Calibration mode, LA=1, RA=1) + +#define CJ125_INIT2_NORMAL 0x00 // 0b00000000, (Normal mode) +#define CJ125_INIT2_DIAG 0x10 // 0b00010000, (Extended diagnostics mode, SET_DIA_Q=1) +#define CJ125_INIT2_RESET 0x40 // 0b01000000, SRESET=1 + +#define CJ125_DIAG_NORM 0xFF // no errors + #endif /* HW_LAYER_SENSORS_CJ125_LOGIC_H_ */ diff --git a/unit_tests/tests/test_cj125.cpp b/unit_tests/tests/test_cj125.cpp index 9d97cf993d..7616426eff 100644 --- a/unit_tests/tests/test_cj125.cpp +++ b/unit_tests/tests/test_cj125.cpp @@ -13,6 +13,12 @@ static void applyHeaterPinState(PwmConfig *state, int stateIndex) { } +class TestSpi : public Cj125SpiStream { +public: + MOCK_METHOD1(ReadRegister, uint8_t(uint8_t)); + MOCK_METHOD2(WriteRegister, void(uint8_t, uint8_t)); +}; + TEST(testCJ125, testInitialState) { CJ125 cj; @@ -26,6 +32,16 @@ TEST(testCJ125, testInitialState) { cj.StartHeaterControl(&applyHeaterPinState PASS_ENGINE_PARAMETER_SUFFIX); ASSERT_EQ(cj.heaterDuty, CJ125_HEATER_IDLE_RATE); + TestSpi mock; + cj.spi = &mock; + + EXPECT_CALL(mock, ReadRegister(IDENT_REG_RD)).Times(1); + EXPECT_CALL(mock, ReadRegister(INIT_REG1_RD)).Times(1); + EXPECT_CALL(mock, ReadRegister(INIT_REG2_RD)).Times(1); + EXPECT_CALL(mock, ReadRegister(DIAG_REG_RD)).Times(1); + + cj.cjIdentify(); + }