diff --git a/firmware/config/boards/proteus/knock_config.h b/firmware/config/boards/proteus/knock_config.h index ac65da1777..e73f38078e 100644 --- a/firmware/config/boards/proteus/knock_config.h +++ b/firmware/config/boards/proteus/knock_config.h @@ -8,6 +8,7 @@ #define KNOCK_PIN_CH1 GPIOF_4 // knock 2 - pin PF5 +#define KNOCK_HAS_CH2 true #define KNOCK_ADC_CH2 ADC_CHANNEL_IN15 #define KNOCK_PIN_CH2 GPIOF_5 diff --git a/firmware/controllers/sensors/software_knock.cpp b/firmware/controllers/sensors/software_knock.cpp index 7cd07d3d81..2ebfbbda89 100644 --- a/firmware/controllers/sensors/software_knock.cpp +++ b/firmware/controllers/sensors/software_knock.cpp @@ -38,7 +38,7 @@ static void completionCallback(ADCDriver* adcp, adcsample_t*, size_t) { static void errorCallback(ADCDriver*, adcerror_t err) { } -static const ADCConversionGroup adcConvGroup = { FALSE, 1, &completionCallback, &errorCallback, +static const ADCConversionGroup adcConvGroupCh1 = { FALSE, 1, &completionCallback, &errorCallback, 0, ADC_CR2_SWSTART, ADC_SMPR1_SMP_AN14(KNOCK_SAMPLE_TIME), // sample times for channels 10...18 @@ -52,6 +52,52 @@ static const ADCConversionGroup adcConvGroup = { FALSE, 1, &completionCallback, ADC_SQR3_SQ1_N(KNOCK_ADC_CH1) }; +// Not all boards have a second channel - configure it if it exists +#if KNOCK_HAS_CH2 +static const ADCConversionGroup adcConvGroupCh2 = { FALSE, 1, &completionCallback, &errorCallback, + 0, + ADC_CR2_SWSTART, + ADC_SMPR1_SMP_AN14(KNOCK_SAMPLE_TIME), // sample times for channels 10...18 + 0, + + 0, // htr + 0, // ltr + + 0, // sqr1 + 0, // sqr2 + ADC_SQR3_SQ1_N(KNOCK_ADC_CH2) +}; +#endif // KNOCK_HAS_CH2 + +static bool cylinderUsesChannel2(uint8_t cylinderIndex) { + // C/C++ can't index in to bit fields, we have to provide lookup ourselves + switch (cylinderIndex) { + case 0: return CONFIG(knockBankCyl1); + case 1: return CONFIG(knockBankCyl2); + case 2: return CONFIG(knockBankCyl3); + case 3: return CONFIG(knockBankCyl4); + case 4: return CONFIG(knockBankCyl5); + case 5: return CONFIG(knockBankCyl6); + case 6: return CONFIG(knockBankCyl7); + case 7: return CONFIG(knockBankCyl8); + case 8: return CONFIG(knockBankCyl9); + case 9: return CONFIG(knockBankCyl10); + case 10: return CONFIG(knockBankCyl11); + case 11: return CONFIG(knockBankCyl12); + default: return false; + } +} + +const ADCConversionGroup* getConversionGroup(uint8_t cylinderIndex) { +#if KNOCK_HAS_CH2 + if (cylinderUsesChannel2(cylinderIndex)) { + return &adcConvGroupCh2; + } +#endif // KNOCK_HAS_CH2 + + return &adcConvGroupCh1; +} + void startKnockSampling(uint8_t cylinderIndex) { if (!CONFIG(enableSoftwareKnock)) { return; @@ -78,8 +124,13 @@ void startKnockSampling(uint8_t cylinderIndex) { constexpr int sampleRate = KNOCK_SAMPLE_RATE; sampleCount = 0xFFFFFFFE & static_cast(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); + + // Stash the current cylinder's index so we can store the result appropriately currentCylinderIndex = cylinderIndex; - adcStartConversionI(&KNOCK_ADC, &adcConvGroup, sampleBuffer, sampleCount); + + adcStartConversionI(&KNOCK_ADC, conversionGroup, sampleBuffer, sampleCount); } class KnockThread : public ThreadController<256> { @@ -88,7 +139,7 @@ public: void ThreadTask() override; }; -KnockThread kt; +static KnockThread kt; void initSoftwareKnock() { chBSemObjectInit(&knockSem, TRUE); diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 72e50a7d84..75a0b237c4 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -890,18 +890,18 @@ custom maf_sensor_type_e 4 bits, S32, @OFFSET@, [0:1], @@maf_sensor_type_e_enum@ bit verboseVVTDecoding;enable vvt_details bit invertCamVVTSignal;get invertCamVVTSignal bit consumeObdSensors;enable consumeObdSensors - bit unusedBit_251_16 - bit unusedBit_251_17 - bit unusedBit_251_18 - bit unusedBit_251_19 - bit unusedBit_251_20 - bit unusedBit_251_21 - bit unusedBit_251_22 - bit unusedBit_251_23 - bit unusedBit_251_24 - bit unusedBit_251_25 - bit unusedBit_251_26 - bit unusedBit_251_27 + bit knockBankCyl1,Channel 2,Channel 1; + bit knockBankCyl2,Channel 2,Channel 1; + bit knockBankCyl3,Channel 2,Channel 1; + bit knockBankCyl4,Channel 2,Channel 1; + bit knockBankCyl5,Channel 2,Channel 1; + bit knockBankCyl6,Channel 2,Channel 1; + bit knockBankCyl7,Channel 2,Channel 1; + bit knockBankCyl8,Channel 2,Channel 1; + bit knockBankCyl9,Channel 2,Channel 1; + bit knockBankCyl10,Channel 2,Channel 1; + bit knockBankCyl11,Channel 2,Channel 1; + bit knockBankCyl12,Channel 2,Channel 1; bit unusedBit_251_28 bit unusedBit_251_29 diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index e9182fb9ec..6d71028e79 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -2357,7 +2357,22 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00" dialog = softwareKnock, "Software Knock" field = "Enable", enableSoftwareKnock - field = "Band Freq override", knockBandCustom, {enableSoftwareKnock} + field = "Knock filter frequency", knockBandCustom, {enableSoftwareKnock} + field = "" + field = "Select the nearest sensor for each cylinder" + field = "Cylinder 1", knockBankCyl1, {enableSoftwareKnock} + field = "Cylinder 2", knockBankCyl2, {enableSoftwareKnock && cylindersCount >= 2} + field = "Cylinder 3", knockBankCyl3, {enableSoftwareKnock && cylindersCount >= 3} + field = "Cylinder 4", knockBankCyl4, {enableSoftwareKnock && cylindersCount >= 4} + field = "Cylinder 5", knockBankCyl5, {enableSoftwareKnock && cylindersCount >= 5} + field = "Cylinder 6", knockBankCyl6, {enableSoftwareKnock && cylindersCount >= 6} + field = "Cylinder 7", knockBankCyl7, {enableSoftwareKnock && cylindersCount >= 7} + field = "Cylinder 8", knockBankCyl8, {enableSoftwareKnock && cylindersCount >= 8} + field = "Cylinder 9", knockBankCyl9, {enableSoftwareKnock && cylindersCount >= 9} + field = "Cylinder 10", knockBankCyl10, {enableSoftwareKnock && cylindersCount >= 10} + field = "Cylinder 11", knockBankCyl11, {enableSoftwareKnock && cylindersCount >= 11} + field = "Cylinder 12", knockBankCyl12, {enableSoftwareKnock && cylindersCount >= 12} + ; Engine->hip9011 Settings dialog = hipFunction, "HIP9011 Settings (knock decoder)"