diff --git a/firmware/config/boards/subaru_eg33/board_configuration.cpp b/firmware/config/boards/subaru_eg33/board_configuration.cpp index 24307470da..b10f574eed 100644 --- a/firmware/config/boards/subaru_eg33/board_configuration.cpp +++ b/firmware/config/boards/subaru_eg33/board_configuration.cpp @@ -195,6 +195,8 @@ void setBoardDefaultConfiguration(void) { engineConfiguration->hip9011IntHoldPinMode = OM_OPENDRAIN; engineConfiguration->hipOutputChannel = EFI_ADC_7; /* PA7 */ engineConfiguration->isHip9011Enabled = true; + /* this board has TPIC8101, that supports advanced mode */ + engineConfiguration->useTpicAdvancedMode = true; engineConfiguration->hip9011PrescalerAndSDO = (0x6 << 1); //HIP_16MHZ_PRESCALER; @@ -204,6 +206,14 @@ void setBoardDefaultConfiguration(void) { engineConfiguration->cylinderBore = 96.9; engineConfiguration->maxKnockSubDeg = 20.0; + /* Cylinder to knock bank mapping */ + engineConfiguration->knockBankCyl1 = 0; + engineConfiguration->knockBankCyl2 = 1; + engineConfiguration->knockBankCyl3 = 0; + engineConfiguration->knockBankCyl4 = 1; + engineConfiguration->knockBankCyl5 = 0; + engineConfiguration->knockBankCyl6 = 1; + #if 0 engineConfiguration->cj125SpiDevice = SPI_DEVICE_3; engineConfiguration->cj125ua = EFI_ADC_9; diff --git a/firmware/controllers/controllers.mk b/firmware/controllers/controllers.mk index d014482b29..54ca37cb3b 100644 --- a/firmware/controllers/controllers.mk +++ b/firmware/controllers/controllers.mk @@ -34,6 +34,7 @@ CONTROLLERS_SRC_CPP = \ $(CONTROLLERS_DIR)/engine_cycle/high_pressure_fuel_pump.cpp \ $(CONTROLLERS_DIR)/engine_cycle/rpm_calculator.cpp \ $(CONTROLLERS_DIR)/engine_cycle/spark_logic.cpp \ + $(CONTROLLERS_DIR)/engine_cycle/knock_logic.cpp \ $(CONTROLLERS_DIR)/engine_cycle/main_trigger_callback.cpp \ $(CONTROLLERS_DIR)/engine_cycle/aux_valves.cpp \ $(CONTROLLERS_DIR)/engine_cycle/fuel_schedule.cpp \ diff --git a/firmware/controllers/engine_cycle/knock_logic.cpp b/firmware/controllers/engine_cycle/knock_logic.cpp new file mode 100644 index 0000000000..94bab6814e --- /dev/null +++ b/firmware/controllers/engine_cycle/knock_logic.cpp @@ -0,0 +1,46 @@ +/* + * @file knock_logic.c + * + * @date Apr 04, 2021 + * @author Andrey Gusakov + */ + +#include "engine.h" +#include "knock_logic.h" +#include "os_access.h" + +EXTERN_ENGINE; + +int getCylinderKnockBank(uint8_t cylinderIndex) { + // C/C++ can't index in to bit fields, we have to provide lookup ourselves + switch (cylinderIndex) { +#if EFI_PROD_CODE + case 0: + return CONFIG(knockBankCyl1); + case 1: + return CONFIG(knockBankCyl2); + case 2: + return CONFIG(knockBankCyl3); + case 3: + return CONFIG(knockBankCyl4); + case 4: + return CONFIG(knockBankCyl5); + case 5: + return CONFIG(knockBankCyl6); + case 6: + return CONFIG(knockBankCyl7); + case 7: + return CONFIG(knockBankCyl8); + case 8: + return CONFIG(knockBankCyl9); + case 9: + return CONFIG(knockBankCyl10); + case 10: + return CONFIG(knockBankCyl11); + case 11: + return CONFIG(knockBankCyl12); +#endif + default: + return 0; + } +} diff --git a/firmware/controllers/engine_cycle/knock_logic.h b/firmware/controllers/engine_cycle/knock_logic.h new file mode 100644 index 0000000000..6badc2fd95 --- /dev/null +++ b/firmware/controllers/engine_cycle/knock_logic.h @@ -0,0 +1,10 @@ +/* + * @file knock_logic.h + * + * @date Apr 04, 2021 + * @author Andrey Gusakov + */ + +#pragma once + +int getCylinderKnockBank(uint8_t cylinderIndex); diff --git a/firmware/controllers/math/engine_math.cpp b/firmware/controllers/math/engine_math.cpp index 7e73d99c4a..1ccc2f5b48 100644 --- a/firmware/controllers/math/engine_math.cpp +++ b/firmware/controllers/math/engine_math.cpp @@ -131,6 +131,7 @@ floatms_t getSparkDwell(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) { #endif } +static const int order_1[] = {1}; static const int order_1_2[] = {1, 2}; @@ -239,6 +240,87 @@ static int getFiringOrderLength(DECLARE_ENGINE_PARAMETER_SIGNATURE) { return 1; } +static const int *getFiringOrderTable(DECLARE_ENGINE_PARAMETER_SIGNATURE) +{ + switch (CONFIG(specs.firingOrder)) { + case FO_1: + return order_1; +// 2 cylinder + case FO_1_2: + return order_1_2; +// 3 cylinder + case FO_1_2_3: + return order_1_2_3; + case FO_1_3_2: + return order_1_3_2; +// 4 cylinder + case FO_1_3_4_2: + return order_1_THEN_3_THEN_4_THEN2; + case FO_1_2_4_3: + return order_1_THEN_2_THEN_4_THEN3; + case FO_1_3_2_4: + return order_1_THEN_3_THEN_2_THEN4; + case FO_1_4_3_2: + return order_1_THEN_4_THEN_3_THEN2; +// 5 cylinder + case FO_1_2_4_5_3: + return order_1_2_4_5_3; + +// 6 cylinder + case FO_1_5_3_6_2_4: + return order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4; + case FO_1_4_2_5_3_6: + return order_1_THEN_4_THEN_2_THEN_5_THEN_3_THEN_6; + case FO_1_2_3_4_5_6: + return order_1_THEN_2_THEN_3_THEN_4_THEN_5_THEN_6; + case FO_1_6_3_2_5_4: + return order_1_6_3_2_5_4; + +// 8 cylinder + case FO_1_8_4_3_6_5_7_2: + return order_1_8_4_3_6_5_7_2; + case FO_1_8_7_2_6_5_4_3: + return order_1_8_7_2_6_5_4_3; + case FO_1_5_4_2_6_3_7_8: + return order_1_5_4_2_6_3_7_8; + case FO_1_2_7_8_4_5_6_3: + return order_1_2_7_8_4_5_6_3; + case FO_1_3_7_2_6_5_4_8: + return order_1_3_7_2_6_5_4_8; + case FO_1_2_3_4_5_6_7_8: + return order_1_2_3_4_5_6_7_8; + case FO_1_5_4_8_6_3_7_2: + return order_1_5_4_8_6_3_7_2; + +// 9 cylinder + case FO_1_2_3_4_5_6_7_8_9: + return order_1_2_3_4_5_6_7_8_9; + + +// 10 cylinder + case FO_1_10_9_4_3_6_5_8_7_2: + return order_1_10_9_4_3_6_5_8_7_2; + +// 12 cylinder + case FO_1_7_5_11_3_9_6_12_2_8_4_10: + return order_1_7_5_11_3_9_6_12_2_8_4_10; + case FO_1_7_4_10_2_8_6_12_3_9_5_11: + return order_1_7_4_10_2_8_6_12_3_9_5_11; + case FO_1_12_5_8_3_10_6_7_2_11_4_9: + return order_1_12_5_8_3_10_6_7_2_11_4_9; + case FO_1_2_3_4_5_6_7_8_9_10_11_12: + return order_1_2_3_4_5_6_7_8_9_10_11_12; + +// do not ask + case FO_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10: + return order_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10; + + default: + firmwareError(CUSTOM_OBD_UNKNOWN_FIRING_ORDER, "Invalid firing order: %d", CONFIG(specs.firingOrder)); + } + + return NULL; +} /** * @param index from zero to cylindersCount - 1 @@ -264,81 +346,27 @@ int getCylinderId(int index DECLARE_ENGINE_PARAMETER_SUFFIX) { return 1; } - switch (CONFIG(specs.firingOrder)) { - case FO_1: - return 1; -// 2 cylinder - case FO_1_2: - return order_1_2[index]; -// 3 cylinder - case FO_1_2_3: - return order_1_2_3[index]; - case FO_1_3_2: - return order_1_3_2[index]; -// 4 cylinder - case FO_1_3_4_2: - return order_1_THEN_3_THEN_4_THEN2[index]; - case FO_1_2_4_3: - return order_1_THEN_2_THEN_4_THEN3[index]; - case FO_1_3_2_4: - return order_1_THEN_3_THEN_2_THEN4[index]; - case FO_1_4_3_2: - return order_1_THEN_4_THEN_3_THEN2[index]; -// 5 cylinder - case FO_1_2_4_5_3: - return order_1_2_4_5_3[index]; + const int *firingOrderTable = getFiringOrderTable(PASS_ENGINE_PARAMETER_SIGNATURE); + if (firingOrderTable) + return firingOrderTable[index]; + /* else + error already reported */ -// 6 cylinder - case FO_1_5_3_6_2_4: - return order_1_THEN_5_THEN_3_THEN_6_THEN_2_THEN_4[index]; - case FO_1_4_2_5_3_6: - return order_1_THEN_4_THEN_2_THEN_5_THEN_3_THEN_6[index]; - case FO_1_2_3_4_5_6: - return order_1_THEN_2_THEN_3_THEN_4_THEN_5_THEN_6[index]; - case FO_1_6_3_2_5_4: - return order_1_6_3_2_5_4[index]; + return 1; +} -// 8 cylinder - case FO_1_8_4_3_6_5_7_2: - return order_1_8_4_3_6_5_7_2[index]; - case FO_1_8_7_2_6_5_4_3: - return order_1_8_7_2_6_5_4_3[index]; - case FO_1_5_4_2_6_3_7_8: - return order_1_5_4_2_6_3_7_8[index]; - case FO_1_2_7_8_4_5_6_3: - return order_1_2_7_8_4_5_6_3[index]; - case FO_1_3_7_2_6_5_4_8: - return order_1_3_7_2_6_5_4_8[index]; - case FO_1_2_3_4_5_6_7_8: - return order_1_2_3_4_5_6_7_8[index]; - case FO_1_5_4_8_6_3_7_2: - return order_1_5_4_8_6_3_7_2[index]; +/** + * @param prevCylinderId from one to cylindersCount + * @return cylinderId from one to cylindersCount + */ +int getNextFiringCylinderId(int prevCylinderId DECLARE_ENGINE_PARAMETER_SUFFIX) { + const int firingOrderLength = getFiringOrderLength(PASS_ENGINE_PARAMETER_SIGNATURE); + const int *firingOrderTable = getFiringOrderTable(PASS_ENGINE_PARAMETER_SIGNATURE); -// 9 cylinder - case FO_1_2_3_4_5_6_7_8_9: - return order_1_2_3_4_5_6_7_8_9[index]; - - -// 10 cylinder - case FO_1_10_9_4_3_6_5_8_7_2: - return order_1_10_9_4_3_6_5_8_7_2[index]; - -// 12 cylinder - case FO_1_7_5_11_3_9_6_12_2_8_4_10: - return order_1_7_5_11_3_9_6_12_2_8_4_10[index]; - case FO_1_7_4_10_2_8_6_12_3_9_5_11: - return order_1_7_4_10_2_8_6_12_3_9_5_11[index]; - case FO_1_12_5_8_3_10_6_7_2_11_4_9: - return order_1_12_5_8_3_10_6_7_2_11_4_9[index]; - case FO_1_2_3_4_5_6_7_8_9_10_11_12: - return order_1_2_3_4_5_6_7_8_9_10_11_12[index]; - -// do not ask - case FO_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10: - return order_1_14_9_4_7_12_15_6_13_8_3_16_11_2_5_10[index]; - - default: - firmwareError(CUSTOM_OBD_UNKNOWN_FIRING_ORDER, "Invalid firing order: %d", CONFIG(specs.firingOrder)); + if (firingOrderTable) { + for (size_t i = 0; i < firingOrderLength; i++) + if (firingOrderTable[i] == prevCylinderId) + return firingOrderTable[(i + 1) % firingOrderLength]; } return 1; } diff --git a/firmware/controllers/math/engine_math.h b/firmware/controllers/math/engine_math.h index 262d293b9b..5d34a5d6c6 100644 --- a/firmware/controllers/math/engine_math.h +++ b/firmware/controllers/math/engine_math.h @@ -53,6 +53,7 @@ ignition_mode_e getCurrentIgnitionMode(DECLARE_ENGINE_PARAMETER_SIGNATURE); void prepareIgnitionPinIndices(ignition_mode_e ignitionMode DECLARE_ENGINE_PARAMETER_SUFFIX); int getCylinderId(int index DECLARE_ENGINE_PARAMETER_SUFFIX); +int getNextFiringCylinderId(int prevCylinderId DECLARE_ENGINE_PARAMETER_SUFFIX); void setTimingRpmBin(float from, float to DECLARE_CONFIG_PARAMETER_SUFFIX); void setTimingLoadBin(float from, float to DECLARE_CONFIG_PARAMETER_SUFFIX); diff --git a/firmware/controllers/sensors/software_knock.cpp b/firmware/controllers/sensors/software_knock.cpp index 585c9ed5e3..54a1ab5e06 100644 --- a/firmware/controllers/sensors/software_knock.cpp +++ b/firmware/controllers/sensors/software_knock.cpp @@ -4,6 +4,7 @@ #include "biquad.h" #include "perf_trace.h" #include "thread_controller.h" +#include "knock_logic.h" #include "software_knock.h" #include "thread_priority.h" @@ -93,31 +94,11 @@ static const ADCConversionGroup adcConvGroupCh2 = { FALSE, 1, &completionCallbac 0, // sqr2 ADC_SQR3_SQ1_N(KNOCK_ADC_CH2) }; - -static bool cylinderUsesChannel2(uint8_t cylinderIndex) { - // C/C++ can't index in to bit fields, we have to provide lookup ourselves - switch (cylinderIndex) { - case 0: return CONFIG(knockBankCyl1); - case 1: return CONFIG(knockBankCyl2); - case 2: return CONFIG(knockBankCyl3); - case 3: return CONFIG(knockBankCyl4); - case 4: return CONFIG(knockBankCyl5); - case 5: return CONFIG(knockBankCyl6); - case 6: return CONFIG(knockBankCyl7); - case 7: return CONFIG(knockBankCyl8); - case 8: return CONFIG(knockBankCyl9); - case 9: return CONFIG(knockBankCyl10); - case 10: return CONFIG(knockBankCyl11); - case 11: return CONFIG(knockBankCyl12); - default: return false; - } -} - #endif // KNOCK_HAS_CH2 const ADCConversionGroup* getConversionGroup(uint8_t cylinderIndex) { #if KNOCK_HAS_CH2 - if (cylinderUsesChannel2(cylinderIndex)) { + if (getCylinderKnockBank(cylinderIndex)) { return &adcConvGroupCh2; } #else diff --git a/firmware/hw_layer/sensors/hip9011.cpp b/firmware/hw_layer/sensors/hip9011.cpp index 74f32a18b8..bba6eaead6 100644 --- a/firmware/hw_layer/sensors/hip9011.cpp +++ b/firmware/hw_layer/sensors/hip9011.cpp @@ -116,17 +116,21 @@ static void hip_addconsoleActions(void); /* Local functions. */ /*==========================================================================*/ -static int checkResponse(uint8_t tx, uint8_t rx) { - /* TODO: implement response check for Advanced SPI mode too */ +static int checkResponseDefMode(uint8_t tx, uint8_t rx) { + /* in default SPI mode SDO is directly equals the SDI (echo function) */ if (tx == rx) { - instance.correctResponsesCount++; return 0; } else { - instance.invalidResponsesCount++; return -1; } } +static int checkResponseAdvMode(uint8_t tx, uint8_t rx) { + UNUSED(tx); UNUSED(rx); + /* TODO: no check for advanced mode yet */ + return 0; +} + int Hip9011Hardware::sendSyncCommand(uint8_t tx, uint8_t *rx_ptr) { int ret; uint8_t rx; @@ -143,20 +147,22 @@ int Hip9011Hardware::sendSyncCommand(uint8_t tx, uint8_t *rx_ptr) { spiUnselect(spi); /* Ownership release. */ spiReleaseBus(spi); - /* check response */ - if (instance.adv_mode == false) { - /* only default SPI mode SDO is directly equals the SDI (echo function) */ - ret = checkResponse(tx, rx); - - if (ret) - return ret; - } - - if (rx_ptr) { + /* received data */ + if (rx_ptr) *rx_ptr = rx; - } + /* check response */ + if (instance.adv_mode == false) + ret = checkResponseDefMode(tx, rx); + else + ret = checkResponseAdvMode(tx, rx); - return 0; + /* statistic counters */ + if (ret) + instance.invalidResponsesCount++; + else + instance.correctResponsesCount++; + + return ret; } EXTERN_ENGINE; @@ -214,13 +220,25 @@ void hip9011_startKnockSampling(uint8_t cylinderNumber, efitick_t nowNt) { return; } - instance.cylinderNumber = cylinderNumber; - startIntegration(NULL); + if (cylinderNumber == instance.expectedCylinderNumber) { + /* save currect cylinder */ + instance.cylinderNumber = cylinderNumber; + startIntegration(NULL); - /* TODO: reference to knockDetectionWindowStart */ - scheduleByAngle(&endTimer, nowNt, - engineConfiguration->knockDetectionWindowEnd - engineConfiguration->knockDetectionWindowStart, - &endIntegration); + /* TODO: reference to knockDetectionWindowStart */ + scheduleByAngle(&endTimer, nowNt, + engineConfiguration->knockDetectionWindowEnd - engineConfiguration->knockDetectionWindowStart, + &endIntegration); + } else { + /* out of sync */ + if (instance.expectedCylinderNumber >= 0) + instance.unsync++; + /* save currect cylinder */ + instance.cylinderNumber = cylinderNumber; + /* Skip integration, call driver task to prepare for next cylinder */ + instance.state = NOT_READY; + hip_wake_driver(); + } } void hipAdcCallback(adcsample_t adcValue) { @@ -234,26 +252,82 @@ void hipAdcCallback(adcsample_t adcValue) { } } +static int hip_testAdvMode(void) { + int ret; + uint8_t ret0, ret1, ret2; + + /* do not care about configuration values, we meed replyes only. + * correct values will be uploaded later */ + + /* A control byte is written to the SDI and shifted with the MSB + * first. The response byte on the SDO is shifted out with the MSB + * first. The response byte corresponds to the previous command. + * Therefore, the SDI shifts in a control byte n and shifts out a + * response command byte n − 1. */ + ret = instance.hw->sendSyncCommand(SET_BAND_PASS_CMD(0), NULL); + if (ret) + return ret; + ret = instance.hw->sendSyncCommand(SET_GAIN_CMD(0), &ret0); + if (ret) + return ret; + ret = instance.hw->sendSyncCommand(SET_INTEGRATOR_CMD(0), &ret1); + if (ret) + return ret; + ret = instance.hw->sendSyncCommand(SET_INTEGRATOR_CMD(0), &ret2); + if (ret) + return ret; + + /* magic reply bytes from DS Table 2 */ + if ((ret0 == SET_BAND_PASS_REP) && + (ret1 == SET_GAIN_REP) && + (ret2 == SET_INTEGRATOR_REP)) + return 0; + + return -1; +} + static int hip_init(void) { int ret; ret = instance.hw->sendSyncCommand(SET_PRESCALER_CMD(instance.prescaler), NULL); - if (ret) - return ret; - - // '0' for channel #1 - ret = instance.hw->sendSyncCommand(SET_CHANNEL_CMD(instance.channelIdx), NULL); - if (ret) - return ret; - - if (CONFIG(useTpicAdvancedMode)) { - // enable advanced mode for digital integrator output - ret = instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, NULL); - if (ret) + if (ret) { + /* NOTE: hip9011/tpic8101 can be in default or advansed mode at this point + * If we supposed not to support advanced mode this is definitely error */ + if (!CONFIG(useTpicAdvancedMode)) return ret; - instance.adv_mode = true; } + /* ...othervice or when no error is reported lets try to switch to advanced mode */ + if (CONFIG(useTpicAdvancedMode)) { + /* enable advanced mode */ + ret = instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, NULL); + if (ret) { + uint8_t rx; + /* communication error is detected for default mode... + * may be we are in advanced mode already? + * Now we dont care for return value */ + instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, &rx); + if (rx != SET_ADVANCED_MODE_REP) { + /* this is realy a communication problem */ + return ret; + } + } + + /* now we should be in advanced mode... if chip supports... + * set advanced mode flag now so checkResponse will switch to + * advanced mode checkig (not implemented) */ + instance.adv_mode = true; + + ret = hip_testAdvMode(); + if (ret) { + warning(CUSTOM_OBD_KNOCK_PROCESSOR, "TPIC/HIP does not support advanced mode"); + instance.adv_mode = false; + } + } + + /* reset error counter now */ + instance.invalidResponsesCount = 0; + instance.state = READY_TO_INTEGRATE; return 0; @@ -296,6 +370,8 @@ static msg_t hipThread(void *arg) { /* load new/updated settings */ instance.handleSettings(GET_RPM() DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS)); + /* switch input channel */ + instance.handleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS)); /* State */ instance.state = READY_TO_INTEGRATE; @@ -303,8 +379,8 @@ static msg_t hipThread(void *arg) { if (msg == MSG_TIMEOUT) { /* ??? */ } else { - /* TODO: check for correct cylinder/input */ - if (1) { + /* Check for correct cylinder/input */ + if (instance.cylinderNumber == instance.expectedCylinderNumber) { /* calculations */ float knockVolts = instance.raw_value * adcToVolts(1) * CONFIG(analogInputDividerCoefficient); hipValueMax = maxF(knockVolts, hipValueMax); @@ -313,6 +389,11 @@ static msg_t hipThread(void *arg) { /* TunerStudio */ tsOutputChannels.knockLevels[instance.cylinderNumber] = knockVolts; tsOutputChannels.knockLevel = knockVolts; + + /* counters */ + instance.samples++; + } else { + /* out of sync event already calculated, nothing to do */ } } } @@ -357,7 +438,6 @@ void initHip9011(Logging *sharedLogger) { startHip9001_pins(); /* load settings */ - instance.channelIdx = 0; instance.prescaler = CONFIG(hip9011PrescalerAndSDO); scheduleMsg(logger, "Starting HIP9011/TPIC8101 driver"); @@ -377,20 +457,30 @@ static void showHipInfo(void) { return; } - scheduleMsg(logger, "enabled=%s state=%s", + scheduleMsg(logger, "HIP9011: enabled %s state %s", boolToString(CONFIG(isHip9011Enabled)), getHip_state_e(instance.state)); - scheduleMsg(logger, " bore=%.2fmm freq=%.2fkHz", - engineConfiguration->cylinderBore, - instance.getBand(PASS_HIP_PARAMS)); + scheduleMsg(logger, " Advanced mode: enabled %d used %d", + CONFIG(useTpicAdvancedMode), + instance.adv_mode); - scheduleMsg(logger, " band idx=%d integrator idx=%d gain %.2f (idx %d) output=%s", - instance.bandIdx, - instance.intergratorIdx, + scheduleMsg(logger, " Input Ch %d (cylinder %d next %d)", + instance.channelIdx, + instance.cylinderNumber, + instance.expectedCylinderNumber); + + scheduleMsg(logger, " Cyl bore %.2fmm freq %.2fkHz band idx 0x%x", + engineConfiguration->cylinderBore, + instance.getBand(PASS_HIP_PARAMS), + instance.bandIdx); + + scheduleMsg(logger, " Integrator idx 0x%x", + instance.intergratorIdx); + + scheduleMsg(logger, " Gain %.2f idx 0x%x", engineConfiguration->hip9011Gain, - instance.gainIdx, - getAdc_channel_e(engineConfiguration->hipOutputChannel)); + instance.gainIdx); scheduleMsg(logger, " PaSDO=0x%x", instance.prescaler); @@ -400,31 +490,37 @@ static void showHipInfo(void) { engine->knockCount, engineConfiguration->maxKnockSubDeg); - scheduleMsg(logger, " spi=%s IntHold@%s(0x%x) correct response=%d incorrect response=%d (%s)", - getSpi_device_e(engineConfiguration->hip9011SpiDevice), + scheduleMsg(logger, " Adc input %s (%.2f V)", + getAdc_channel_e(engineConfiguration->hipOutputChannel), + getVoltage("hipinfo", engineConfiguration->hipOutputChannel)); + + scheduleMsg(logger, " IntHold %s (mode 0x%x)", hwPortname(CONFIG(hip9011IntHoldPin)), - CONFIG(hip9011IntHoldPinMode), - instance.correctResponsesCount, - instance.invalidResponsesCount, - instance.invalidResponsesCount > 0 ? "NOT GOOD" : "ok"); + CONFIG(hip9011IntHoldPinMode)); + + scheduleMsg(logger, " Spi %s CS %s (mode 0x%x)", + getSpi_device_e(engineConfiguration->hip9011SpiDevice), + hwPortname(CONFIG(hip9011CsPin)), + CONFIG(hip9011CsPinMode)); #if EFI_PROD_CODE - scheduleMsg(logger, "hip %.2fv/last=%.2f/max=%.2f adv=%d", - engine->knockVolts, - getVoltage("hipinfo", engineConfiguration->hipOutputChannel), - hipValueMax, - CONFIG(useTpicAdvancedMode)); - scheduleMsg(logger, "hip9011 CS@%s", - hwPortname(CONFIG(hip9011CsPin))); printSpiConfig(logger, "hip9011", CONFIG(hip9011SpiDevice)); #endif /* EFI_PROD_CODE */ - scheduleMsg(logger, "start %.2f end %.2f", + scheduleMsg(logger, " SPI good response %d incorrect response %d", + instance.correctResponsesCount, + instance.invalidResponsesCount); + + scheduleMsg(logger, " hip %.2f vmax=%.2f", + engine->knockVolts, + hipValueMax); + + scheduleMsg(logger, " Window start %.2f end %.2f", engineConfiguration->knockDetectionWindowStart, engineConfiguration->knockDetectionWindowEnd); - scheduleMsg(logger, "Status: overruns %d", - instance.overrun); + scheduleMsg(logger, " Counters: samples %d overruns %d sync miss %d", + instance.samples, instance.overrun, instance.unsync); hipValueMax = 0; engine->printKnockState(); diff --git a/firmware/hw_layer/sensors/hip9011_logic.cpp b/firmware/hw_layer/sensors/hip9011_logic.cpp index 6e8412aa27..6555c9d4c9 100644 --- a/firmware/hw_layer/sensors/hip9011_logic.cpp +++ b/firmware/hw_layer/sensors/hip9011_logic.cpp @@ -7,6 +7,10 @@ #include "global.h" #include "engine.h" +/* getNextFiringCylinderId */ +#include "engine_math.h" +/* getCylinderKnockBank */ +#include "knock_logic.h" #include "hip9011_logic.h" /*==========================================================================*/ @@ -183,3 +187,28 @@ void HIP9011::handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)) { prescaler = new_prescaler; } } + +int HIP9011::cylinderToChannelIdx(int cylinder) { + /* TODO: hip9011 inputs to bank mapping? */ + return getCylinderKnockBank(cylinder); +} + +void HIP9011::handleChannel(DEFINE_HIP_PARAMS) { + int ret; + + /* we did not receive any callback from spark logic with valid cylinder yet */ + if (cylinderNumber < 0) + return; + + /* find next firing cylinder */ + /* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */ + expectedCylinderNumber = getNextFiringCylinderId((cylinderNumber + 1) PASS_ENGINE_PARAMETER_SUFFIX) - 1; + + int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber); + if (nextChannelIdx == channelIdx) + return; + + ret = sendCommand(SET_CHANNEL_CMD(nextChannelIdx)); + if (ret == 0) + channelIdx = nextChannelIdx; +} diff --git a/firmware/hw_layer/sensors/hip9011_logic.h b/firmware/hw_layer/sensors/hip9011_logic.h index c5a6c4b295..2b47c2f585 100644 --- a/firmware/hw_layer/sensors/hip9011_logic.h +++ b/firmware/hw_layer/sensors/hip9011_logic.h @@ -61,6 +61,8 @@ public: class HIP9011 { public: + DECLARE_ENGINE_PTR; + explicit HIP9011(Hip9011HardwareInterface *hardware); int sendCommand(uint8_t cmd); @@ -68,6 +70,8 @@ public: void prepareRpmLookup(void); void setAngleWindowWidth(DEFINE_HIP_PARAMS); void handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)); + int cylinderToChannelIdx(int cylinder); + void handleChannel(DEFINE_HIP_PARAMS); float getBand(DEFINE_HIP_PARAMS); int getIntegrationIndexByRpm(float rpm); int getBandIndex(DEFINE_HIP_PARAMS); @@ -98,11 +102,14 @@ public: * hipOutput should be set to used FAST adc device */ hip_state_e state; - uint8_t cylinderNumber; + int8_t cylinderNumber = -1; + int8_t expectedCylinderNumber = -1; int raw_value; - /* error counters */ + /* counters */ + int samples = 0; int overrun = 0; + int unsync = 0; float rpmLookup[INT_LOOKUP_SIZE]; }; @@ -113,12 +120,20 @@ public: #define SET_CHANNEL_CMD(v) (0xE0 | ((v) & 0x01)) // 0b00xx.xxxx #define SET_BAND_PASS_CMD(v) (0x00 | ((v) & 0x3f)) +/* magic replyed on SET_BAND_PASS_CMD in advanced mode */ +#define SET_BAND_PASS_REP (0x01) // 0b10xx.xxxx #define SET_GAIN_CMD(v) (0x80 | ((v) & 0x3f)) +/* magic replyed on SET_GAIN_CMD in advanced mode */ +#define SET_GAIN_REP (0xe0) // 0b110x.xxxx #define SET_INTEGRATOR_CMD(v) (0xC0 | ((v) & 0x1f)) +/* magic replyed on SET_INTEGRATOR_CMD in advanced mode */ +#define SET_INTEGRATOR_REP (0x71) // 0b0111.0001 #define SET_ADVANCED_MODE_CMD (0x71) +/* magic replyed on SET_ADVANCED_MODE_CMD in advanced mode */ +#define SET_ADVANCED_MODE_REP ((~SET_ADVANCED_MODE_CMD) & 0xff) // D[4:1] = 0000 : 4 MHz #define HIP_4MHZ_PRESCALER (0x0 << 1)