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:
parent
0d63fd04c5
commit
afcc8848c5
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue