Hip9011 (#2512)
* hip9011: coexistance with other spi devices * hip9011: rework so SPI transfer is invoked from thread also use polling spi exchange to avoid cache problems * hip9011: move calculations from ADC callback to thread * hip9011: big cleanup * hip9011: simplify spi communication * No need to set knockBandCustom if it is not custom HIP9011 calculates knockBand from cylinderBore same way * hip9011: make unit test happy * hip9011: fix unit test * hip9011: remove duplicated initialization, reorder * hip9011: just renames and data type adjustments * hip9011: rename BAND() to HIP9011_BAND() * hip9011: move some code from lookup.cpp to logic.cpp * hip9011: move initEngineNoiseTable to engine_configuration.cpp * hip9011: move lookup tables to hip9011_logic.c * hip9011: remove empty files * hip9011: additional checks
This commit is contained in:
parent
523bef2eb6
commit
3d138958ce
|
@ -110,7 +110,6 @@ void m73engine(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
|||
engineConfiguration->cranking.baseFuel = 30;
|
||||
|
||||
engineConfiguration->cylinderBore = 85.0;
|
||||
engineConfiguration->knockBandCustom = BAND(engineConfiguration->cylinderBore);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -790,7 +790,7 @@ void setMiataNB2_ProteusEngineConfiguration(DECLARE_CONFIG_PARAMETER_SIGNATURE)
|
|||
CONFIG(enableSoftwareKnock) = true;
|
||||
// second harmonic (aka double) is usually quieter background noise
|
||||
// 13.8
|
||||
engineConfiguration->knockBandCustom = 2 * BAND(engineConfiguration->cylinderBore);
|
||||
engineConfiguration->knockBandCustom = 2 * HIP9011_BAND(engineConfiguration->cylinderBore);
|
||||
|
||||
engineConfiguration->malfunctionIndicatorPin = GPIOB_6; // "Lowside 10" # pin 20/black35
|
||||
|
||||
|
|
|
@ -637,7 +637,7 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
|
|||
|
||||
tsOutputChannels->isWarnNow = engine->engineState.warnings.isWarningNow(timeSeconds, true);
|
||||
#if EFI_HIP_9011
|
||||
tsOutputChannels->isKnockChipOk = (instance.invalidHip9011ResponsesCount == 0);
|
||||
tsOutputChannels->isKnockChipOk = (instance.invalidResponsesCount == 0);
|
||||
#endif /* EFI_HIP_9011 */
|
||||
|
||||
#if EFI_LAUNCH_CONTROL
|
||||
|
@ -818,7 +818,7 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
|
|||
case DBG_KNOCK:
|
||||
// todo: maybe extract hipPostState(tsOutputChannels);
|
||||
tsOutputChannels->debugIntField1 = instance.correctResponsesCount;
|
||||
tsOutputChannels->debugIntField2 = instance.invalidHip9011ResponsesCount;
|
||||
tsOutputChannels->debugIntField2 = instance.invalidResponsesCount;
|
||||
break;
|
||||
#endif /* EFI_HIP_9011 */
|
||||
#if EFI_CJ125 && HAL_USE_SPI
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "sensor.h"
|
||||
#include "flash_main.h"
|
||||
|
||||
#include "hip9011_lookup.h"
|
||||
#include "hip9011_logic.h"
|
||||
|
||||
#if EFI_MEMS
|
||||
|
@ -658,6 +657,19 @@ void setDefaultGppwmParameters(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
}
|
||||
}
|
||||
|
||||
void setDefaultEngineNoiseTable(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||
setRpmTableBin(engineConfiguration->knockNoiseRpmBins, ENGINE_NOISE_CURVE_SIZE);
|
||||
|
||||
engineConfiguration->knockNoise[0] = 2; // 800
|
||||
engineConfiguration->knockNoise[1] = 2; // 1700
|
||||
engineConfiguration->knockNoise[2] = 2; // 2600
|
||||
engineConfiguration->knockNoise[3] = 2; // 3400
|
||||
engineConfiguration->knockNoise[4] = 2; // 4300
|
||||
engineConfiguration->knockNoise[5] = 2; // 5200
|
||||
engineConfiguration->knockNoise[6] = 2; // 6100
|
||||
engineConfiguration->knockNoise[7] = 2; // 7000
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Global default engine configuration
|
||||
* This method sets the global engine configuration defaults. These default values are then
|
||||
|
@ -824,7 +836,7 @@ static void setDefaultEngineConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
setLinearCurve(config->fsioTable4LoadBins, 20, 120, 10);
|
||||
setRpmTableBin(config->fsioTable4RpmBins, FSIO_TABLE_8);
|
||||
|
||||
initEngineNoiseTable(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||
setDefaultEngineNoiseTable(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||
|
||||
engineConfiguration->clt.config = {0, 23.8889, 48.8889, 9500, 2100, 1000, 1500};
|
||||
|
||||
|
@ -972,7 +984,6 @@ static void setDefaultEngineConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
engineConfiguration->HD44780height = 4;
|
||||
|
||||
engineConfiguration->cylinderBore = 87.5;
|
||||
engineConfiguration->knockBandCustom = BAND(engineConfiguration->cylinderBore);
|
||||
|
||||
setEgoSensor(ES_14Point7_Free PASS_CONFIG_PARAMETER_SUFFIX);
|
||||
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
* @file hip9011_lookup.cpp
|
||||
* @brief HIP9011-specific table lookups, the other part of implementation is in HIP9011.cpp
|
||||
*
|
||||
* @date Jan 4, 2015
|
||||
* @author Andrey Belomutskiy, (c) 2012-2020
|
||||
*/
|
||||
|
||||
#include "hip9011_lookup.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
/**
|
||||
* These are HIP9011 magic values - integrator time constants in uS
|
||||
*/
|
||||
const int integratorValues[INT_LOOKUP_SIZE] = { 40, 45, 50, 55, 60, 65, 70, 75, 80, 90, 100, 110, 120, 130, 140, 150,
|
||||
160, 180, 200, 220, 240, 260, 280, 300, 320, 360, 400, 440, 480, 520, 560, 600 };
|
||||
|
||||
const float gainLookupInReverseOrder[GAIN_LOOKUP_SIZE] = {
|
||||
/* 00 */0.111, 0.118, 0.125, 0.129, 0.133, 0.138, 0.143, 0.148,
|
||||
/* 08 */0.154, 0.160, 0.167, 0.174, 0.182, 0.190, 0.200, 0.211,
|
||||
/* 16 */0.222, 0.236, 0.250, 0.258, 0.267, 0.276, 0.286, 0.296,
|
||||
/* 24 */0.308, 0.320, 0.333, 0.348, 0.364, 0.381, 0.400, 0.421,
|
||||
/* 32 */0.444, 0.471, 0.500, 0.548, 0.567, 0.586, 0.607, 0.630,
|
||||
/* 40 */0.654, 0.680, 0.708, 0.739, 0.773, 0.810, 0.850, 0.895,
|
||||
/* 48 */0.944, 1.000, 1.063, 1.143, 1.185, 1.231, 1.280, 1.333,
|
||||
/* 56 */1.391, 1.455, 1.523, 1.600, 1.684, 1.778, 1.882, 2.0 };
|
||||
|
||||
const float bandFreqLookup[BAND_LOOKUP_SIZE] = { 1.22, 1.26, 1.31, 1.35, 1.4, 1.45, 1.51, 1.57, 1.63, 1.71, 1.78,
|
||||
1.87, 1.96, 2.07, 2.18, 2.31, 2.46, 2.54, 2.62, 2.71, 2.81, 2.92, 3.03, 3.15, 3.28, 3.43, 3.59, 3.76, 3.95,
|
||||
4.16, 4.39, 4.66, 4.95, 5.12, 5.29, 5.48, 5.68, 5.9, 6.12, 6.37, 6.64, 6.94, 7.27, 7.63, 8.02, 8.46, 8.95, 9.5,
|
||||
10.12, 10.46, 10.83, 11.22, 11.65, 12.1, 12.6, 13.14, 13.72, 14.36, 15.07, 15.84, 16.71, 17.67, 18.76, 19.98 };
|
||||
|
||||
|
||||
/**
|
||||
* 'TC is typically TINT/(2*Pi*VOUT)'
|
||||
* Knock Sensor Training TPIC8101, page 24
|
||||
*/
|
||||
float getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth) {
|
||||
/**
|
||||
* TINT = TC * 2 * PI * VOUT
|
||||
*/
|
||||
float integrationTimeUs = timeUs * 2 * PIF * DESIRED_OUTPUT_VALUE;
|
||||
/**
|
||||
* rpm = 60 seconds / time
|
||||
* '60000000' because revolutions per MINUTE in uS conversion
|
||||
*/
|
||||
float windowWidthMult = angleWindowWidth / 360.0f;
|
||||
return 60000000.0f / integrationTimeUs * windowWidthMult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param frequency knock frequency, in kHz
|
||||
*/
|
||||
int getHip9011BandIndex(float frequency) {
|
||||
return findIndexMsg("freq", bandFreqLookup, BAND_LOOKUP_SIZE, frequency);
|
||||
}
|
||||
|
||||
EXTERN_ENGINE;
|
||||
|
||||
void initEngineNoiseTable(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||
setRpmTableBin(engineConfiguration->knockNoiseRpmBins, ENGINE_NOISE_CURVE_SIZE);
|
||||
|
||||
engineConfiguration->knockNoise[0] = 2; // 800
|
||||
engineConfiguration->knockNoise[1] = 2; // 1700
|
||||
engineConfiguration->knockNoise[2] = 2; // 2600
|
||||
engineConfiguration->knockNoise[3] = 2; // 3400
|
||||
engineConfiguration->knockNoise[4] = 2; // 4300
|
||||
engineConfiguration->knockNoise[5] = 2; // 5200
|
||||
engineConfiguration->knockNoise[6] = 2; // 6100
|
||||
engineConfiguration->knockNoise[7] = 2; // 7000
|
||||
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/**
|
||||
* @file hip9011_lookup.h
|
||||
*
|
||||
* @date Jan 4, 2015
|
||||
* @author Andrey Belomutskiy, (c) 2012-2020
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
#define INT_LOOKUP_SIZE 32
|
||||
#define GAIN_LOOKUP_SIZE 64
|
||||
#define BAND_LOOKUP_SIZE 64
|
||||
|
||||
#define PIF 3.14159f
|
||||
#define DESIRED_OUTPUT_VALUE 5.0f
|
||||
|
||||
extern const int integratorValues[INT_LOOKUP_SIZE];
|
||||
extern const float gainLookupInReverseOrder[GAIN_LOOKUP_SIZE];
|
||||
extern const float bandFreqLookup[BAND_LOOKUP_SIZE];
|
||||
|
||||
float getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth);
|
||||
|
||||
int getHip9011BandIndex(float frequency);
|
||||
|
||||
#define GAIN_INDEX(gain) (GAIN_LOOKUP_SIZE - 1 - findIndexMsg("fGain", gainLookupInReverseOrder, GAIN_LOOKUP_SIZE, (gain)))
|
||||
|
||||
extern float rpmLookup[INT_LOOKUP_SIZE];
|
||||
void initEngineNoiseTable(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
||||
|
|
@ -7,7 +7,6 @@ CONTROLLERS_SENSORS_SRC_CPP = $(PROJECT_DIR)/controllers/sensors/thermistors.cp
|
|||
$(PROJECT_DIR)/controllers/sensors/maf.cpp \
|
||||
$(PROJECT_DIR)/controllers/sensors/tps.cpp \
|
||||
$(PROJECT_DIR)/controllers/sensors/ego.cpp \
|
||||
$(PROJECT_DIR)/controllers/sensors/hip9011_lookup.cpp \
|
||||
$(PROJECT_DIR)/controllers/sensors/sensor.cpp \
|
||||
$(PROJECT_DIR)/controllers/sensors/sensor_info_printing.cpp \
|
||||
$(PROJECT_DIR)/controllers/sensors/functional_sensor.cpp \
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include "rpm_calculator.h"
|
||||
#include "trigger_central.h"
|
||||
#include "hip9011_logic.h"
|
||||
#include "hip9011_lookup.h"
|
||||
#include "hip9011.h"
|
||||
#include "adc_inputs.h"
|
||||
#include "perf_trace.h"
|
||||
|
@ -50,28 +49,38 @@
|
|||
#if EFI_PROD_CODE
|
||||
#include "pin_repository.h"
|
||||
#include "mpu_util.h"
|
||||
#include "os_util.h"
|
||||
#endif
|
||||
|
||||
#if EFI_HIP_9011
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Local definitions. */
|
||||
/*==========================================================================*/
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Local variables and types. */
|
||||
/*==========================================================================*/
|
||||
|
||||
static NamedOutputPin intHold(PROTOCOL_HIP_NAME);
|
||||
static NamedOutputPin Cs(PROTOCOL_HIP_NAME);
|
||||
|
||||
class Hip9011Hardware : public Hip9011HardwareInterface {
|
||||
void sendSyncCommand(unsigned char command) override;
|
||||
void sendCommand(unsigned char command) override;
|
||||
int sendSyncCommand(uint8_t command, uint8_t *rx_ptr) override;
|
||||
};
|
||||
|
||||
/* TODO: include following stuff in object */
|
||||
/* wake semaphore */
|
||||
static semaphore_t wake;
|
||||
|
||||
static SPIDriver *spi;
|
||||
|
||||
static Hip9011Hardware hardware;
|
||||
|
||||
static float hipValueMax = 0;
|
||||
|
||||
HIP9011 instance(&hardware);
|
||||
|
||||
static unsigned char tx_buff[1];
|
||||
static unsigned char rx_buff[1];
|
||||
|
||||
static scheduling_s startTimer;
|
||||
static scheduling_s endTimer;
|
||||
|
||||
static Logging *logger;
|
||||
|
@ -97,132 +106,77 @@ static SPIConfig hipSpiCfg = {
|
|||
};
|
||||
#endif /* EFI_PROD_CODE */
|
||||
|
||||
static void checkResponse(void) {
|
||||
if (tx_buff[0] == rx_buff[0]) {
|
||||
/*==========================================================================*/
|
||||
/* Forward declarations */
|
||||
/*==========================================================================*/
|
||||
|
||||
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 */
|
||||
if (tx == rx) {
|
||||
instance.correctResponsesCount++;
|
||||
return 0;
|
||||
} else {
|
||||
instance.invalidHip9011ResponsesCount++;
|
||||
instance.invalidResponsesCount++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// this macro is only used on startup
|
||||
#define SPI_SYNCHRONOUS(value) \
|
||||
spiSelect(driver); \
|
||||
tx_buff[0] = value; \
|
||||
spiExchange(driver, 1, tx_buff, rx_buff); \
|
||||
spiUnselect(driver); \
|
||||
checkResponse();
|
||||
int Hip9011Hardware::sendSyncCommand(uint8_t tx, uint8_t *rx_ptr) {
|
||||
int ret;
|
||||
uint8_t rx;
|
||||
|
||||
/* Acquire ownership of the bus. */
|
||||
spiAcquireBus(spi);
|
||||
/* Setup transfer parameters. */
|
||||
spiStart(spi, &hipSpiCfg);
|
||||
/* Slave Select assertion. */
|
||||
spiSelect(spi);
|
||||
/* Transfer */
|
||||
rx = spiPolledExchange(spi, tx);
|
||||
/* Slave Select de-assertion. */
|
||||
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);
|
||||
|
||||
static SPIDriver *driver;
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Hip9011Hardware::sendSyncCommand(unsigned char command) {
|
||||
SPI_SYNCHRONOUS(command);
|
||||
chThdSleepMilliseconds(10);
|
||||
}
|
||||
if (rx_ptr) {
|
||||
*rx_ptr = rx;
|
||||
}
|
||||
|
||||
void Hip9011Hardware::sendCommand(unsigned char command) {
|
||||
tx_buff[0] = command;
|
||||
|
||||
spiSelectI(driver);
|
||||
spiStartExchangeI(driver, 1, tx_buff, rx_buff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXTERN_ENGINE;
|
||||
|
||||
static void showHipInfo(void) {
|
||||
if (!CONFIG(isHip9011Enabled)) {
|
||||
scheduleMsg(logger, "hip9011 driver not active");
|
||||
return;
|
||||
static int hip_wake_driver(void)
|
||||
{
|
||||
/* Entering a reentrant critical zone.*/
|
||||
syssts_t sts = chSysGetStatusAndLockX();
|
||||
chSemSignalI(&wake);
|
||||
if (!port_is_isr_context()) {
|
||||
/**
|
||||
* chSemSignalI above requires rescheduling
|
||||
* interrupt handlers have implicit rescheduling
|
||||
*/
|
||||
chSchRescheduleS();
|
||||
}
|
||||
/* Leaving the critical zone.*/
|
||||
chSysRestoreStatusX(sts);
|
||||
|
||||
scheduleMsg(logger, "enabled=%s state=%s",
|
||||
boolToString(CONFIG(isHip9011Enabled)),
|
||||
getHip_state_e(instance.state));
|
||||
|
||||
scheduleMsg(logger, " bore=%.2fmm freq=%.2fkHz",
|
||||
engineConfiguration->cylinderBore,
|
||||
getHIP9011Band(PASS_HIP_PARAMS));
|
||||
|
||||
scheduleMsg(logger, " band_index=%d integrator index=%d gain %.2f (%d) output=%s",
|
||||
instance.currentBandIndex,
|
||||
instance.currentIntergratorIndex,
|
||||
engineConfiguration->hip9011Gain,
|
||||
instance.currentGainIndex,
|
||||
getAdc_channel_e(engineConfiguration->hipOutputChannel));
|
||||
|
||||
scheduleMsg(logger, " PaSDO=0x%x",
|
||||
engineConfiguration->hip9011PrescalerAndSDO);
|
||||
|
||||
scheduleMsg(logger, " knockVThreshold=%.2f knockCount=%d maxKnockSubDeg=%.2f",
|
||||
engineConfiguration->knockVThreshold,
|
||||
engine->knockCount,
|
||||
engineConfiguration->maxKnockSubDeg);
|
||||
|
||||
scheduleMsg(logger, " spi=%s IntHold@%s(0x%x) correct response=%d incorrect response=%d (%s)",
|
||||
getSpi_device_e(engineConfiguration->hip9011SpiDevice),
|
||||
hwPortname(CONFIG(hip9011IntHoldPin)),
|
||||
CONFIG(hip9011IntHoldPinMode),
|
||||
instance.correctResponsesCount,
|
||||
instance.invalidHip9011ResponsesCount,
|
||||
instance.invalidHip9011ResponsesCount > 0 ? "NOT GOOD" : "ok");
|
||||
|
||||
#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",
|
||||
engineConfiguration->knockDetectionWindowStart,
|
||||
engineConfiguration->knockDetectionWindowEnd);
|
||||
|
||||
scheduleMsg(logger, "Status: overruns %d",
|
||||
instance.overrun);
|
||||
|
||||
hipValueMax = 0;
|
||||
engine->printKnockState();
|
||||
}
|
||||
|
||||
void setHip9011FrankensoPinout(void) {
|
||||
/**
|
||||
* SPI on PB13/14/15
|
||||
*/
|
||||
// CONFIG(hip9011CsPin) = GPIOD_0; // rev 0.1
|
||||
|
||||
CONFIG(isHip9011Enabled) = true;
|
||||
engineConfiguration->hip9011PrescalerAndSDO = HIP_8MHZ_PRESCALER; // 8MHz chip
|
||||
CONFIG(is_enabled_spi_2) = true;
|
||||
// todo: convert this to rusEfi, hardware-independent enum
|
||||
#if EFI_PROD_CODE
|
||||
#ifdef EFI_HIP_CS_PIN
|
||||
CONFIG(hip9011CsPin) = EFI_HIP_CS_PIN;
|
||||
#else
|
||||
CONFIG(hip9011CsPin) = GPIOB_0; // rev 0.4
|
||||
#endif
|
||||
CONFIG(hip9011CsPinMode) = OM_OPENDRAIN;
|
||||
|
||||
CONFIG(hip9011IntHoldPin) = GPIOB_11;
|
||||
CONFIG(hip9011IntHoldPinMode) = OM_OPENDRAIN;
|
||||
|
||||
engineConfiguration->spi2SckMode = PO_OPENDRAIN; // 4
|
||||
engineConfiguration->spi2MosiMode = PO_OPENDRAIN; // 4
|
||||
engineConfiguration->spi2MisoMode = PO_PULLUP; // 32
|
||||
#endif /* EFI_PROD_CODE */
|
||||
|
||||
engineConfiguration->hip9011Gain = 1;
|
||||
engineConfiguration->knockVThreshold = 4;
|
||||
engineConfiguration->maxKnockSubDeg = 20;
|
||||
|
||||
|
||||
if (!CONFIG(useTpicAdvancedMode)) {
|
||||
engineConfiguration->hipOutputChannel = EFI_ADC_10; // PC0
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void startIntegration(void *) {
|
||||
|
@ -269,111 +223,107 @@ void hip9011_startKnockSampling(uint8_t cylinderNumber, efitick_t nowNt) {
|
|||
&endIntegration);
|
||||
}
|
||||
|
||||
void setMaxKnockSubDeg(int value) {
|
||||
engineConfiguration->maxKnockSubDeg = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
void setKnockThresh(float value) {
|
||||
engineConfiguration->knockVThreshold = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
void setPrescalerAndSDO(int value) {
|
||||
engineConfiguration->hip9011PrescalerAndSDO = value;
|
||||
}
|
||||
|
||||
void setHipBand(float value) {
|
||||
engineConfiguration->knockBandCustom = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
void setHipGain(float value) {
|
||||
engineConfiguration->hip9011Gain = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* this is the end of the non-synchronous exchange
|
||||
*/
|
||||
static void endOfSpiExchange(SPIDriver *spip) {
|
||||
(void)spip;
|
||||
spiUnselectI(driver);
|
||||
instance.state = READY_TO_INTEGRATE;
|
||||
checkResponse();
|
||||
}
|
||||
|
||||
void hipAdcCallback(adcsample_t adcValue) {
|
||||
if (instance.state == WAITING_FOR_ADC_TO_SKIP) {
|
||||
instance.state = WAITING_FOR_RESULT_ADC;
|
||||
} else if (instance.state == WAITING_FOR_RESULT_ADC) {
|
||||
float knockVolts = adcValue * adcToVolts(1) * CONFIG(analogInputDividerCoefficient);
|
||||
hipValueMax = maxF(knockVolts, hipValueMax);
|
||||
engine->knockLogic(knockVolts);
|
||||
|
||||
instance.handleValue(GET_RPM() DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
|
||||
|
||||
/* TunerStudio */
|
||||
tsOutputChannels.knockLevels[instance.cylinderNumber] = knockVolts;
|
||||
tsOutputChannels.knockLevel = knockVolts;
|
||||
/* offload calculations to driver thread */
|
||||
instance.raw_value = adcValue;
|
||||
instance.state = NOT_READY;
|
||||
hip_wake_driver();
|
||||
}
|
||||
}
|
||||
|
||||
static void hipStartupCode(void) {
|
||||
instance.currentPrescaler = engineConfiguration->hip9011PrescalerAndSDO;
|
||||
instance.hardware->sendSyncCommand(SET_PRESCALER_CMD(instance.currentPrescaler));
|
||||
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
|
||||
instance.hardware->sendSyncCommand(SET_CHANNEL_CMD(0));
|
||||
|
||||
// band index depends on cylinder bore
|
||||
instance.hardware->sendSyncCommand(SET_BAND_PASS_CMD(instance.currentBandIndex));
|
||||
|
||||
if (instance.correctResponsesCount == 0) {
|
||||
warning(CUSTOM_OBD_KNOCK_PROCESSOR, "TPIC/HIP does not respond");
|
||||
}
|
||||
ret = instance.hw->sendSyncCommand(SET_CHANNEL_CMD(instance.channelIdx), NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (CONFIG(useTpicAdvancedMode)) {
|
||||
// enable advanced mode for digital integrator output
|
||||
instance.hardware->sendSyncCommand(SET_ADVANCED_MODE_CMD);
|
||||
ret = instance.hw->sendSyncCommand(SET_ADVANCED_MODE_CMD, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
instance.adv_mode = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let's restart SPI to switch it from synchronous mode into
|
||||
* asynchronous mode
|
||||
*/
|
||||
spiStop(driver);
|
||||
#if EFI_PROD_CODE
|
||||
hipSpiCfg.end_cb = endOfSpiExchange;
|
||||
#endif
|
||||
spiStart(driver, &hipSpiCfg);
|
||||
instance.state = READY_TO_INTEGRATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static THD_WORKING_AREA(hipThreadStack, UTILITY_THREAD_STACK_SIZE);
|
||||
|
||||
static msg_t hipThread(void *arg) {
|
||||
int ret;
|
||||
UNUSED(arg);
|
||||
chRegSetThreadName("hip9011 init");
|
||||
chRegSetThreadName("hip9011 worker");
|
||||
|
||||
/* Acquire ownership of the bus. */
|
||||
spiAcquireBus(spi);
|
||||
// some time to let the hardware start
|
||||
Cs.setValue(true);
|
||||
chThdSleepMilliseconds(100);
|
||||
Cs.setValue(false);
|
||||
chThdSleepMilliseconds(100);
|
||||
Cs.setValue(true);
|
||||
/* Ownership release. */
|
||||
spiReleaseBus(spi);
|
||||
|
||||
while (true) {
|
||||
chThdSleepMilliseconds(100);
|
||||
/* init semaphore */
|
||||
chSemObjectInit(&wake, 10);
|
||||
|
||||
if (instance.needToInit) {
|
||||
hipStartupCode();
|
||||
instance.needToInit = false;
|
||||
chThdSleepMilliseconds(100);
|
||||
|
||||
do {
|
||||
/* retry until success */
|
||||
ret = hip_init();
|
||||
if (ret) {
|
||||
warning(CUSTOM_OBD_KNOCK_PROCESSOR, "TPIC/HIP does not respond: %d", ret);
|
||||
chThdSleepMilliseconds(10 * 1000);
|
||||
}
|
||||
} while (ret);
|
||||
|
||||
while (1) {
|
||||
msg_t msg;
|
||||
|
||||
/* load new/updated settings */
|
||||
instance.handleSettings(GET_RPM() DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
|
||||
/* State */
|
||||
instance.state = READY_TO_INTEGRATE;
|
||||
|
||||
msg = chSemWaitTimeout(&wake, TIME_INFINITE);
|
||||
if (msg == MSG_TIMEOUT) {
|
||||
/* ??? */
|
||||
} else {
|
||||
/* TODO: check for correct cylinder/input */
|
||||
if (1) {
|
||||
/* calculations */
|
||||
float knockVolts = instance.raw_value * adcToVolts(1) * CONFIG(analogInputDividerCoefficient);
|
||||
hipValueMax = maxF(knockVolts, hipValueMax);
|
||||
engine->knockLogic(knockVolts);
|
||||
|
||||
/* TunerStudio */
|
||||
tsOutputChannels.knockLevels[instance.cylinderNumber] = knockVolts;
|
||||
tsOutputChannels.knockLevel = knockVolts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Exported functions. */
|
||||
/*==========================================================================*/
|
||||
|
||||
void stopHip9001_pins() {
|
||||
intHold.deInit();
|
||||
Cs.deInit();
|
||||
|
@ -389,16 +339,13 @@ void startHip9001_pins() {
|
|||
|
||||
void initHip9011(Logging *sharedLogger) {
|
||||
logger = sharedLogger;
|
||||
addConsoleAction("hipinfo", showHipInfo);
|
||||
|
||||
if (!CONFIG(isHip9011Enabled))
|
||||
return;
|
||||
|
||||
|
||||
instance.setAngleWindowWidth();
|
||||
|
||||
#if EFI_PROD_CODE
|
||||
driver = getSpiDevice(engineConfiguration->hip9011SpiDevice);
|
||||
if (driver == NULL) {
|
||||
spi = getSpiDevice(CONFIG(hip9011SpiDevice));
|
||||
if (spi == NULL) {
|
||||
// error already reported
|
||||
return;
|
||||
}
|
||||
|
@ -409,22 +356,151 @@ void initHip9011(Logging *sharedLogger) {
|
|||
|
||||
startHip9001_pins();
|
||||
|
||||
/* load settings */
|
||||
instance.channelIdx = 0;
|
||||
instance.prescaler = CONFIG(hip9011PrescalerAndSDO);
|
||||
|
||||
scheduleMsg(logger, "Starting HIP9011/TPIC8101 driver");
|
||||
spiStart(driver, &hipSpiCfg);
|
||||
|
||||
instance.currentBandIndex = getBandIndex();
|
||||
chThdCreateStatic(hipThreadStack, sizeof(hipThreadStack), PRIO_HIP9011, (tfunc_t)(void*) hipThread, NULL);
|
||||
|
||||
// MISO PB14
|
||||
// palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(EFI_SPI2_AF) | PAL_STM32_PUDR_PULLUP);
|
||||
// MOSI PB15
|
||||
// palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(EFI_SPI2_AF) | PAL_STM32_OTYPE_OPENDRAIN);
|
||||
hip_addconsoleActions();
|
||||
}
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Debug functions. */
|
||||
/*==========================================================================*/
|
||||
|
||||
static void showHipInfo(void) {
|
||||
if (!CONFIG(isHip9011Enabled)) {
|
||||
scheduleMsg(logger, "hip9011 driver not active");
|
||||
return;
|
||||
}
|
||||
|
||||
scheduleMsg(logger, "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, " band idx=%d integrator idx=%d gain %.2f (idx %d) output=%s",
|
||||
instance.bandIdx,
|
||||
instance.intergratorIdx,
|
||||
engineConfiguration->hip9011Gain,
|
||||
instance.gainIdx,
|
||||
getAdc_channel_e(engineConfiguration->hipOutputChannel));
|
||||
|
||||
scheduleMsg(logger, " PaSDO=0x%x",
|
||||
instance.prescaler);
|
||||
|
||||
scheduleMsg(logger, " knockVThreshold=%.2f knockCount=%d maxKnockSubDeg=%.2f",
|
||||
engineConfiguration->knockVThreshold,
|
||||
engine->knockCount,
|
||||
engineConfiguration->maxKnockSubDeg);
|
||||
|
||||
scheduleMsg(logger, " spi=%s IntHold@%s(0x%x) correct response=%d incorrect response=%d (%s)",
|
||||
getSpi_device_e(engineConfiguration->hip9011SpiDevice),
|
||||
hwPortname(CONFIG(hip9011IntHoldPin)),
|
||||
CONFIG(hip9011IntHoldPinMode),
|
||||
instance.correctResponsesCount,
|
||||
instance.invalidResponsesCount,
|
||||
instance.invalidResponsesCount > 0 ? "NOT GOOD" : "ok");
|
||||
|
||||
#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",
|
||||
engineConfiguration->knockDetectionWindowStart,
|
||||
engineConfiguration->knockDetectionWindowEnd);
|
||||
|
||||
scheduleMsg(logger, "Status: overruns %d",
|
||||
instance.overrun);
|
||||
|
||||
hipValueMax = 0;
|
||||
engine->printKnockState();
|
||||
}
|
||||
|
||||
static void setMaxKnockSubDeg(int value) {
|
||||
engineConfiguration->maxKnockSubDeg = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
static void setKnockThresh(float value) {
|
||||
engineConfiguration->knockVThreshold = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
static void setPrescalerAndSDO(int value) {
|
||||
engineConfiguration->hip9011PrescalerAndSDO = value;
|
||||
}
|
||||
|
||||
static void setHipBand(float value) {
|
||||
engineConfiguration->knockBandCustom = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
static void setHipGain(float value) {
|
||||
engineConfiguration->hip9011Gain = value;
|
||||
showHipInfo();
|
||||
}
|
||||
|
||||
static void hip_addconsoleActions(void) {
|
||||
addConsoleAction("hipinfo", showHipInfo);
|
||||
addConsoleActionF("set_gain", setHipGain);
|
||||
addConsoleActionF("set_band", setHipBand);
|
||||
addConsoleActionI("set_hip_prescalerandsdo", setPrescalerAndSDO);
|
||||
addConsoleActionF("set_knock_threshold", setKnockThresh);
|
||||
addConsoleActionI("set_max_knock_sub_deg", setMaxKnockSubDeg);
|
||||
chThdCreateStatic(hipThreadStack, sizeof(hipThreadStack), PRIO_HIP9011, (tfunc_t)(void*) hipThread, NULL);
|
||||
}
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Boards specific functions. */
|
||||
/*==========================================================================*/
|
||||
/* TODO: move out oif here */
|
||||
void setHip9011FrankensoPinout(void) {
|
||||
/**
|
||||
* SPI on PB13/14/15
|
||||
*/
|
||||
// CONFIG(hip9011CsPin) = GPIOD_0; // rev 0.1
|
||||
|
||||
CONFIG(isHip9011Enabled) = true;
|
||||
engineConfiguration->hip9011PrescalerAndSDO = HIP_8MHZ_PRESCALER; // 8MHz chip
|
||||
CONFIG(is_enabled_spi_2) = true;
|
||||
// todo: convert this to rusEfi, hardware-independent enum
|
||||
#if EFI_PROD_CODE
|
||||
#ifdef EFI_HIP_CS_PIN
|
||||
CONFIG(hip9011CsPin) = EFI_HIP_CS_PIN;
|
||||
#else
|
||||
CONFIG(hip9011CsPin) = GPIOB_0; // rev 0.4
|
||||
#endif
|
||||
CONFIG(hip9011CsPinMode) = OM_OPENDRAIN;
|
||||
|
||||
CONFIG(hip9011IntHoldPin) = GPIOB_11;
|
||||
CONFIG(hip9011IntHoldPinMode) = OM_OPENDRAIN;
|
||||
|
||||
engineConfiguration->spi2SckMode = PO_OPENDRAIN; // 4
|
||||
engineConfiguration->spi2MosiMode = PO_OPENDRAIN; // 4
|
||||
engineConfiguration->spi2MisoMode = PO_PULLUP; // 32
|
||||
#endif /* EFI_PROD_CODE */
|
||||
|
||||
engineConfiguration->hip9011Gain = 1;
|
||||
engineConfiguration->knockVThreshold = 4;
|
||||
engineConfiguration->maxKnockSubDeg = 20;
|
||||
|
||||
|
||||
if (!CONFIG(useTpicAdvancedMode)) {
|
||||
engineConfiguration->hipOutputChannel = EFI_ADC_10; // PC0
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* EFI_HIP_9011 */
|
||||
|
|
|
@ -13,14 +13,10 @@
|
|||
void initHip9011(Logging *sharedLogger);
|
||||
void startHip9001_pins();
|
||||
void stopHip9001_pins();
|
||||
void setHip9011FrankensoPinout(void);
|
||||
#if HAL_USE_ADC
|
||||
void hipAdcCallback(adcsample_t value);
|
||||
#endif /* HAL_USE_ADC */
|
||||
void setHipGain(float value);
|
||||
void setHipBand(float value);
|
||||
void setPrescalerAndSDO(int value);
|
||||
void setKnockThresh(float value);
|
||||
void setMaxKnockSubDeg(int value);
|
||||
|
||||
void hip9011_startKnockSampling(uint8_t cylinderNumber, efitick_t nowNt);
|
||||
|
||||
void setHip9011FrankensoPinout(void);
|
||||
|
|
|
@ -6,49 +6,122 @@
|
|||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "engine.h"
|
||||
#include "hip9011_logic.h"
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Local definitions. */
|
||||
/*==========================================================================*/
|
||||
|
||||
#define DESIRED_OUTPUT_VALUE 5.0f
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Local variables and types. */
|
||||
/*==========================================================================*/
|
||||
|
||||
/**
|
||||
* These are HIP9011 magic values - integrator time constants in uS
|
||||
*/
|
||||
const int integratorValues[INT_LOOKUP_SIZE] = {
|
||||
/* 00 */ 40, 45, 50, 55, 60, 65, 70, 75,
|
||||
/* 08 */ 80, 90, 100, 110, 120, 130, 140, 150,
|
||||
/* 16 */160, 180, 200, 220, 240, 260, 280, 300,
|
||||
/* 24 */320, 360, 400, 440, 480, 520, 560, 600
|
||||
};
|
||||
|
||||
const float gainLookupInReverseOrder[GAIN_LOOKUP_SIZE] = {
|
||||
/* 00 */0.111, 0.118, 0.125, 0.129, 0.133, 0.138, 0.143, 0.148,
|
||||
/* 08 */0.154, 0.160, 0.167, 0.174, 0.182, 0.190, 0.200, 0.211,
|
||||
/* 16 */0.222, 0.236, 0.250, 0.258, 0.267, 0.276, 0.286, 0.296,
|
||||
/* 24 */0.308, 0.320, 0.333, 0.348, 0.364, 0.381, 0.400, 0.421,
|
||||
/* 32 */0.444, 0.471, 0.500, 0.548, 0.567, 0.586, 0.607, 0.630,
|
||||
/* 40 */0.654, 0.680, 0.708, 0.739, 0.773, 0.810, 0.850, 0.895,
|
||||
/* 48 */0.944, 1.000, 1.063, 1.143, 1.185, 1.231, 1.280, 1.333,
|
||||
/* 56 */1.391, 1.455, 1.523, 1.600, 1.684, 1.778, 1.882, 2.000
|
||||
};
|
||||
|
||||
const float bandFreqLookup[BAND_LOOKUP_SIZE] = {
|
||||
/* 00 */ 1.22, 1.26, 1.31, 1.35, 1.40, 1.45, 1.51, 1.57,
|
||||
/* 08 */ 1.63, 1.71, 1.78, 1.87, 1.96, 2.07, 2.18, 2.31,
|
||||
/* 16 */ 2.46, 2.54, 2.62, 2.71, 2.81, 2.92, 3.03, 3.15,
|
||||
/* 24 */ 3.28, 3.43, 3.59, 3.76, 3.95, 4.16, 4.39, 4.66,
|
||||
/* 32 */ 4.95, 5.12, 5.29, 5.48, 5.68, 5.90, 6.12, 6.37,
|
||||
/* 40 */ 6.64, 6.94, 7.27, 7.63, 8.02, 8.46, 8.95, 9.50,
|
||||
/* 48 */10.12, 10.46, 10.83, 11.22, 11.65, 12.10, 12.60, 13.14,
|
||||
/* 56 */13.72, 14.36, 15.07, 15.84, 16.71, 17.67, 18.76, 19.98
|
||||
};
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Forward declarations */
|
||||
/*==========================================================================*/
|
||||
|
||||
EXTERN_ENGINE;
|
||||
|
||||
HIP9011::HIP9011(Hip9011HardwareInterface *hardware) : rpmLookup() {
|
||||
this->hardware = hardware;
|
||||
/*==========================================================================*/
|
||||
/* Exported. */
|
||||
/*==========================================================================*/
|
||||
|
||||
HIP9011::HIP9011(Hip9011HardwareInterface *hardware) {
|
||||
this->hw = hardware;
|
||||
}
|
||||
|
||||
void HIP9011::setStateAndCommand(unsigned char cmd) {
|
||||
this->state = IS_SENDING_SPI_COMMAND;
|
||||
hardware->sendCommand(cmd);
|
||||
int HIP9011::sendCommand(uint8_t cmd) {
|
||||
return hw->sendSyncCommand(cmd, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return frequency band we are interested in
|
||||
*/
|
||||
float getHIP9011Band(DEFINE_HIP_PARAMS) {
|
||||
float HIP9011::getBand(DEFINE_HIP_PARAMS) {
|
||||
return GET_CONFIG_VALUE(knockBandCustom) == 0 ?
|
||||
BAND(GET_CONFIG_VALUE(cylinderBore)) : GET_CONFIG_VALUE(knockBandCustom);
|
||||
HIP9011_BAND(GET_CONFIG_VALUE(cylinderBore)) :
|
||||
GET_CONFIG_VALUE(knockBandCustom);
|
||||
}
|
||||
|
||||
int getBandIndex(DEFINE_HIP_PARAMS) {
|
||||
float freq = getHIP9011Band(FORWARD_HIP_PARAMS);
|
||||
return getHip9011BandIndex(freq);
|
||||
int HIP9011::getBandIndex(DEFINE_HIP_PARAMS) {
|
||||
float freq = getBand(FORWARD_HIP_PARAMS);
|
||||
int i = findIndexMsg("freq", bandFreqLookup, BAND_LOOKUP_SIZE, freq);
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (i > BAND_LOOKUP_SIZE - 1)
|
||||
i = BAND_LOOKUP_SIZE - 1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int getHip9011GainIndex(DEFINE_HIP_PARAMS) {
|
||||
int i = GAIN_INDEX(GET_CONFIG_VALUE(hip9011Gain));
|
||||
// GAIN_LOOKUP_SIZE is returned for index which is too low
|
||||
return i == GAIN_LOOKUP_SIZE ? GAIN_LOOKUP_SIZE - 1 : i;
|
||||
int HIP9011::getGainIndex(DEFINE_HIP_PARAMS) {
|
||||
int i = findIndexMsg("fGain", gainLookupInReverseOrder, GAIN_LOOKUP_SIZE, GET_CONFIG_VALUE(hip9011Gain));
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (i > GAIN_LOOKUP_SIZE - 1)
|
||||
i = GAIN_LOOKUP_SIZE - 1;
|
||||
|
||||
/* reverse order */
|
||||
return GAIN_LOOKUP_SIZE - 1 - i;
|
||||
}
|
||||
|
||||
int getHip9011GainIndex(float gain) {
|
||||
int i = GAIN_INDEX(gain);
|
||||
// GAIN_LOOKUP_SIZE is returned for index which is too low
|
||||
return i == GAIN_LOOKUP_SIZE ? GAIN_LOOKUP_SIZE - 1 : i;
|
||||
/**
|
||||
* 'TC is typically TINT/(2*Pi*VOUT)'
|
||||
* Knock Sensor Training TPIC8101, page 24
|
||||
*/
|
||||
float HIP9011::getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth) {
|
||||
/**
|
||||
* TINT = TC * 2 * PI * VOUT
|
||||
*/
|
||||
float integrationTimeUs = timeUs * 2 * PIF * DESIRED_OUTPUT_VALUE;
|
||||
/**
|
||||
* rpm = 60 seconds / time
|
||||
* '60000000' because revolutions per MINUTE in uS conversion
|
||||
*/
|
||||
float windowWidthMult = angleWindowWidth / 360.0f;
|
||||
return 60000000.0f / integrationTimeUs * windowWidthMult;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* We know the set of possible integration times, we know the knock detection window width
|
||||
*/
|
||||
void HIP9011::prepareHip9011RpmLookup(float angleWindowWidth) {
|
||||
void HIP9011::prepareRpmLookup(void) {
|
||||
/**
|
||||
* out binary search method needs increasing order thus the reverse order here
|
||||
*/
|
||||
|
@ -63,44 +136,50 @@ int HIP9011::getIntegrationIndexByRpm(float rpm) {
|
|||
}
|
||||
|
||||
void HIP9011::setAngleWindowWidth(DEFINE_HIP_PARAMS) {
|
||||
float angleWindowWidth = GET_CONFIG_VALUE(knockDetectionWindowEnd) - GET_CONFIG_VALUE(knockDetectionWindowStart);
|
||||
if (angleWindowWidth < 0) {
|
||||
float new_angleWindowWidth =
|
||||
GET_CONFIG_VALUE(knockDetectionWindowEnd) -
|
||||
GET_CONFIG_VALUE(knockDetectionWindowStart);
|
||||
if (new_angleWindowWidth < 0) {
|
||||
#if EFI_PROD_CODE
|
||||
warning(CUSTOM_KNOCK_WINDOW, "invalid knock window");
|
||||
#endif
|
||||
angleWindowWidth = 0;
|
||||
new_angleWindowWidth = 0;
|
||||
}
|
||||
// float '==' is totally appropriate here
|
||||
if (this->angleWindowWidth == angleWindowWidth)
|
||||
if (angleWindowWidth == new_angleWindowWidth)
|
||||
return; // exit if value has not change
|
||||
this->angleWindowWidth = angleWindowWidth;
|
||||
prepareHip9011RpmLookup(angleWindowWidth);
|
||||
angleWindowWidth = new_angleWindowWidth;
|
||||
prepareRpmLookup();
|
||||
}
|
||||
|
||||
void HIP9011::handleValue(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)) {
|
||||
void HIP9011::handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)) {
|
||||
int ret;
|
||||
|
||||
setAngleWindowWidth(FORWARD_HIP_PARAMS);
|
||||
|
||||
int prescalerIndex = GET_CONFIG_VALUE(hip9011PrescalerAndSDO);
|
||||
int integratorIndex = getIntegrationIndexByRpm(rpm);
|
||||
int gainIndex = getHip9011GainIndex(FORWARD_HIP_PARAMS);
|
||||
int bandIndex = getBandIndex(FORWARD_HIP_PARAMS);
|
||||
int new_prescaler = GET_CONFIG_VALUE(hip9011PrescalerAndSDO);
|
||||
int new_integratorIdx = getIntegrationIndexByRpm(rpm);
|
||||
int new_gainIdx = getGainIndex(FORWARD_HIP_PARAMS);
|
||||
int new_bandIdx = getBandIndex(FORWARD_HIP_PARAMS);
|
||||
|
||||
if (currentGainIndex != gainIndex) {
|
||||
currentGainIndex = gainIndex;
|
||||
setStateAndCommand(SET_GAIN_CMD(gainIndex));
|
||||
|
||||
} else if (currentIntergratorIndex != integratorIndex) {
|
||||
currentIntergratorIndex = integratorIndex;
|
||||
setStateAndCommand(SET_INTEGRATOR_CMD(integratorIndex));
|
||||
} else if (currentBandIndex != bandIndex) {
|
||||
currentBandIndex = bandIndex;
|
||||
setStateAndCommand(SET_BAND_PASS_CMD(bandIndex));
|
||||
} else if (currentPrescaler != prescalerIndex) {
|
||||
currentPrescaler = prescalerIndex;
|
||||
setStateAndCommand(SET_PRESCALER_CMD(prescalerIndex));
|
||||
|
||||
} else {
|
||||
state = READY_TO_INTEGRATE;
|
||||
if (gainIdx != new_gainIdx) {
|
||||
ret = sendCommand(SET_GAIN_CMD(new_gainIdx));
|
||||
if (ret == 0)
|
||||
gainIdx = new_gainIdx;
|
||||
}
|
||||
if (intergratorIdx != new_integratorIdx) {
|
||||
ret = sendCommand(SET_INTEGRATOR_CMD(new_integratorIdx));
|
||||
if (ret == 0)
|
||||
intergratorIdx = new_integratorIdx;
|
||||
}
|
||||
if (bandIdx != new_bandIdx) {
|
||||
ret = sendCommand(SET_BAND_PASS_CMD(new_bandIdx));
|
||||
if (ret == 0)
|
||||
bandIdx = new_bandIdx;
|
||||
}
|
||||
if (prescaler != new_prescaler) {
|
||||
ret = sendCommand(SET_PRESCALER_CMD(new_prescaler));
|
||||
if (ret == 0)
|
||||
prescaler = new_prescaler;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
|
||||
#include "efifeatures.h"
|
||||
#include "rusefi_enums.h"
|
||||
#include "hip9011_lookup.h"
|
||||
|
||||
#define BAND(bore) (900 / (PIF * (bore) / 2))
|
||||
#define PIF 3.14159f
|
||||
#define HIP9011_BAND(bore) (900 / (PIF * (bore) / 2))
|
||||
|
||||
#define INT_LOOKUP_SIZE 32
|
||||
#define GAIN_LOOKUP_SIZE 64
|
||||
#define BAND_LOOKUP_SIZE 64
|
||||
|
||||
/**
|
||||
* this interface defines hardware communication layer for HIP9011 chip
|
||||
*/
|
||||
class Hip9011HardwareInterface {
|
||||
public:
|
||||
virtual void sendSyncCommand(unsigned char command) = 0;
|
||||
virtual void sendCommand(unsigned char command) = 0;
|
||||
virtual int sendSyncCommand(unsigned char command, uint8_t *rx_ptr) = 0;
|
||||
};
|
||||
|
||||
#if EFI_PROD_CODE || EFI_SIMULATOR
|
||||
|
@ -59,26 +62,31 @@ public:
|
|||
class HIP9011 {
|
||||
public:
|
||||
explicit HIP9011(Hip9011HardwareInterface *hardware);
|
||||
void prepareHip9011RpmLookup(float angleWindowWidth);
|
||||
int getIntegrationIndexByRpm(float rpm);
|
||||
void setStateAndCommand(unsigned char cmd);
|
||||
void setAngleWindowWidth(DEFINE_HIP_PARAMS);
|
||||
void handleValue(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS));
|
||||
int sendCommand(uint8_t cmd);
|
||||
|
||||
float getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth);
|
||||
void prepareRpmLookup(void);
|
||||
void setAngleWindowWidth(DEFINE_HIP_PARAMS);
|
||||
void handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS));
|
||||
float getBand(DEFINE_HIP_PARAMS);
|
||||
int getIntegrationIndexByRpm(float rpm);
|
||||
int getBandIndex(DEFINE_HIP_PARAMS);
|
||||
int getGainIndex(DEFINE_HIP_PARAMS);
|
||||
|
||||
/* Settings loaded to chip */
|
||||
uint8_t intergratorIdx = 0xff;
|
||||
uint8_t bandIdx = 0xff;
|
||||
uint8_t prescaler = 0xff;
|
||||
uint8_t gainIdx = 0xff;
|
||||
uint8_t channelIdx = 0xff;
|
||||
|
||||
/**
|
||||
* band index is only send to HIP chip on startup
|
||||
*/
|
||||
int currentBandIndex = 0;
|
||||
int currentGainIndex = -1;
|
||||
int correctResponsesCount = 0;
|
||||
int invalidHip9011ResponsesCount = 0;
|
||||
int invalidResponsesCount = 0;
|
||||
float angleWindowWidth = - 1;
|
||||
|
||||
int currentIntergratorIndex = -1;
|
||||
bool needToInit = true;
|
||||
int totalKnockEventsCount = 0;
|
||||
int currentPrescaler = 0;
|
||||
Hip9011HardwareInterface *hardware;
|
||||
Hip9011HardwareInterface *hw;
|
||||
bool adv_mode = false;
|
||||
/**
|
||||
* Int/Hold pin is controlled from scheduler call-backs which are set according to current RPM
|
||||
*
|
||||
|
@ -91,6 +99,7 @@ public:
|
|||
*/
|
||||
hip_state_e state;
|
||||
uint8_t cylinderNumber;
|
||||
int raw_value;
|
||||
|
||||
/* error counters */
|
||||
int overrun = 0;
|
||||
|
@ -98,10 +107,6 @@ public:
|
|||
float rpmLookup[INT_LOOKUP_SIZE];
|
||||
};
|
||||
|
||||
float getHIP9011Band(DEFINE_HIP_PARAMS);
|
||||
int getBandIndex(DEFINE_HIP_PARAMS);
|
||||
int getHip9011GainIndex(DEFINE_HIP_PARAMS);
|
||||
|
||||
// 0b010x.xxxx
|
||||
#define SET_PRESCALER_CMD(v) (0x40 | ((v) & 0x1f))
|
||||
// 0b1110.000x
|
||||
|
|
|
@ -38,8 +38,11 @@ typedef uint16_t adcsample_t;
|
|||
#define spiExchange(x,y,w,z) {}
|
||||
#define spiExchangeI(x,y,w,z) {}
|
||||
#define spiStartExchangeI(x,y,w,z) {}
|
||||
#define spiStartExchange(x,y,w,z) {}
|
||||
#define spiUnselect(x) {}
|
||||
#define spiUnselectI(x) {}
|
||||
#define spiAcquireBus(x) {}
|
||||
#define spiReleaseBus(x) {}
|
||||
// end of mock SPI
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -5,30 +5,33 @@
|
|||
*/
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
#include "hip9011_lookup.h"
|
||||
#include "hip9011_logic.h"
|
||||
#include "test_parameters.h"
|
||||
using ::testing::_;
|
||||
|
||||
TEST(hip9011, lookup) {
|
||||
assertEqualsM2("", 3183.1013, getRpmByAngleWindowAndTimeUs(600, 360), 0.1);
|
||||
assertEqualsM2("40us", 47746.5195, getRpmByAngleWindowAndTimeUs(40, 360), 0.1);
|
||||
HIP9011 instance(NULL);
|
||||
|
||||
assertEqualsM2("600us 50 degree", 442.0974, getRpmByAngleWindowAndTimeUs(600, 50), 0.1);
|
||||
assertEqualsM2("240us 50 degree", 1105.2435, getRpmByAngleWindowAndTimeUs(240, 50), 0.1);
|
||||
assertEqualsM2("240us 50 degree", 6631.4619, getRpmByAngleWindowAndTimeUs(40, 50), 0.1);
|
||||
assertEqualsM2("", 3183.1013, instance.getRpmByAngleWindowAndTimeUs(600, 360), 0.1);
|
||||
assertEqualsM2("40us", 47746.5195, instance.getRpmByAngleWindowAndTimeUs(40, 360), 0.1);
|
||||
|
||||
EXPECT_EQ(0, getHip9011GainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/3, 0, NAN, NAN));
|
||||
EXPECT_EQ(0, getHip9011GainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/2, 0, NAN, NAN));
|
||||
EXPECT_EQ(47, getHip9011GainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/0.234, 0, NAN, NAN));
|
||||
EXPECT_EQ(63, getHip9011GainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/0.000001, 0, NAN, NAN));
|
||||
assertEqualsM2("600us 50 degree", 442.0974, instance.getRpmByAngleWindowAndTimeUs(600, 50), 0.1);
|
||||
assertEqualsM2("240us 50 degree", 1105.2435, instance.getRpmByAngleWindowAndTimeUs(240, 50), 0.1);
|
||||
assertEqualsM2("240us 50 degree", 6631.4619, instance.getRpmByAngleWindowAndTimeUs(40, 50), 0.1);
|
||||
|
||||
EXPECT_EQ(0, instance.getGainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/3, 0, NAN, NAN));
|
||||
EXPECT_EQ(0, instance.getGainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/2, 0, NAN, NAN));
|
||||
EXPECT_EQ(47, instance.getGainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/0.234, 0, NAN, NAN));
|
||||
EXPECT_EQ(63, instance.getGainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/0.000001, 0, NAN, NAN));
|
||||
EXPECT_EQ(63, instance.getGainIndex(/* knockBandCustom*/NAN, /*cylinderBore*/NAN, /*hip9011Gain*/-1.0, 0, NAN, NAN));
|
||||
|
||||
}
|
||||
|
||||
TEST(hip9011, rpmLookup) {
|
||||
HIP9011 instance(NULL);
|
||||
|
||||
instance.prepareHip9011RpmLookup(50);
|
||||
instance.angleWindowWidth = 50.0;
|
||||
instance.prepareRpmLookup();
|
||||
|
||||
EXPECT_EQ(31, instance.getIntegrationIndexByRpm(1));
|
||||
EXPECT_EQ(21, instance.getIntegrationIndexByRpm(1100));
|
||||
|
@ -37,11 +40,12 @@ TEST(hip9011, rpmLookup) {
|
|||
}
|
||||
|
||||
TEST(hip9011, band) {
|
||||
HIP9011 instance(NULL);
|
||||
|
||||
EXPECT_FLOAT_EQ(3, getHIP9011Band(/* knockBandCustom*/3, /*cylinderBore*/76, /*hip9011Gain*/NAN, 0, NAN, NAN));
|
||||
EXPECT_FLOAT_EQ(7.5389242, getHIP9011Band(/* knockBandCustom*/0, /*cylinderBore*/76, /*hip9011Gain*/NAN, 0, NAN, NAN));
|
||||
EXPECT_FLOAT_EQ(3, instance.getBand(/* knockBandCustom*/3, /*cylinderBore*/76, /*hip9011Gain*/NAN, 0, NAN, NAN));
|
||||
EXPECT_FLOAT_EQ(7.5389242, instance.getBand(/* knockBandCustom*/0, /*cylinderBore*/76, /*hip9011Gain*/NAN, 0, NAN, NAN));
|
||||
|
||||
EXPECT_EQ(42, getBandIndex(/* knockBandCustom*/0, /*cylinderBore*/76, /*hip9011Gain*/NAN, 0, NAN, NAN));
|
||||
EXPECT_EQ(42, instance.getBandIndex(/* knockBandCustom*/0, /*cylinderBore*/76, /*hip9011Gain*/NAN, 0, NAN, NAN));
|
||||
|
||||
}
|
||||
|
||||
|
@ -50,8 +54,7 @@ class MockHip9011Hardware : public Hip9011HardwareInterface
|
|||
public:
|
||||
MockHip9011Hardware() { }
|
||||
|
||||
MOCK_METHOD1(sendSyncCommand, void(unsigned char));
|
||||
MOCK_METHOD1(sendCommand, void(unsigned char));
|
||||
MOCK_METHOD2(sendSyncCommand, int(unsigned char, unsigned char *));
|
||||
};
|
||||
|
||||
TEST(hip9011, configurationCommands) {
|
||||
|
@ -64,24 +67,13 @@ TEST(hip9011, configurationCommands) {
|
|||
#define PARAMETERS 600, /* knockBandCustom*/0, /*cylinderBore*/76, /*hip9011Gain*/1, HIP_8MHZ_PRESCALER, 0.0, 50.0
|
||||
|
||||
// Not making assumptions on the message send ...
|
||||
EXPECT_CALL(mock, sendSyncCommand(_)).Times(0);
|
||||
EXPECT_CALL(mock, sendCommand(SET_GAIN_CMD(0xE))).Times(1);
|
||||
instance.handleValue(PARAMETERS);
|
||||
|
||||
EXPECT_CALL(mock, sendSyncCommand(_)).Times(0);
|
||||
EXPECT_CALL(mock, sendCommand(SET_INTEGRATOR_CMD(0x1C))).Times(1);
|
||||
instance.handleValue(PARAMETERS);
|
||||
|
||||
EXPECT_CALL(mock, sendSyncCommand(_)).Times(0);
|
||||
EXPECT_CALL(mock, sendCommand(SET_BAND_PASS_CMD(0x2A))).Times(1);
|
||||
instance.handleValue(PARAMETERS);
|
||||
|
||||
EXPECT_CALL(mock, sendSyncCommand(_)).Times(0);
|
||||
EXPECT_CALL(mock, sendCommand(SET_PRESCALER_CMD(6))).Times(1);
|
||||
instance.handleValue(PARAMETERS);
|
||||
EXPECT_CALL(mock, sendSyncCommand(SET_GAIN_CMD(0xE), 0)).Times(1);
|
||||
EXPECT_CALL(mock, sendSyncCommand(SET_INTEGRATOR_CMD(0x1C), 0)).Times(1);
|
||||
EXPECT_CALL(mock, sendSyncCommand(SET_BAND_PASS_CMD(0x2A), 0)).Times(1);
|
||||
EXPECT_CALL(mock, sendSyncCommand(SET_PRESCALER_CMD(6), 0)).Times(1);
|
||||
instance.handleSettings(PARAMETERS);
|
||||
|
||||
// initialization is over, no commands should be sent
|
||||
EXPECT_CALL(mock, sendSyncCommand(_)).Times(0);
|
||||
EXPECT_CALL(mock, sendCommand(_)).Times(0);
|
||||
instance.handleValue(PARAMETERS);
|
||||
EXPECT_CALL(mock, sendSyncCommand(_, _)).Times(0);
|
||||
instance.handleSettings(PARAMETERS);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue