mirror of https://github.com/FOME-Tech/fome-fw.git
more knock sense unification (#3250)
* more unification * hip stub * comment * guard * channel idx * include * hip * move in to engine * hip9011
This commit is contained in:
parent
085709b6ba
commit
6ac12f2984
|
@ -386,6 +386,11 @@ public:
|
|||
*/
|
||||
float getTimeIgnitionSeconds(void) const;
|
||||
|
||||
void onSparkFireKnockSense(uint8_t cylinderIndex, efitick_t nowNt);
|
||||
|
||||
// onKnockSenseCompleted is the callback from the knock sense driver to report a sensed knock level
|
||||
bool onKnockSenseCompleted(uint8_t cylinderIndex, float levelDbv, efitick_t lastKnockTime);
|
||||
|
||||
void knockLogic(float knockVolts DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||
void printKnockState(void);
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "os_access.h"
|
||||
#include "peak_detect.h"
|
||||
|
||||
#include "hip9011.h"
|
||||
|
||||
int getCylinderKnockBank(uint8_t cylinderIndex) {
|
||||
// C/C++ can't index in to bit fields, we have to provide lookup ourselves
|
||||
switch (cylinderIndex) {
|
||||
|
@ -48,7 +50,9 @@ using PD = PeakDetect<float, MS2NT(100)>;
|
|||
static PD peakDetectors[12];
|
||||
static PD allCylinderPeakDetector;
|
||||
|
||||
void onKnockSenseCompleted(uint8_t cylinderIndex, float dbv, efitick_t lastKnockTime) {
|
||||
bool Engine::onKnockSenseCompleted(uint8_t cylinderIndex, float dbv, efitick_t lastKnockTime) {
|
||||
bool isKnock = dbv > ENGINE(engineState).knockThreshold;
|
||||
|
||||
#if EFI_TUNER_STUDIO
|
||||
// Pass through per-cylinder peak detector
|
||||
float cylPeak = peakDetectors[cylinderIndex].detect(dbv, lastKnockTime);
|
||||
|
@ -58,11 +62,51 @@ void onKnockSenseCompleted(uint8_t cylinderIndex, float dbv, efitick_t lastKnock
|
|||
tsOutputChannels.knockLevel = allCylinderPeakDetector.detect(dbv, lastKnockTime);
|
||||
|
||||
// If this was a knock, count it!
|
||||
bool isKnock = dbv > ENGINE(engineState).knockThreshold;
|
||||
if (isKnock) {
|
||||
tsOutputChannels.knockCount++;
|
||||
}
|
||||
#endif // EFI_TUNER_STUDIO
|
||||
|
||||
// TODO: retard timing, then put it back!
|
||||
|
||||
return isKnock;
|
||||
}
|
||||
|
||||
// This callback is to be implemented by the knock sense driver
|
||||
void onStartKnockSampling(uint8_t cylinderIndex, float samplingTimeSeconds, uint8_t channelIdx);
|
||||
|
||||
static uint8_t cylinderIndexCopy;
|
||||
|
||||
// Called when its time to start listening for knock
|
||||
// Does some math, then hands off to the driver to start any sampling hardware
|
||||
static void startKnockSampling(Engine* engine) {
|
||||
EXPAND_Engine;
|
||||
|
||||
if (!engine->rpmCalculator.isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert sampling angle to time
|
||||
float samplingSeconds = ENGINE(rpmCalculator).oneDegreeUs * CONFIG(knockSamplingDuration) / US_PER_SECOND_F;
|
||||
|
||||
// Look up which channel this cylinder uses
|
||||
auto channel = getCylinderKnockBank(cylinderIndexCopy);
|
||||
|
||||
// Call the driver to begin sampling
|
||||
onStartKnockSampling(cylinderIndexCopy, samplingSeconds, channel);
|
||||
}
|
||||
|
||||
static scheduling_s startSampling;
|
||||
|
||||
void Engine::onSparkFireKnockSense(uint8_t cylinderIndex, efitick_t nowNt) {
|
||||
cylinderIndexCopy = cylinderIndex;
|
||||
|
||||
#if EFI_HIP_9011 || EFI_SOFTWARE_KNOCK
|
||||
scheduleByAngle(&startSampling, nowNt,
|
||||
/*angle*/CONFIG(knockDetectionWindowStart), { startKnockSampling, engine } PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
#endif
|
||||
|
||||
#if EFI_HIP_9011
|
||||
hip9011_onFireEvent(cylinderIndex, nowNt);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -8,5 +8,3 @@
|
|||
#pragma once
|
||||
|
||||
int getCylinderKnockBank(uint8_t cylinderIndex);
|
||||
|
||||
void onKnockSenseCompleted(uint8_t cylinderIndex, float levelDbv, efitick_t lastKnockTime);
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include "pch.h"
|
||||
|
||||
#include "software_knock.h"
|
||||
#include "spark_logic.h"
|
||||
#include "os_access.h"
|
||||
|
||||
|
@ -15,7 +14,7 @@
|
|||
#include "event_queue.h"
|
||||
#include "tooth_logger.h"
|
||||
|
||||
#include "hip9011.h"
|
||||
#include "knock_logic.h"
|
||||
|
||||
#if EFI_ENGINE_CONTROL
|
||||
|
||||
|
@ -215,12 +214,7 @@ if (engineConfiguration->debugMode == DBG_DWELL_METRIC) {
|
|||
prepareCylinderIgnitionSchedule(dwellAngleDuration, sparkDwell, event PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
}
|
||||
|
||||
#if EFI_SOFTWARE_KNOCK
|
||||
knockSamplingCallback(event->cylinderNumber, nowNt);
|
||||
#endif
|
||||
#if EFI_HIP_9011
|
||||
hip9011_onFireEvent(event->cylinderNumber, nowNt);
|
||||
#endif
|
||||
engine->onSparkFireKnockSense(event->cylinderNumber, nowNt);
|
||||
}
|
||||
|
||||
static void startDwellByTurningSparkPinHigh(IgnitionEvent *event, IgnitionOutputPin *output) {
|
||||
|
|
|
@ -18,7 +18,6 @@ static Biquad knockFilter;
|
|||
static volatile bool knockIsSampling = false;
|
||||
static volatile bool knockNeedsProcess = false;
|
||||
static volatile size_t sampleCount = 0;
|
||||
static int cylinderIndexCopy;
|
||||
|
||||
chibios_rt::BinarySemaphore knockSem(/* taken =*/ true);
|
||||
|
||||
|
@ -93,27 +92,23 @@ static const ADCConversionGroup adcConvGroupCh2 = { FALSE, 1, &completionCallbac
|
|||
};
|
||||
#endif // KNOCK_HAS_CH2
|
||||
|
||||
const ADCConversionGroup* getConversionGroup(uint8_t cylinderIndex) {
|
||||
const ADCConversionGroup* getConversionGroup(uint8_t channelIdx) {
|
||||
#if KNOCK_HAS_CH2
|
||||
if (getCylinderKnockBank(cylinderIndex)) {
|
||||
if (channelIdx == 1) {
|
||||
return &adcConvGroupCh2;
|
||||
}
|
||||
#else
|
||||
(void)cylinderIndex;
|
||||
(void)channelIdx;
|
||||
#endif // KNOCK_HAS_CH2
|
||||
|
||||
return &adcConvGroupCh1;
|
||||
}
|
||||
|
||||
static void startKnockSampling(uint8_t cylinderIndex) {
|
||||
void onStartKnockSampling(uint8_t cylinderIndex, float samplingSeconds, uint8_t channelIdx) {
|
||||
if (!CONFIG(enableSoftwareKnock)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!engine->rpmCalculator.isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel if ADC isn't ready
|
||||
if (!((KNOCK_ADC.state == ADC_READY) ||
|
||||
(KNOCK_ADC.state == ADC_COMPLETE) ||
|
||||
|
@ -126,13 +121,12 @@ static void startKnockSampling(uint8_t cylinderIndex) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Sample for XX degrees
|
||||
float samplingSeconds = ENGINE(rpmCalculator).oneDegreeUs * CONFIG(knockSamplingDuration) / US_PER_SECOND_F;
|
||||
// Convert sampling time to number of samples
|
||||
constexpr int sampleRate = KNOCK_SAMPLE_RATE;
|
||||
sampleCount = 0xFFFFFFFE & static_cast<size_t>(clampF(100, samplingSeconds * sampleRate, efi::size(sampleBuffer)));
|
||||
|
||||
// Select the appropriate conversion group - it will differ depending on which sensor this cylinder should listen on
|
||||
auto conversionGroup = getConversionGroup(cylinderIndex);
|
||||
auto conversionGroup = getConversionGroup(channelIdx);
|
||||
|
||||
// Stash the current cylinder's index so we can store the result appropriately
|
||||
currentCylinderIndex = cylinderIndex;
|
||||
|
@ -141,20 +135,6 @@ static void startKnockSampling(uint8_t cylinderIndex) {
|
|||
lastKnockSampleTime = getTimeNowNt();
|
||||
}
|
||||
|
||||
static void startKnockSamplingNoParam(void*) {
|
||||
// ugly as hell but that's error: cast between incompatible function types from 'void (*)(uint8_t)' {aka 'void (*)(unsigned char)'} to 'schfunc_t' {aka 'void (*)(void*)'} [-Werror=cast-function-type]
|
||||
startKnockSampling(cylinderIndexCopy);
|
||||
}
|
||||
|
||||
static scheduling_s startSampling;
|
||||
|
||||
void knockSamplingCallback(uint8_t cylinderIndex, efitick_t nowNt) {
|
||||
cylinderIndexCopy = cylinderIndex;
|
||||
|
||||
scheduleByAngle(&startSampling, nowNt,
|
||||
/*angle*/CONFIG(knockDetectionWindowStart), startKnockSamplingNoParam PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
}
|
||||
|
||||
class KnockThread : public ThreadController<256> {
|
||||
public:
|
||||
KnockThread() : ThreadController("knock", PRIO_KNOCK_PROCESS) {}
|
||||
|
@ -221,7 +201,7 @@ void processLastKnockEvent() {
|
|||
// clamp to reasonable range
|
||||
db = clampF(-100, db, 100);
|
||||
|
||||
onKnockSenseCompleted(currentCylinderIndex, db, lastKnockTime);
|
||||
engine->onKnockSenseCompleted(currentCylinderIndex, db, lastKnockTime);
|
||||
}
|
||||
|
||||
void KnockThread::ThreadTask() {
|
||||
|
|
|
@ -257,6 +257,19 @@ static void endIntegration(HIP9011 *hip) {
|
|||
}
|
||||
}
|
||||
|
||||
void onStartKnockSampling(uint8_t cylinderIndex, float samplingTimeSeconds, uint8_t channelIdx) {
|
||||
/* TODO: @dron0gus: not sure if we need the expectedCylinderNumber logic at all
|
||||
|
||||
Something like this might be right:
|
||||
|
||||
startIntegration(&instance);
|
||||
|
||||
efitick_t windowLength = USF2NT(1e6 * samplingTimeSeconds);
|
||||
|
||||
engine->executor.scheduleByTimestampNt("knock", &hardware.endTimer, getTimeNowNt() + windowLength, { endIntegration, &instance });
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignition callback used to start HIP integration and schedule finish
|
||||
*/
|
||||
|
@ -491,7 +504,7 @@ static msg_t hipThread(void *arg) {
|
|||
engine->knockLogic(knockVolts);
|
||||
|
||||
// TODO: convert knock level to dBv
|
||||
onKnockSenseCompleted(instance.cylinderNumber, knockVolts, instance.knockSampleTimestamp);
|
||||
engine->onKnockSenseCompleted(instance.cylinderNumber, knockVolts, instance.knockSampleTimestamp);
|
||||
|
||||
#if EFI_HIP_9011_DEBUG
|
||||
/* debug */
|
||||
|
|
Loading…
Reference in New Issue