faster uniform adc cleanup (#3334)

* dead fast tps

* oooooh map avg on hh7

* adc v4 fast support

* new fast API

* hardware.cpp

* adc v2

* warning

* guard

* no check required

* stub cypress/kinetis

* kinetis and cypress stubs

* cleanup

* h7 adc speed

* adc skip

* configurable oversample
This commit is contained in:
Matthew Kennedy 2021-10-10 19:59:25 -07:00 committed by GitHub
parent 3d7aa1eeb7
commit abb6513744
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 55 deletions

View File

@ -37,12 +37,7 @@ DDEFS += -DEFI_LOGIC_ANALYZER=FALSE
TRIGGER_USE_ADC = yes
# we need fast ADC for software trigger detector
#DDEFS += -DEFI_OVERRIDE_FAST_ADC_FOR_STM32H7=TRUE -DADC_FAST_DEVICE=ADCD1 -DADC_SLOW_DEVICE=ADCD3 -DSTM32_ADC_USE_ADC3=TRUE
#DDEFS += -DADC_SLOW_DEVICE=ADCD3 -DSTM32_ADC_USE_ADC3=TRUE
DDEFS += -DEFI_OVERRIDE_FAST_ADC_FOR_STM32H7=TRUE -DADC_FAST_DEVICE=ADCD1 -DEFI_USE_ONLY_FAST_ADC=TRUE -DEFI_FASTER_UNIFORM_ADC=TRUE -DADC_MAX_CHANNELS_COUNT=16 -DADC_BUF_DEPTH_FAST=1 -DADC_BUF_NUM_AVG=1
#DDEFS += -DADC_SLOW_DEVICE=ADCD1
DDEFS += -DFAST_ADC_SKIP=3 -DH7_ADC_SPEED=20000 -DH7_ADC_OVERSAMPLE=2
# We are running on Hellen-One hardware!
DDEFS += -DHW_HELLEN=1

View File

@ -148,53 +148,32 @@ static FastAdcToken triggerSampleIndex;
extern AdcDevice fastAdc;
#if EFI_FASTER_UNIFORM_ADC
static int adcCallbackCounter = 0;
static volatile int averagedSamples[ADC_MAX_CHANNELS_COUNT];
static adcsample_t avgBuf[ADC_MAX_CHANNELS_COUNT];
#ifdef FAST_ADC_SKIP
// No reason to enable if N = 1
static_assert(FAST_ADC_SKIP > 1);
static size_t fastAdcSkipCount = 0;
#endif // FAST_ADC_SKIP
void onFastAdcCompleteInternal(adcsample_t* samples);
/**
* This method is not in the adc* lower-level file because it is more business logic then hardware.
*/
void onFastAdcComplete(adcsample_t*) {
ScopePerf perf(PE::AdcCallbackFast);
void onFastAdcComplete(adcsample_t* samples) {
#if HAL_TRIGGER_USE_ADC
// we need to call this ASAP, because trigger processing is time-critical
triggerAdcCallback(getFastAdc(triggerSampleIndex));
#endif /* HAL_TRIGGER_USE_ADC */
// store the values for averaging
for (int i = fastAdc.size() - 1; i >= 0; i--) {
averagedSamples[i] += samples[i];
#ifdef FAST_ADC_SKIP
// If we run the fast ADC _very_ fast for triggerAdcCallback's benefit, we may want to
// skip most of the samples for the rest of the callback.
if (fastAdcSkipCount++ == FAST_ADC_SKIP) {
fastAdcSkipCount = 0;
} else {
return;
}
// if it's time to process the data
if (++adcCallbackCounter >= ADC_BUF_NUM_AVG) {
// get an average
for (int i = fastAdc.size() - 1; i >= 0; i--) {
avgBuf[i] = (adcsample_t)(averagedSamples[i] / ADC_BUF_NUM_AVG); // todo: rounding?
}
// call the real callback (see below)
onFastAdcCompleteInternal(samples);
// reset the avg buffer & counter
for (int i = fastAdc.size() - 1; i >= 0; i--) {
averagedSamples[i] = 0;
}
adcCallbackCounter = 0;
}
}
#endif /* EFI_FASTER_UNIFORM_ADC */
/**
* This method is not in the adc* lower-level file because it is more business logic then hardware.
*/
#if EFI_FASTER_UNIFORM_ADC
void onFastAdcCompleteInternal(adcsample_t*) {
#else
void onFastAdcComplete(adcsample_t*) {
#endif
ScopePerf perf(PE::AdcCallbackFast);
/**
* this callback is executed 10 000 times a second, it needs to be as fast as possible
@ -237,13 +216,6 @@ static void adcConfigListener(Engine *engine) {
}
static void turnOnHardware(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
#if EFI_FASTER_UNIFORM_ADC
for (int i = 0; i < ADC_MAX_CHANNELS_COUNT; i++) {
averagedSamples[i] = 0;
}
adcCallbackCounter = 0;
#endif /* EFI_FASTER_UNIFORM_ADC */
#if EFI_PROD_CODE && EFI_SHAFT_POSITION_INPUT
turnOnTriggerInputPins(PASS_ENGINE_PARAMETER_SIGNATURE);
#endif /* EFI_SHAFT_POSITION_INPUT */

View File

@ -10,6 +10,29 @@
#include "mpu_util.h"
#include "map_averaging.h"
#ifndef H7_ADC_SPEED
#define H7_ADC_SPEED (10000)
#endif
#ifndef H7_ADC_OVERSAMPLE
#define H7_ADC_OVERSAMPLE (4)
#endif
static_assert((H7_ADC_OVERSAMPLE & (H7_ADC_OVERSAMPLE - 1)) == 0, "H7_ADC_OVERSAMPLE must be a power of 2");
constexpr size_t log2_int(size_t x) {
size_t result = 0;
while (x >>= 1) result++;
return result;
}
// poor man's unit test
static_assert(log2_int(4) == 2);
static_assert(log2_int(16) == 4);
// Shift the result by log2(N) bits to divide by N
static constexpr int H7_ADC_SHIFT_BITS = log2_int(H7_ADC_OVERSAMPLE);
void portInitAdc() {
// Init slow ADC
adcStart(&ADCD1, NULL);
@ -50,8 +73,8 @@ static constexpr ADCConversionGroup convGroupSlow = {
.end_cb = adc_callback,
.error_cb = nullptr,
.cfgr = ADC_CFGR_EXTEN_0 | (4 << ADC_CFGR_EXTSEL_Pos), // External trigger ch4, rising edge: TIM3 TRGO
.cfgr2 = 3 << ADC_CFGR2_OVSR_Pos | // Oversample by 4x (register contains N-1)
2 << ADC_CFGR2_OVSS_Pos | // shift the result right 2 bits to make a 16 bit result out of the 18 bit internal sum (4x oversampled)
.cfgr2 = (H7_ADC_OVERSAMPLE - 1) << ADC_CFGR2_OVSR_Pos | // Oversample by Nx (register contains N-1)
H7_ADC_SHIFT_BITS << ADC_CFGR2_OVSS_Pos | // shift the result right log2(N) bits to make a 16 bit result out of the internal oversample sum
ADC_CFGR2_ROVSE, // Enable oversampling
.ccr = 0,
.pcsel = 0xFFFFFFFF, // enable analog switches on all channels
@ -119,8 +142,8 @@ bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
adcStartConversionI(&ADCD1, &convGroupSlow, convertedSamples, 1);
}
constexpr uint32_t samplingRate = 10000;
constexpr uint32_t timerCountFrequency = samplingRate * 100;
constexpr uint32_t samplingRate = H7_ADC_SPEED;
constexpr uint32_t timerCountFrequency = samplingRate * 10;
constexpr uint32_t timerPeriod = timerCountFrequency / samplingRate;
static constexpr GPTConfig gptCfg = {