ADC cleanup, enable oversampling on H7 (#2437)

* cleanup v2 adc

* simplify

* oversample on h7

* output 16b result

* port-ify ADC_MAX_VALUE

* simplify include

* guard for cypress

* make sim/tests happy

* 16x oversample + comment

* this check is uesless

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2021-03-08 11:50:50 -08:00 committed by GitHub
parent b4f1fedc9e
commit 96a14fd649
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 38 additions and 50 deletions

View File

@ -38,7 +38,12 @@
#include "perf_trace.h"
#include "thread_priority.h"
static adcsample_t slowAdcSamples[ADC_MAX_CHANNELS_COUNT];
/* Depth of the conversion buffer, channels are sampled X times each.*/
#ifndef ADC_BUF_DEPTH_FAST
#define ADC_BUF_DEPTH_FAST 4
#endif
static NO_CACHE adcsample_t slowAdcSamples[ADC_MAX_CHANNELS_COUNT];
static NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST * ADC_MAX_CHANNELS_COUNT];
static adc_channel_mode_e adcHwChannelEnabled[HW_MAX_ADC_INDEX];
@ -217,11 +222,6 @@ int getInternalAdcValue(const char *msg, adc_channel_e hwChannel) {
}
#endif // EFI_USE_FAST_ADC
if (adcHwChannelEnabled[hwChannel] != ADC_SLOW) {
// todo: make this not happen during hardware continuous integration
warning(CUSTOM_OBD_WRONG_ADC_MODE, "ADC is off [%s] index=%d", msg, hwChannel);
}
return slowAdcSamples[hwChannel - 1];
}
@ -517,10 +517,6 @@ static SlowAdcController slowAdcController;
void initAdcInputs() {
scheduleMsg(&logger, "initAdcInputs()");
if (ADC_BUF_DEPTH_FAST > MAX_ADC_GRP_BUF_DEPTH)
firmwareError(CUSTOM_ERR_ADC_DEPTH_FAST, "ADC_BUF_DEPTH_FAST too high");
if (ADC_BUF_DEPTH_SLOW > MAX_ADC_GRP_BUF_DEPTH)
firmwareError(CUSTOM_ERR_ADC_DEPTH_SLOW, "ADC_BUF_DEPTH_SLOW too high");
configureInputs();

View File

@ -56,19 +56,6 @@ float getMCUInternalTemperature(void);
void addChannel(const char *name, adc_channel_e setting, adc_channel_mode_e mode);
void removeChannel(const char *name, adc_channel_e setting);
/* Depth of the conversion buffer, channels are sampled X times each.*/
#ifndef ADC_BUF_DEPTH_SLOW
#define ADC_BUF_DEPTH_SLOW 8
#endif /* ADC_BUF_DEPTH_SLOW */
#ifndef ADC_BUF_DEPTH_FAST
#define ADC_BUF_DEPTH_FAST 4
#endif /* ADC_BUF_DEPTH_FAST */
// todo: preprocessor way of doing 'max'?
// max(ADC_BUF_DEPTH_SLOW, ADC_BUF_DEPTH_FAST)
#define MAX_ADC_GRP_BUF_DEPTH 8
#define getAdcValue(msg, hwChannel) getInternalAdcValue(msg, hwChannel)
#define adcToVoltsDivided(adc) (adcToVolts(adc) * engineConfiguration->analogInputDividerCoefficient)

View File

@ -10,8 +10,12 @@
#pragma once
#include "engine_configuration.h"
#if EFI_PROD_CODE
#include "port_mpu_util.h"
#include "rusefi_hw_enums.h"
#else // not EFI_PROD_CODE
#define ADC_MAX_VALUE 4095
#endif
#define adcToVolts(adc) ((engineConfiguration->adcVcc) / ADC_MAX_VALUE * (adc))

View File

@ -46,3 +46,5 @@ typedef enum {
// TODO
#define SPI_CR1_24BIT_MODE 0
#define SPI_CR2_24BIT_MODE 0
#define ADC_MAX_VALUE 4095

View File

@ -34,3 +34,5 @@ typedef enum {
// TODO
#define SPI_CR1_24BIT_MODE 0
#define SPI_CR2_24BIT_MODE 0
#define ADC_MAX_VALUE 4095

View File

@ -14,9 +14,7 @@
EXTERN_CONFIG;
/* Depth of the conversion buffer, channels are sampled X times each.*/
#ifndef ADC_BUF_DEPTH_SLOW
#define ADC_BUF_DEPTH_SLOW 8
#endif /* ADC_BUF_DEPTH_SLOW */
#define SLOW_ADC_OVERSAMPLE 8
void portInitAdc() {
// Init slow ADC
@ -150,13 +148,13 @@ static constexpr ADCConversionGroup convGroupSlow = {
.sqr3 = ADC_SQR3_SQ1_N(0) | ADC_SQR3_SQ2_N(1) | ADC_SQR3_SQ3_N(2) | ADC_SQR3_SQ4_N(3) | ADC_SQR3_SQ5_N(4) | ADC_SQR3_SQ6_N(5), // Conversion group sequence 1...6
};
static NO_CACHE adcsample_t slowSampleBuffer[ADC_BUF_DEPTH_SLOW * slowChannelCount];
static NO_CACHE adcsample_t slowSampleBuffer[SLOW_ADC_OVERSAMPLE * slowChannelCount];
bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
msg_t result = adcConvert(&ADCD1, &convGroupSlow, slowSampleBuffer, ADC_BUF_DEPTH_SLOW);
msg_t result = adcConvert(&ADCD1, &convGroupSlow, slowSampleBuffer, SLOW_ADC_OVERSAMPLE);
// If something went wrong - try again later
if (result == MSG_RESET || result == MSG_TIMEOUT) {
if (result != MSG_OK) {
return false;
}
@ -164,12 +162,12 @@ bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
for (int i = 0; i < slowChannelCount; i++) {
uint32_t sum = 0;
size_t index = i;
for (size_t j = 0; j < ADC_BUF_DEPTH_SLOW; j++) {
for (size_t j = 0; j < SLOW_ADC_OVERSAMPLE; j++) {
sum += slowSampleBuffer[index];
index += slowChannelCount;
}
adcsample_t value = static_cast<adcsample_t>(sum / ADC_BUF_DEPTH_SLOW);
adcsample_t value = static_cast<adcsample_t>(sum / SLOW_ADC_OVERSAMPLE);
convertedSamples[i] = value;
}

View File

@ -24,8 +24,11 @@ float getMcuTemperature() {
return 0;
}
// TODO: use a define instead of magic number
#define ADC_SAMPLING_SLOW (7)
// ADC Clock is 25MHz
// 32.5 sampling + 8.5 conversion = 41 cycles per sample total
// 16 channels * 16x oversample = 256 samples per batch
// (41 * 256) / 25MHz -> 419 microseconds to sample all channels
#define ADC_SAMPLING_SLOW ADC_SMPR_SMP_32P5
// Sample the 16 channels that line up with the STM32F4/F7
constexpr size_t slowChannelCount = 16;
@ -38,7 +41,9 @@ static constexpr ADCConversionGroup convGroupSlow = {
.end_cb = nullptr,
.error_cb = nullptr,
.cfgr = 0,
.cfgr2 = 0, // no oversampling (yet)
.cfgr2 = 16 << ADC_CFGR2_OVSR_Pos | // Oversample by 16x
4 << ADC_CFGR2_OVSS_Pos | // shift the result right 4 bits to make a 16 bit result
ADC_CFGR2_ROVSE, // Enable oversampling
.ccr = 0,
.pcsel = 0xFFFFFFFF, // enable analog switches on all channels
// Thresholds aren't used
@ -88,21 +93,10 @@ static constexpr ADCConversionGroup convGroupSlow = {
},
};
static NO_CACHE adcsample_t slowSampleBuffer[slowChannelCount];
bool readSlowAnalogInputs(adcsample_t* convertedSamples) {
msg_t result = adcConvert(&ADCD1, &convGroupSlow, slowSampleBuffer, 1);
// Oversampling and right-shift happen in hardware, so we can sample directly to the output buffer
msg_t result = adcConvert(&ADCD1, &convGroupSlow, convertedSamples, 1);
// If something went wrong - try again later
if (result != MSG_OK) {
return false;
}
// V4 ADC can oversample in hardware, so no need to oversample in software
for (int i = 0; i < slowChannelCount; i++) {
// Convert from 16b result to 12b result
convertedSamples[i] = slowSampleBuffer[i] >> 4;
}
return true;
// Return true if OK
return result == MSG_OK;
}

View File

@ -21,3 +21,4 @@
#define SPI_CR1_24BIT_MODE 0
#define SPI_CR2_24BIT_MODE 0
#define ADC_MAX_VALUE 4095

View File

@ -20,3 +20,5 @@
/* 3 x 8-bit transfer */
#define SPI_CR1_24BIT_MODE 0
#define SPI_CR2_24BIT_MODE SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0
#define ADC_MAX_VALUE 4095

View File

@ -12,3 +12,5 @@
#define MCU_SERIAL_NUMBER_LOCATION (uint8_t*)(0x1FF1E800)
// todo SPI! #2284
#define ADC_MAX_VALUE 65535