hip9011 and friends (#2527)

* engine math: extrant getFiringOrderTable for reuse

* engine math: getNextFiringCylinderId helper

* introduce knock_logic: first member is getCylinderKnockBank()

moved from software_knock.cpp

* hip9011: support two inputs/banks

* fix CI

* Board Subaru EG33: populated with TPIC8101 with Advanced mode

* hip9011: test communication in advanced mode

* hip9011: handle situation when chip is already in advanced mode

* Board Subaru EG33: cylinder to knock bank mapping

* hip9011: count spi transactions in advansed mode too

* hip9011: reset incalid responce counter after chip initialization

* hip9011: make debug output more structured
This commit is contained in:
Andrey G 2021-04-05 01:13:21 +03:00 committed by GitHub
parent c785a5705c
commit fa840a7593
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 375 additions and 158 deletions

View File

@ -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;

View File

@ -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 \

View File

@ -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;
}
}

View File

@ -0,0 +1,10 @@
/*
* @file knock_logic.h
*
* @date Apr 04, 2021
* @author Andrey Gusakov
*/
#pragma once
int getCylinderKnockBank(uint8_t cylinderIndex);

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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)