rusefi/firmware/hw_layer/sensors/hip9011_logic.cpp

257 lines
7.8 KiB
C++

/*
* @file HIP9011_logic.cpp
*
* Created on: Jan 3, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "pch.h"
/* getCylinderKnockBank */
#include "knock_logic.h"
#include "hip9011_logic.h"
/*==========================================================================*/
/* Local definitions. */
/*==========================================================================*/
/*==========================================================================*/
/* 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 */
/*==========================================================================*/
/*==========================================================================*/
/* Exported. */
/*==========================================================================*/
HIP9011::HIP9011(Hip9011HardwareInterface *hardware) {
this->hw = hardware;
}
int HIP9011::sendCommand(uint8_t cmd) {
return hw->sendSyncCommand(cmd, NULL);
}
int HIP9011::sendCommandGetReply(uint8_t cmd, uint8_t *reply) {
return hw->sendSyncCommand(cmd, reply);
}
/**
* @return frequency band we are interested in
*/
float HIP9011::getBand(DEFINE_HIP_PARAMS) {
return GET_CONFIG_VALUE(knockBandCustom) == 0 ?
HIP9011_BAND(GET_CONFIG_VALUE(cylinderBore)) :
GET_CONFIG_VALUE(knockBandCustom);
}
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 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;
}
/**
* 'TC is typically TINT/(2*Pi*VOUT)'
* Knock Sensor Training TPIC8101, page 24
*/
float HIP9011::getRpmByAngleWindowAndTimeUs(int timeUs, float p_angleWindowWidth) {
/**
* TINT = TC * 2 * PI * VOUT
*/
float integrationTimeUs = timeUs * 2 * CONST_PI * HIP9011_ANALOG_OUTPUT_MAX;
/**
* rpm = 60 seconds / time
* '60000000' because revolutions per MINUTE in uS conversion
*/
float windowWidthMult = p_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::prepareRpmLookup(void) {
/**
* out binary search method needs increasing order thus the reverse order here
*/
for (int i = 0; i < INT_LOOKUP_SIZE; i++) {
rpmLookup[i] = getRpmByAngleWindowAndTimeUs(integratorValues[INT_LOOKUP_SIZE - i - 1], angleWindowWidth);
}
}
int HIP9011::getIntegrationIndexByRpm(float rpm) {
int i = findIndexMsg("getIbR", rpmLookup, INT_LOOKUP_SIZE, (rpm));
return i == -1 ? INT_LOOKUP_SIZE - 1 : INT_LOOKUP_SIZE - i - 1;
}
void HIP9011::setAngleWindowWidth(DEFINE_HIP_PARAMS) {
float new_angleWindowWidth =
GET_CONFIG_VALUE(knockDetectionWindowEnd) -
GET_CONFIG_VALUE(knockDetectionWindowStart);
if (new_angleWindowWidth < 0) {
#if EFI_PROD_CODE
warning(ObdCode::CUSTOM_KNOCK_WINDOW, "invalid knock window");
#endif
new_angleWindowWidth = 0;
}
// float '==' is totally appropriate here
if (angleWindowWidth == new_angleWindowWidth)
return; // exit if value has not change
angleWindowWidth = new_angleWindowWidth;
prepareRpmLookup();
}
void HIP9011::handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)) {
int ret;
setAngleWindowWidth(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 (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;
}
}
int HIP9011::cylinderToChannelIdx(int cylinder) {
/* TODO: hip9011 inputs to bank mapping? */
return getCylinderKnockBank(cylinder);
}
int HIP9011::handleChannel(DEFINE_HIP_PARAMS) {
int ret;
/* we did not receive any callback from spark logic with valid cylinder yet */
if (cylinderNumber < 0)
return -1;
/* find next firing cylinder */
/* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */
expectedCylinderNumber = getNextFiringCylinderId((cylinderNumber + 1)) - 1;
int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber);
if (nextChannelIdx == channelIdx)
return 0;
ret = sendCommand(SET_CHANNEL_CMD(nextChannelIdx));
if (ret)
return ret;
channelIdx = nextChannelIdx;
return 0;
}
int HIP9011::readValueAndHandleChannel(DEFINE_HIP_PARAMS) {
int ret;
uint8_t rx[2];
/* we did not receive any callback from spark logic with valid cylinder yet */
if (cylinderNumber < 0)
return -1;
/* find next firing cylinder */
/* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */
expectedCylinderNumber = getNextFiringCylinderId((cylinderNumber + 1)) - 1;
int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber);
/* use cached values, let handleSettings take care of settings update */
/* don't care about rx'ed data now */
ret = sendCommand(SET_PRESCALER_CMD(prescaler));
if (ret)
return ret;
/* reply from Set Prescaler CMD -> D7 to D0 of the digital integrator output */
ret = sendCommandGetReply(SET_CHANNEL_CMD(nextChannelIdx), &rx[0]);
if (ret)
return ret;
/* Same connand to get reply for previous command:
* reply from Select the channel CMD -> D9 to D8 of difital integrator output and six zeroes */
ret = sendCommandGetReply(SET_CHANNEL_CMD(nextChannelIdx), &rx[1]);
if (ret)
return ret;
channelIdx = nextChannelIdx;
/* D9..D8 in high bits */
rx[1] = (rx[1] >> 6) & 0x03;
/* return digital integrator value */
return (rx[0] | (rx[1] << 8));
}