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 { class Hip9011Hardware : public Hip9011HardwareInterface {
int sendSyncCommand(uint8_t command, uint8_t *rx_ptr) override; 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 */ /* TODO: include following stuff in object */
@ -77,7 +84,8 @@ static SPIDriver *spi;
static Hip9011Hardware hardware; static Hip9011Hardware hardware;
static float hipValueMax = 0; static float normalizedValue[HIP_INPUT_CHANNELS];
static float normalizedValueMax[HIP_INPUT_CHANNELS];
HIP9011 instance(&hardware); HIP9011 instance(&hardware);
@ -114,7 +122,7 @@ static void hip_addconsoleActions(void);
/* Local functions. */ /* 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) */ /* in default SPI mode SDO is directly equals the SDI (echo function) */
if (tx == rx) { if (tx == rx) {
return 0; return 0;
@ -123,10 +131,41 @@ static int checkResponseDefMode(uint8_t tx, uint8_t rx) {
} }
} }
static int checkResponseAdvMode(uint8_t tx, uint8_t rx) { int Hip9011Hardware::checkResponseAdvMode(uint8_t tx, uint8_t rx) {
UNUSED(tx); UNUSED(rx); int ret = 0;
/* TODO: no check for advanced mode yet */
return 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) { 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) if (rx_ptr)
*rx_ptr = rx; *rx_ptr = rx;
/* check response */ /* check response */
if (instance.adv_mode == false) if (instance.adv_mode)
ret = checkResponseDefMode(tx, rx);
else
ret = checkResponseAdvMode(tx, rx); ret = checkResponseAdvMode(tx, rx);
else
ret = checkResponseDefMode(tx, rx);
/* statistic counters */ /* statistic counters */
if (ret) if (ret)
@ -201,9 +240,16 @@ static void endIntegration(void *) {
*/ */
if (instance.state == IS_INTEGRATING) { if (instance.state == IS_INTEGRATING) {
intHold.setLow(); intHold.setLow();
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; instance.state = WAITING_FOR_ADC_TO_SKIP;
} }
} }
}
/** /**
* Ignition callback used to start HIP integration and schedule finish * Ignition callback used to start HIP integration and schedule finish
@ -240,11 +286,16 @@ void hip9011_startKnockSampling(uint8_t cylinderNumber, efitick_t nowNt) {
} }
void hipAdcCallback(adcsample_t adcValue) { void hipAdcCallback(adcsample_t adcValue) {
/* we read in digital mode */
if (instance.adv_mode)
return;
if (instance.state == WAITING_FOR_ADC_TO_SKIP) { if (instance.state == WAITING_FOR_ADC_TO_SKIP) {
instance.state = WAITING_FOR_RESULT_ADC; instance.state = WAITING_FOR_RESULT_ADC;
} else if (instance.state == WAITING_FOR_RESULT_ADC) { } else if (instance.state == WAITING_FOR_RESULT_ADC) {
/* offload calculations to driver thread */ /* offload calculations to driver thread */
instance.raw_value = adcValue; if (instance.channelIdx < HIP_INPUT_CHANNELS) {
instance.rawValue[instance.channelIdx] = adcValue;
}
instance.state = NOT_READY; instance.state = NOT_READY;
hip_wake_driver(); hip_wake_driver();
} }
@ -368,8 +419,11 @@ static msg_t hipThread(void *arg) {
/* load new/updated settings */ /* load new/updated settings */
instance.handleSettings(GET_RPM() DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS)); instance.handleSettings(GET_RPM() DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
/* in advanced more driver will set channel while reading integrator value */
if (!instance.adv_mode) {
/* switch input channel */ /* switch input channel */
instance.handleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS)); instance.handleChannel(DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS));
}
/* State */ /* State */
instance.state = READY_TO_INTEGRATE; instance.state = READY_TO_INTEGRATE;
@ -377,11 +431,50 @@ static msg_t hipThread(void *arg) {
if (msg == MSG_TIMEOUT) { if (msg == MSG_TIMEOUT) {
/* ??? */ /* ??? */
} else { } else {
/* Check for correct cylinder/input */ int rawValue;
if (instance.cylinderNumber == instance.expectedCylinderNumber) { /* 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 */ /* calculations */
float knockVolts = instance.raw_value * adcToVolts(1) * CONFIG(analogInputDividerCoefficient); if (instance.adv_mode) {
hipValueMax = maxF(knockVolts, hipValueMax); /* 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 (correctCylinder) {
/* debug */
normalizedValue[idx] = knockNormalized;
normalizedValueMax[idx] = maxF(knockNormalized, normalizedValueMax[idx]);
/* report */
engine->knockLogic(knockVolts); engine->knockLogic(knockVolts);
/* TunerStudio */ /* TunerStudio */
@ -486,10 +579,6 @@ static void showHipInfo(void) {
engine->knockCount, engine->knockCount,
engineConfiguration->maxKnockSubDeg); engineConfiguration->maxKnockSubDeg);
efiPrintf(" Adc input %s (%.2f V)",
getAdc_channel_e(engineConfiguration->hipOutputChannel),
getVoltage("hipinfo", engineConfiguration->hipOutputChannel));
efiPrintf(" IntHold %s (mode 0x%x)", efiPrintf(" IntHold %s (mode 0x%x)",
hwPortname(CONFIG(hip9011IntHoldPin)), hwPortname(CONFIG(hip9011IntHoldPin)),
CONFIG(hip9011IntHoldPinMode)); CONFIG(hip9011IntHoldPinMode));
@ -503,22 +592,32 @@ static void showHipInfo(void) {
printSpiConfig("hip9011", CONFIG(hip9011SpiDevice)); printSpiConfig("hip9011", CONFIG(hip9011SpiDevice));
#endif /* EFI_PROD_CODE */ #endif /* EFI_PROD_CODE */
efiPrintf(" SPI good response %d incorrect response %d", efiPrintf(" SPI: good response %d incorrect response %d",
instance.correctResponsesCount, instance.correctResponsesCount,
instance.invalidResponsesCount); instance.invalidResponsesCount);
efiPrintf(" hip %.2f vmax=%.2f", efiPrintf(" Counters: samples %d overruns %d sync miss %d",
engine->knockVolts, instance.samples, instance.overrun, instance.unsync);
hipValueMax);
efiPrintf(" Window start %.2f end %.2f", efiPrintf(" Window start %.2f end %.2f",
engineConfiguration->knockDetectionWindowStart, engineConfiguration->knockDetectionWindowStart,
engineConfiguration->knockDetectionWindowEnd); engineConfiguration->knockDetectionWindowEnd);
efiPrintf(" Counters: samples %d overruns %d sync miss %d", if (!instance.adv_mode) {
instance.samples, instance.overrun, instance.unsync); 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(); engine->printKnockState();
} }

View File

@ -17,8 +17,6 @@
/* Local definitions. */ /* Local definitions. */
/*==========================================================================*/ /*==========================================================================*/
#define DESIRED_OUTPUT_VALUE 5.0f
/*==========================================================================*/ /*==========================================================================*/
/* Local variables and types. */ /* Local variables and types. */
/*==========================================================================*/ /*==========================================================================*/
@ -73,6 +71,10 @@ int HIP9011::sendCommand(uint8_t cmd) {
return hw->sendSyncCommand(cmd, NULL); 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 * @return frequency band we are interested in
*/ */
@ -112,7 +114,7 @@ float HIP9011::getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth)
/** /**
* TINT = TC * 2 * PI * VOUT * 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 * rpm = 60 seconds / time
* '60000000' because revolutions per MINUTE in uS conversion * '60000000' because revolutions per MINUTE in uS conversion
@ -193,12 +195,12 @@ int HIP9011::cylinderToChannelIdx(int cylinder) {
return getCylinderKnockBank(cylinder); return getCylinderKnockBank(cylinder);
} }
void HIP9011::handleChannel(DEFINE_HIP_PARAMS) { int HIP9011::handleChannel(DEFINE_HIP_PARAMS) {
int ret; int ret;
/* we did not receive any callback from spark logic with valid cylinder yet */ /* we did not receive any callback from spark logic with valid cylinder yet */
if (cylinderNumber < 0) if (cylinderNumber < 0)
return; return -1;
/* find next firing cylinder */ /* find next firing cylinder */
/* MAGIC +1 -1, couse getNextFiringCylinderId expect cylinders to start from 1 */ /* 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); int nextChannelIdx = cylinderToChannelIdx(expectedCylinderNumber);
if (nextChannelIdx == channelIdx) if (nextChannelIdx == channelIdx)
return; return 0;
ret = sendCommand(SET_CHANNEL_CMD(nextChannelIdx)); ret = sendCommand(SET_CHANNEL_CMD(nextChannelIdx));
if (ret == 0) if (ret)
return ret;
channelIdx = nextChannelIdx; 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

@ -12,6 +12,9 @@
#define PIF 3.14159f #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 INT_LOOKUP_SIZE 32
#define GAIN_LOOKUP_SIZE 64 #define GAIN_LOOKUP_SIZE 64
@ -65,13 +68,15 @@ public:
explicit HIP9011(Hip9011HardwareInterface *hardware); explicit HIP9011(Hip9011HardwareInterface *hardware);
int sendCommand(uint8_t cmd); int sendCommand(uint8_t cmd);
int sendCommandGetReply(uint8_t cmd, uint8_t *reply);
float getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth); float getRpmByAngleWindowAndTimeUs(int timeUs, float angleWindowWidth);
void prepareRpmLookup(void); void prepareRpmLookup(void);
void setAngleWindowWidth(DEFINE_HIP_PARAMS); void setAngleWindowWidth(DEFINE_HIP_PARAMS);
void handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS)); void handleSettings(int rpm DEFINE_PARAM_SUFFIX(DEFINE_HIP_PARAMS));
int cylinderToChannelIdx(int cylinder); int cylinderToChannelIdx(int cylinder);
void handleChannel(DEFINE_HIP_PARAMS); int handleChannel(DEFINE_HIP_PARAMS);
int readValueAndHandleChannel(DEFINE_HIP_PARAMS);
float getBand(DEFINE_HIP_PARAMS); float getBand(DEFINE_HIP_PARAMS);
int getIntegrationIndexByRpm(float rpm); int getIntegrationIndexByRpm(float rpm);
int getBandIndex(DEFINE_HIP_PARAMS); int getBandIndex(DEFINE_HIP_PARAMS);
@ -104,7 +109,7 @@ public:
hip_state_e state; hip_state_e state;
int8_t cylinderNumber = -1; int8_t cylinderNumber = -1;
int8_t expectedCylinderNumber = -1; int8_t expectedCylinderNumber = -1;
int raw_value; int rawValue[HIP_INPUT_CHANNELS];
/* counters */ /* counters */
int samples = 0; int samples = 0;