hip9011 update (#2653)

* hip9011: add check for SPI reply in advanced mode

* hip9011: read value over SPI in advanced mode
This commit is contained in:
Andrey G 2021-05-08 16:50:28 +03:00 committed by GitHub
parent 0d63fd04c5
commit afcc8848c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 189 additions and 39 deletions

View File

@ -67,6 +67,13 @@ static NamedOutputPin Cs(PROTOCOL_HIP_NAME);
class Hip9011Hardware : public Hip9011HardwareInterface {
int sendSyncCommand(uint8_t command, uint8_t *rx_ptr) override;
private:
int checkResponseDefMode(uint8_t tx, uint8_t rx);
int checkResponseAdvMode(uint8_t tx, uint8_t rx);
uint8_t rep_mask;
uint8_t rep_value;
};
/* TODO: include following stuff in object */
@ -77,7 +84,8 @@ static SPIDriver *spi;
static Hip9011Hardware hardware;
static float hipValueMax = 0;
static float normalizedValue[HIP_INPUT_CHANNELS];
static float normalizedValueMax[HIP_INPUT_CHANNELS];
HIP9011 instance(&hardware);
@ -114,7 +122,7 @@ static void hip_addconsoleActions(void);
/* Local functions. */
/*==========================================================================*/
static int checkResponseDefMode(uint8_t tx, uint8_t rx) {
int Hip9011Hardware::checkResponseDefMode(uint8_t tx, uint8_t rx) {
/* in default SPI mode SDO is directly equals the SDI (echo function) */
if (tx == rx) {
return 0;
@ -123,10 +131,41 @@ static int checkResponseDefMode(uint8_t tx, uint8_t rx) {
}
}
static int checkResponseAdvMode(uint8_t tx, uint8_t rx) {
UNUSED(tx); UNUSED(rx);
/* TODO: no check for advanced mode yet */
return 0;
int Hip9011Hardware::checkResponseAdvMode(uint8_t tx, uint8_t rx) {
int ret = 0;
/* check reply */
if ((rx & rep_mask) != rep_value)
ret = -1;
/* extract mask and value for next reply */
if ((tx & 0xe0) == SET_PRESCALER_CMD(0)){
/* D7 to D0 of digital integrator output */
rep_mask = 0x00;
rep_value = 0x00;
} else if ((tx & 0xfe) == SET_CHANNEL_CMD(0)) {
/* D9 to D8 of digital integrator output and six zeroes */
rep_mask = 0x3f;
rep_value = 0x00;
} else if ((tx & 0xc0) == SET_BAND_PASS_CMD(0)) {
rep_mask = 0xff;
rep_value = SET_BAND_PASS_REP;
} else if ((tx & 0xc0) == SET_GAIN_CMD(0)) {
rep_mask = 0xff;
rep_value = SET_GAIN_REP;
} else if ((tx & 0xe0) == SET_INTEGRATOR_CMD(0)) {
rep_mask = 0xff;
rep_value = SET_INTEGRATOR_REP;
} else if ((tx & 0xff) == SET_ADVANCED_MODE_CMD) {
rep_mask = 0xff;
rep_value = SET_ADVANCED_MODE_REP;
} else {
/* unknown */
rep_mask = 0x00;
rep_value = 0x00;
}
return ret;
}
int Hip9011Hardware::sendSyncCommand(uint8_t tx, uint8_t *rx_ptr) {
@ -149,10 +188,10 @@ int Hip9011Hardware::sendSyncCommand(uint8_t tx, uint8_t *rx_ptr) {
if (rx_ptr)
*rx_ptr = rx;
/* check response */
if (instance.adv_mode == false)
ret = checkResponseDefMode(tx, rx);
else
if (instance.adv_mode)
ret = checkResponseAdvMode(tx, rx);
else
ret = checkResponseDefMode(tx, rx);
/* statistic counters */
if (ret)
@ -201,7 +240,14 @@ static void endIntegration(void *) {
*/
if (instance.state == IS_INTEGRATING) {
intHold.setLow();
instance.state = WAITING_FOR_ADC_TO_SKIP;
if (instance.adv_mode) {
/* read value over SPI in thread mode */
instance.state = NOT_READY;
hip_wake_driver();
} else {
/* wait for ADC samples */
instance.state = WAITING_FOR_ADC_TO_SKIP;
}
}
}
@ -240,11 +286,16 @@ void hip9011_startKnockSampling(uint8_t cylinderNumber, efitick_t nowNt) {
}
void hipAdcCallback(adcsample_t adcValue) {
/* we read in digital mode */
if (instance.adv_mode)
return;
if (instance.state == WAITING_FOR_ADC_TO_SKIP) {
instance.state = WAITING_FOR_RESULT_ADC;
} else if (instance.state == WAITING_FOR_RESULT_ADC) {
/* offload calculations to driver thread */
instance.raw_value = adcValue;
if (instance.channelIdx < HIP_INPUT_CHANNELS) {
instance.rawValue[instance.channelIdx] = adcValue;
}
instance.state = NOT_READY;
hip_wake_driver();
}
@ -368,8 +419,11 @@ 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));
/* in advanced more driver will set channel while reading integrator value */
if (!instance.adv_mode) {
/* switch input channel */
instance.handleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
}
/* State */
instance.state = READY_TO_INTEGRATE;
@ -377,11 +431,50 @@ static msg_t hipThread(void *arg) {
if (msg == MSG_TIMEOUT) {
/* ??? */
} else {
int rawValue;
/* check now, before readValueAndHandleChannel did not overwrite expectedCylinderNumber */
bool correctCylinder = (instance.cylinderNumber == instance.expectedCylinderNumber);
/* this needs to be called in any case to set proper channel for next cycle */
if (instance.adv_mode) {
rawValue = instance.readValueAndHandleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
/* spi communication issue? */
if (rawValue < 0)
continue;
}
/* check that we know channel for current measurement */
int idx = instance.channelIdx;
if (!(idx < HIP_INPUT_CHANNELS))
continue;
float knockNormalized = 0.0f;
float knockVolts = 0.0f;
/* calculations */
if (instance.adv_mode) {
/* store for debug */
instance.rawValue[idx] = rawValue;
/* convert 10 bit integer value to 0.0 .. 1.0 float */
knockNormalized = ((float)rawValue) / HIP9011_DIGITAL_OUTPUT_MAX;
/* convert to magic volts */
knockVolts = knockNormalized * HIP9011_DESIRED_OUTPUT_VALUE;
} else {
rawValue = instance.rawValue[idx];
/* first calculate ouput volts */
knockVolts = adcToVolts(rawValue) * CONFIG(analogInputDividerCoefficient);
/* and then normalize */
knockNormalized = knockVolts / HIP9011_DESIRED_OUTPUT_VALUE;
}
/* Check for correct cylinder/input */
if (instance.cylinderNumber == instance.expectedCylinderNumber) {
/* calculations */
float knockVolts = instance.raw_value * adcToVolts(1) * CONFIG(analogInputDividerCoefficient);
hipValueMax = maxF(knockVolts, hipValueMax);
if (correctCylinder) {
/* debug */
normalizedValue[idx] = knockNormalized;
normalizedValueMax[idx] = maxF(knockNormalized, normalizedValueMax[idx]);
/* report */
engine->knockLogic(knockVolts);
/* TunerStudio */
@ -486,10 +579,6 @@ static void showHipInfo(void) {
engine->knockCount,
engineConfiguration->maxKnockSubDeg);
efiPrintf(" Adc input %s (%.2f V)",
getAdc_channel_e(engineConfiguration->hipOutputChannel),
getVoltage("hipinfo", engineConfiguration->hipOutputChannel));
efiPrintf(" IntHold %s (mode 0x%x)",
hwPortname(CONFIG(hip9011IntHoldPin)),
CONFIG(hip9011IntHoldPinMode));
@ -503,22 +592,32 @@ static void showHipInfo(void) {
printSpiConfig("hip9011", CONFIG(hip9011SpiDevice));
#endif /* EFI_PROD_CODE */
efiPrintf(" SPI good response %d incorrect response %d",
efiPrintf(" SPI: good response %d incorrect response %d",
instance.correctResponsesCount,
instance.invalidResponsesCount);
efiPrintf(" hip %.2f vmax=%.2f",
engine->knockVolts,
hipValueMax);
efiPrintf(" Counters: samples %d overruns %d sync miss %d",
instance.samples, instance.overrun, instance.unsync);
efiPrintf(" Window start %.2f end %.2f",
engineConfiguration->knockDetectionWindowStart,
engineConfiguration->knockDetectionWindowEnd);
efiPrintf(" Counters: samples %d overruns %d sync miss %d",
instance.samples, instance.overrun, instance.unsync);
if (!instance.adv_mode) {
efiPrintf(" Adc input %s (%.2f V)",
getAdc_channel_e(engineConfiguration->hipOutputChannel),
getVoltage("hipinfo", engineConfiguration->hipOutputChannel));
}
for (int i = 0; i < HIP_INPUT_CHANNELS; i++) {
efiPrintf(" input[%d] %d -> %.3f (max %.3f)",
i,
instance.rawValue[i],
normalizedValue[i],
normalizedValueMax[i]);
normalizedValueMax[i] = 0.0;
}
hipValueMax = 0;
engine->printKnockState();
}

View File

@ -17,8 +17,6 @@
/* Local definitions. */
/*==========================================================================*/
#define DESIRED_OUTPUT_VALUE 5.0f
/*==========================================================================*/
/* Local variables and types. */
/*==========================================================================*/
@ -73,6 +71,10 @@ 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
*/
@ -112,7 +114,7 @@ float HIP9011::getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth)
/**
* TINT = TC * 2 * PI * VOUT
*/
float integrationTimeUs = timeUs * 2 * PIF * DESIRED_OUTPUT_VALUE;
float integrationTimeUs = timeUs * 2 * PIF * HIP9011_DESIRED_OUTPUT_VALUE;
/**
* rpm = 60 seconds / time
* '60000000' because revolutions per MINUTE in uS conversion
@ -193,12 +195,12 @@ int HIP9011::cylinderToChannelIdx(int cylinder) {
return getCylinderKnockBank(cylinder);
}
void HIP9011::handleChannel(DEFINE_HIP_PARAMS) {
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;
return -1;
/* find next firing cylinder */
/* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */
@ -206,9 +208,53 @@ void HIP9011::handleChannel(DEFINE_HIP_PARAMS) {
int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber);
if (nextChannelIdx == channelIdx)
return;
return 0;
ret = sendCommand(SET_CHANNEL_CMD(nextChannelIdx));
if (ret == 0)
channelIdx = 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) PASS_ENGINE_PARAMETER_SUFFIX) - 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));
}

View File

@ -11,7 +11,10 @@
#include "rusefi_enums.h"
#define PIF 3.14159f
#define HIP9011_BAND(bore) (900 / (PIF * (bore) / 2))
#define HIP9011_BAND(bore) (900 / (PIF * (bore) / 2))
#define HIP9011_DESIRED_OUTPUT_VALUE 5.0f
#define HIP9011_DIGITAL_OUTPUT_MAX 0x03ff /* 10 bit max value */
#define HIP_INPUT_CHANNELS 2
#define INT_LOOKUP_SIZE 32
#define GAIN_LOOKUP_SIZE 64
@ -65,13 +68,15 @@ public:
explicit HIP9011(Hip9011HardwareInterface *hardware);
int sendCommand(uint8_t cmd);
int sendCommandGetReply(uint8_t cmd, uint8_t *reply);
float getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth);
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);
int handleChannel(DEFINE_HIP_PARAMS);
int readValueAndHandleChannel(DEFINE_HIP_PARAMS);
float getBand(DEFINE_HIP_PARAMS);
int getIntegrationIndexByRpm(float rpm);
int getBandIndex(DEFINE_HIP_PARAMS);
@ -104,7 +109,7 @@ public:
hip_state_e state;
int8_t cylinderNumber = -1;
int8_t expectedCylinderNumber = -1;
int raw_value;
int rawValue[HIP_INPUT_CHANNELS];
/* counters */
int samples = 0;