9#include "knock_config.h"
12#ifdef KNOCK_SPECTROGRAM
15#define COMPRESSED_SPECTRUM_PROTOCOL_SIZE 16
16#define START_SPECTRORGAM_FREQUENCY 4000
56 if (!((KNOCK_ADC.state == ADC_READY) ||
57 (KNOCK_ADC.state == ADC_ERROR))) {
67 constexpr int sampleRate = KNOCK_SAMPLE_RATE;
68 sampleCount = 0xFFFFFFFE &
static_cast<size_t>(clampF(100, samplingSeconds * sampleRate, efi::size(
sampleBuffer)));
103 #ifdef KNOCK_SPECTROGRAM
116 int freqStartConst = START_SPECTRORGAM_FREQUENCY;
117 int minFreqDiff = freqStartConst;
121 for (
size_t i = 0; i < FFT_SIZE/2; i++)
123 float freq =
float(i * KNOCK_SAMPLE_RATE) / FFT_SIZE;
124 int min = abs(freq - freqStartConst);
128 freqStep = abs(freq - freqStart);
131 if(min < minFreqDiff) {
144 efiSetPadMode(
"knock ch1", KNOCK_PIN_CH1, PAL_MODE_INPUT_ANALOG);
146 efiSetPadMode(
"knock ch2", KNOCK_PIN_CH2, PAL_MODE_INPUT_ANALOG);
152#ifdef KNOCK_SPECTROGRAM
153static uint8_t
toDb(
const float& voltage) {
154 float db = 200 * log10(voltage*voltage) + 40;
155 db = clampF(0, db, 255);
168 constexpr float ratio = 3.3f / 4095.0f;
178 for (
size_t i = 0; i < localCount; i++) {
187 sumSq += filtered * filtered;
196#ifdef KNOCK_SPECTROGRAM
207 for(uint8_t i = 0; i < COMPRESSED_SPECTRUM_PROTOCOL_SIZE; ++i) {
216 uint32_t compressed = uint32_t(a << 24 | b << 16 | c << 8 | d);
219 chibios_rt::CriticalSectionLocker csl;
220 spectrum[i] = compressed;
227 chibios_rt::CriticalSectionLocker csl;
235 float meanSquares = sumSq / localCount;
238 float db = 10 * log10(meanSquares);
241 db = clampF(-100, db, 100);
246void KnockThread::ThreadTask() {
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
float filter(float input)
void configureBandpass(float samplingFrequency, float centerFrequency, float Q)
void cookSteadyState(float steadyStateInput)
TunerStudioOutputChannels outputChannels
constexpr auto & module()
A base class for a controller that requires its own thread.
virtual void ThreadTask()=0
static EngineAccessor engine
static constexpr engine_configuration_s * engineConfiguration
uint16_t adcsample_t
ADC sample data type.
static union @47 NO_CACHE
void blackmanharris(float *w, unsigned n, bool sflag)
float amplitude(const complex_type &fft)
bool fft_adc_sample_filtered(Biquad &knockFilter, float *w, float ratio, float sensitivity, const adcsample_t *data_in, complex_type *data_out, const size_t size)
bool fft_adc_sample(float *w, float ratio, float sensitivity, const adcsample_t *data_in, complex_type *data_out, const size_t size)
m_knockFrequencyStep("Knock: Step Freq", SensorCategory.SENSOR_INPUTS, FieldType.INT, 1096, 1.0, 0.0, 0.0, "Hz")
m_knockFrequencyStart("Knock: Start Freq", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 1094, 1.0, 0.0, 0.0, "Hz")
m_knockSpectrumChannelCyl("Knock: ChannelAndCylNumber", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 1092, 1.0, 0.0, 0.0, "compressed N + N")
static SpectrogramData * spectrogramData
static volatile bool knockIsSampling
static int8_t channelNumber
static void processLastKnockEvent()
static size_t spectrogramStartIndex
static Biquad knockFilter
void onStartKnockSampling(uint8_t cylinderNumber, float samplingSeconds, uint8_t channelIdx)
void onKnockSamplingComplete()
static volatile size_t sampleCount
static uint8_t toDb(const float &voltage)
chibios_rt::BinarySemaphore knockSem(true)
static NO_CACHE adcsample_t sampleBuffer[1800]
static volatile bool knockNeedsProcess
static SpectrogramData spectrogramData0
static efitick_t lastKnockSampleTime
static int8_t currentCylinderNumber
fft::complex_type fftBuffer[FFT_SIZE]
bool enableKnockSpectrogramFilter
float knockSpectrumSensitivity
bool enableKnockSpectrogram
bool knockDetectionUseDoubleFrequency