fome-fw/firmware/console/binary/trigger_scope.cpp

121 lines
3.4 KiB
C++

#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 = BIG_BUFFER_SIZE / (2 * sizeof(uint8_t));
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<adcsample_t>(), sampleCount);
}
}
// Enable one buffer's worth of perf tracing, and retrieve the buffer size in bytes
void triggerScopeEnable() {
buffer = getBigBuffer(BigBufferUser::TriggerScope);
isRunning = true;
startSampling();
}
void triggerScopeDisable() {
// we're done with the buffer - let somebody else have it
buffer = {};
isRunning = false;
engine->outputChannels.triggerScopeReady = false;
}
static scheduling_s restartTimer;
// Retrieve the trace buffer
const BigBufferHandle& triggerScopeGetBuffer() {
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