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:
parent
c785a5705c
commit
fa840a7593
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* @file knock_logic.h
|
||||
*
|
||||
* @date Apr 04, 2021
|
||||
* @author Andrey Gusakov
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
int getCylinderKnockBank(uint8_t cylinderIndex);
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue