From 9d8bfb834e708dae03b135d3cf6dd6a28c00d22d Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 10 Dec 2022 20:00:12 -0800 Subject: [PATCH] Basic trigger scope implementation (#4885) * big buffer * mostly hooked up big buffer * bad merge * s * sneak preview of trigger scope * s * constness * channel limits * s * unnecessary * efilib * TcpServerSandbox * includes fix * binary format * tooth logger uses big buffer * dead config * config * implement basic trigger scope * good behavior * enable on other alphax * flag to enable second channel * use 8 bit mode on the ADC for less memory use * changelog --- firmware/CHANGELOG.md | 1 + .../boards/hellen/alphax-2chan/board.mk | 3 +- .../alphax-2chan/trigger_scope_config.h | 11 ++ .../boards/hellen/alphax-4chan/board.mk | 3 +- .../alphax-4chan/trigger_scope_config.h | 12 ++ .../boards/hellen/alphax-8chan/board.mk | 3 +- .../alphax-8chan/trigger_scope_config.h | 12 ++ firmware/console/binary/trigger_scope.cpp | 103 ++++++++++++++++-- firmware/console/binary/trigger_scope.h | 2 + firmware/console/binary/tunerstudio.cpp | 2 + firmware/hw_layer/hardware.cpp | 5 + firmware/tunerstudio/rusefi.input | 10 +- 12 files changed, 145 insertions(+), 22 deletions(-) create mode 100644 firmware/config/boards/hellen/alphax-2chan/trigger_scope_config.h create mode 100644 firmware/config/boards/hellen/alphax-4chan/trigger_scope_config.h create mode 100644 firmware/config/boards/hellen/alphax-8chan/trigger_scope_config.h diff --git a/firmware/CHANGELOG.md b/firmware/CHANGELOG.md index cc7f3b644a..81998733bf 100644 --- a/firmware/CHANGELOG.md +++ b/firmware/CHANGELOG.md @@ -30,6 +30,7 @@ Release template (copy/paste this for new release): ### Added - Electronic throttle supply voltage compensation, giving more consistent behavior as battery voltage changes #4838 + - VR trigger input oscilloscope for boards with "discrete VR" hardware (AlphaX ECUs, some Hellen) #4885 ## December 2022 Release - "Day 289" diff --git a/firmware/config/boards/hellen/alphax-2chan/board.mk b/firmware/config/boards/hellen/alphax-2chan/board.mk index cf8444cd32..0a0df6dfdf 100644 --- a/firmware/config/boards/hellen/alphax-2chan/board.mk +++ b/firmware/config/boards/hellen/alphax-2chan/board.mk @@ -6,7 +6,8 @@ BOARDINC = $(BOARDS_DIR)/hellen/alphax-2chan DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE - +# This board has trigger scope hardware! +DDEFS += -DTRIGGER_SCOPE # Add them all together DDEFS += -DFIRMWARE_ID=\"AlphaX-2chan\" diff --git a/firmware/config/boards/hellen/alphax-2chan/trigger_scope_config.h b/firmware/config/boards/hellen/alphax-2chan/trigger_scope_config.h new file mode 100644 index 0000000000..49ca4aa584 --- /dev/null +++ b/firmware/config/boards/hellen/alphax-2chan/trigger_scope_config.h @@ -0,0 +1,11 @@ +#define TRIGGER_SCOPE_ADC ADCD3 + +#define TRIGGER_SCOPE_SAMPLE_TIME ADC_SAMPLE_144 + +// RES3 +#define TRIGGER_SCOPE_PIN_CH1 Gpio::F8 +#define TRIGGER_SCOPE_ADC_CH1 ADC_CHANNEL_IN6 + +#define TRIGGER_SCOPE_HAS_CH2 true +#define TRIGGER_SCOPE_PIN_CH2 Gpio::F8 +#define TRIGGER_SCOPE_ADC_CH2 ADC_CHANNEL_IN6 diff --git a/firmware/config/boards/hellen/alphax-4chan/board.mk b/firmware/config/boards/hellen/alphax-4chan/board.mk index c8d42178f0..387daaf4a7 100644 --- a/firmware/config/boards/hellen/alphax-4chan/board.mk +++ b/firmware/config/boards/hellen/alphax-4chan/board.mk @@ -6,7 +6,8 @@ BOARDINC = $(BOARDS_DIR)/hellen/alphax-4chan DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE - +# This board has trigger scope hardware! +DDEFS += -DTRIGGER_SCOPE # Add them all together DDEFS += -DFIRMWARE_ID=\"AlphaX-4chan\" diff --git a/firmware/config/boards/hellen/alphax-4chan/trigger_scope_config.h b/firmware/config/boards/hellen/alphax-4chan/trigger_scope_config.h new file mode 100644 index 0000000000..db0891c79e --- /dev/null +++ b/firmware/config/boards/hellen/alphax-4chan/trigger_scope_config.h @@ -0,0 +1,12 @@ +#define TRIGGER_SCOPE_ADC ADCD3 + +#define TRIGGER_SCOPE_SAMPLE_TIME ADC_SAMPLE_144 + +// RES3 +#define TRIGGER_SCOPE_PIN_CH1 Gpio::F8 +#define TRIGGER_SCOPE_ADC_CH1 ADC_CHANNEL_IN6 + +// RES2 +#define TRIGGER_SCOPE_HAS_CH2 true +#define TRIGGER_SCOPE_PIN_CH2 Gpio::F10 +#define TRIGGER_SCOPE_ADC_CH2 ADC_CHANNEL_IN8 diff --git a/firmware/config/boards/hellen/alphax-8chan/board.mk b/firmware/config/boards/hellen/alphax-8chan/board.mk index 2b91a45763..b6be07d165 100644 --- a/firmware/config/boards/hellen/alphax-8chan/board.mk +++ b/firmware/config/boards/hellen/alphax-8chan/board.mk @@ -6,7 +6,8 @@ BOARDINC = $(BOARDS_DIR)/hellen/alphax-8chan DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE - +# This board has trigger scope hardware! +DDEFS += -DTRIGGER_SCOPE # Add them all together DDEFS += -DFIRMWARE_ID=\"AlphaX-8chan\" diff --git a/firmware/config/boards/hellen/alphax-8chan/trigger_scope_config.h b/firmware/config/boards/hellen/alphax-8chan/trigger_scope_config.h new file mode 100644 index 0000000000..db0891c79e --- /dev/null +++ b/firmware/config/boards/hellen/alphax-8chan/trigger_scope_config.h @@ -0,0 +1,12 @@ +#define TRIGGER_SCOPE_ADC ADCD3 + +#define TRIGGER_SCOPE_SAMPLE_TIME ADC_SAMPLE_144 + +// RES3 +#define TRIGGER_SCOPE_PIN_CH1 Gpio::F8 +#define TRIGGER_SCOPE_ADC_CH1 ADC_CHANNEL_IN6 + +// RES2 +#define TRIGGER_SCOPE_HAS_CH2 true +#define TRIGGER_SCOPE_PIN_CH2 Gpio::F10 +#define TRIGGER_SCOPE_ADC_CH2 ADC_CHANNEL_IN8 diff --git a/firmware/console/binary/trigger_scope.cpp b/firmware/console/binary/trigger_scope.cpp index a5e7d4273e..636c5bc77f 100644 --- a/firmware/console/binary/trigger_scope.cpp +++ b/firmware/console/binary/trigger_scope.cpp @@ -1,19 +1,82 @@ #include "pch.h" +#ifdef TRIGGER_SCOPE + #include "trigger_scope.h" +#include "trigger_scope_config.h" static BigBufferHandle buffer; static bool isRunning = false; +static void completionCallback(ADCDriver* adcp) { + if (isRunning && adcp->state == ADC_COMPLETE) { + engine->outputChannels.triggerScopeReady = true; + } +} + +static const uint32_t smpr1 = + ADC_SMPR1_SMP_AN10(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR1_SMP_AN11(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR1_SMP_AN12(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR1_SMP_AN13(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR1_SMP_AN14(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR1_SMP_AN15(TRIGGER_SCOPE_SAMPLE_TIME); + +static const uint32_t smpr2 = + ADC_SMPR2_SMP_AN0(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN1(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN2(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN3(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN4(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN5(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN6(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN7(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN8(TRIGGER_SCOPE_SAMPLE_TIME) | + ADC_SMPR2_SMP_AN9(TRIGGER_SCOPE_SAMPLE_TIME); + +static const ADCConversionGroup adcConvGroupCh1 = { FALSE, 2, &completionCallback, nullptr, + ADC_CR1_RES_1, // Sample in 8-bit mode + ADC_CR2_SWSTART, + // sample times for channels 10...18 + smpr1, + // sample times for channels 0...9 + smpr2, + + 0, // htr + 0, // ltr + + 0, // sqr1 + 0, // sqr2 + ADC_SQR3_SQ1_N(TRIGGER_SCOPE_ADC_CH1) | ADC_SQR3_SQ2_N(TRIGGER_SCOPE_ADC_CH2) +}; + +static constexpr size_t sampleCount = 1000; +static_assert(2 * sizeof(uint8_t) * sampleCount < BIG_BUFFER_SIZE); + +static void startSampling(void* = nullptr) { + chibios_rt::CriticalSectionLocker csl; + + if (buffer && !engineConfiguration->enableSoftwareKnock) { + // Cancel if ADC isn't ready + if (!((TRIGGER_SCOPE_ADC.state == ADC_READY) || + (TRIGGER_SCOPE_ADC.state == ADC_COMPLETE) || + (TRIGGER_SCOPE_ADC.state == ADC_ERROR))) { + triggerScopeDisable(); + return; + } + + adcStartConversionI(&TRIGGER_SCOPE_ADC, &adcConvGroupCh1, buffer.get(), sampleCount); + } +} + // Enable one buffer's worth of perf tracing, and retrieve the buffer size in bytes void triggerScopeEnable() { buffer = getBigBuffer(BigBufferUser::TriggerScope); - // TODO: trigger ADC - isRunning = true; - engine->outputChannels.triggerScopeReady = true; + + startSampling(); } void triggerScopeDisable() { @@ -24,19 +87,35 @@ void triggerScopeDisable() { engine->outputChannels.triggerScopeReady = false; } -static int theta = 0; +static scheduling_s restartTimer; // Retrieve the trace buffer const BigBufferHandle& triggerScopeGetBuffer() { - if (buffer) { - for (size_t i = 0; i < buffer.size(); i++) - { - buffer.get()[i] = 128 + 100 * sin((float)theta / 50); - theta++; - } - } + engine->outputChannels.triggerScopeReady = false; - // engine->outputChannels.triggerScopeReady = false; + // Start the next sample once we've read out this one + if (isRunning) { + engine->executor.scheduleByTimestampNt("trigger scope", &restartTimer, getTimeNowNt() + MS2NT(10), startSampling); + } return buffer; } + +void initTriggerScope() { + // Trigger scope and knock currently mutually exclusive + if (!engineConfiguration->enableSoftwareKnock) { + adcStart(&TRIGGER_SCOPE_ADC, nullptr); + + // Manually set ADC DMA to byte mode, as we'll be taking 8 bit samples + // Defaults are to sample at 12 bits, and DMA 16-bit words + ADCD3.dmamode &= ~(STM32_DMA_CR_PSIZE_MASK | STM32_DMA_CR_MSIZE_MASK); + ADCD3.dmamode |= STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE; + + efiSetPadMode("knock ch1", TRIGGER_SCOPE_PIN_CH1, PAL_MODE_INPUT_ANALOG); +#if TRIGGER_SCOPE_HAS_CH2 + efiSetPadMode("knock ch2", TRIGGER_SCOPE_PIN_CH2, PAL_MODE_INPUT_ANALOG); +#endif + } +} + +#endif // TRIGGER_SCOPE diff --git a/firmware/console/binary/trigger_scope.h b/firmware/console/binary/trigger_scope.h index ec5cd34bac..7d5d2bf61f 100644 --- a/firmware/console/binary/trigger_scope.h +++ b/firmware/console/binary/trigger_scope.h @@ -3,3 +3,5 @@ void triggerScopeEnable(); void triggerScopeDisable(); const BigBufferHandle& triggerScopeGetBuffer(); + +void initTriggerScope(); diff --git a/firmware/console/binary/tunerstudio.cpp b/firmware/console/binary/tunerstudio.cpp index 97c0f73b04..231adc785d 100644 --- a/firmware/console/binary/tunerstudio.cpp +++ b/firmware/console/binary/tunerstudio.cpp @@ -759,6 +759,7 @@ int TunerStudio::handleCrcCommand(TsChannelBase* tsChannel, char *data, int inco } } break; +#ifdef TRIGGER_SCOPE case TS_TRIGGER_SCOPE_ENABLE: triggerScopeEnable(); break; @@ -777,6 +778,7 @@ int TunerStudio::handleCrcCommand(TsChannelBase* tsChannel, char *data, int inco } } break; +#endif // TRIGGER_SCOPE default: // dunno what that was, send NAK return false; diff --git a/firmware/hw_layer/hardware.cpp b/firmware/hw_layer/hardware.cpp index cb313aa395..17bccd821e 100644 --- a/firmware/hw_layer/hardware.cpp +++ b/firmware/hw_layer/hardware.cpp @@ -49,6 +49,7 @@ #include "trigger_emulator_algo.h" #include "boost_control.h" #include "software_knock.h" +#include "trigger_scope.h" #include "init.h" #if EFI_MC33816 #include "mc33816.h" @@ -525,6 +526,10 @@ void initHardware() { initSoftwareKnock(); #endif /* EFI_SOFTWARE_KNOCK */ +#ifdef TRIGGER_SCOPE + initTriggerScope(); +#endif // TRIGGER_SCOPE + #if HAL_USE_SPI initSpiModules(engineConfiguration); #endif /* HAL_USE_SPI */ diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index ce731324e7..23a8875e8d 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -141,13 +141,9 @@ enable2ndByteCanID = false dataReadyCondition = { triggerScopeReady } continuousRead = true - recordDef = 0, 0, 4 - recordField = lowBits1, "low", 0, 8, 1, "" , hidden - recordField = highBits1, "high", 8, 8, 1, "" , hidden - calcField = channel1, "Channel 1", "v", { 6.6 / 4096 * ( lowBits1 * 256 + highBits1 ) } - recordField = lowBits2, "low2", 16, 8, 1, "" , hidden - recordField = highBits2, "high2", 24, 8, 1, "" , hidden - calcField = channel2, "Channel 2", "v", { 6.6 / 4096 * ( lowBits2 * 256 + highBits2 ) } + recordDef = 0, 0, 2 + recordField = channel1, "Channel 1", 0, 8, {6.6 / 255}, "v" + recordField = channel2, "Channel 2", 8, 8, {6.6 / 255}, "v" [VeAnalyze]