diff --git a/firmware/config/boards/hellen/cypress/efifeatures.h b/firmware/config/boards/hellen/cypress/efifeatures.h index 7fec6455eb..5a3df321e2 100644 --- a/firmware/config/boards/hellen/cypress/efifeatures.h +++ b/firmware/config/boards/hellen/cypress/efifeatures.h @@ -231,6 +231,7 @@ #define EFI_INTERNAL_FAST_ADC_GPT &GPTD2 #define ADC_MAX_CHANNELS_COUNT 32 +#define SLOW_ADC_CHANNEL_COUNT 32 #define EFI_FASTER_UNIFORM_ADC TRUE #define ADC_BUF_NUM_AVG 4 diff --git a/firmware/hw_layer/adc/AdcConfiguration.h b/firmware/hw_layer/adc/AdcConfiguration.h index 07fc48cf27..cae15a55cd 100644 --- a/firmware/hw_layer/adc/AdcConfiguration.h +++ b/firmware/hw_layer/adc/AdcConfiguration.h @@ -13,6 +13,14 @@ #define ADC_MAX_CHANNELS_COUNT 16 #endif /* ADC_MAX_CHANNELS_COUNT */ +#ifndef SLOW_ADC_CHANNEL_COUNT +#ifdef ADC_MUX_PIN +#define SLOW_ADC_CHANNEL_COUNT 32 +#else // not ADC_MUX_PIN +#define SLOW_ADC_CHANNEL_COUNT 16 +#endif // def ADC_MUX_PIN +#endif // SLOW_ADC_CHANNEL_COUNT + // this structure contains one multi-channel ADC state snapshot typedef struct { volatile adcsample_t adc_data[ADC_MAX_CHANNELS_COUNT]; diff --git a/firmware/hw_layer/adc/adc_inputs.cpp b/firmware/hw_layer/adc/adc_inputs.cpp index 27b045c734..5f9ed872f5 100644 --- a/firmware/hw_layer/adc/adc_inputs.cpp +++ b/firmware/hw_layer/adc/adc_inputs.cpp @@ -35,7 +35,7 @@ #define ADC_BUF_DEPTH_FAST 4 #endif -static NO_CACHE adcsample_t slowAdcSamples[ADC_MAX_CHANNELS_COUNT]; +static NO_CACHE adcsample_t slowAdcSamples[SLOW_ADC_CHANNEL_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]; diff --git a/firmware/hw_layer/ports/stm32/stm32_adc_v2.cpp b/firmware/hw_layer/ports/stm32/stm32_adc_v2.cpp index 38315ffeba..51286630e0 100644 --- a/firmware/hw_layer/ports/stm32/stm32_adc_v2.cpp +++ b/firmware/hw_layer/ports/stm32/stm32_adc_v2.cpp @@ -13,10 +13,18 @@ /* Depth of the conversion buffer, channels are sampled X times each.*/ #define SLOW_ADC_OVERSAMPLE 8 +#ifdef ADC_MUX_PIN +static OutputPin muxControl; +#endif // ADC_MUX_PIN + void portInitAdc() { // Init slow ADC adcStart(&ADCD1, NULL); +#ifdef ADC_MUX_PIN + muxControl.initPin("ADC Mux", ADC_MUX_PIN); +#endif //ADC_MUX_PIN + #if EFI_USE_FAST_ADC // Init fast ADC (MAP sensor) adcStart(&ADCD2, NULL); @@ -108,14 +116,14 @@ float getMcuTemperature() { #define ADC_SAMPLING_SLOW ADC_SAMPLE_56 #define ADC_SAMPLING_FAST ADC_SAMPLE_28 -// Slow ADC has 16 channels we can sample -constexpr size_t slowChannelCount = 16; +// Slow ADC has 16 channels we can sample, or 32 if ADC mux mode is enabled. +constexpr size_t adcChannelCount = 16; // Conversion group for slow channels // This simply samples every channel in sequence static constexpr ADCConversionGroup convGroupSlow = { .circular = FALSE, - .num_channels = slowChannelCount, + .num_channels = adcChannelCount, .end_cb = nullptr, .error_cb = nullptr, /* HW dependent part.*/ @@ -148,9 +156,9 @@ 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[SLOW_ADC_OVERSAMPLE * slowChannelCount]; +static NO_CACHE adcsample_t slowSampleBuffer[SLOW_ADC_OVERSAMPLE * adcChannelCount]; -bool readSlowAnalogInputs(adcsample_t* convertedSamples) { +bool readBatch(adcsample_t* convertedSamples, size_t start) { msg_t result = adcConvert(&ADCD1, &convGroupSlow, slowSampleBuffer, SLOW_ADC_OVERSAMPLE); // If something went wrong - try again later @@ -159,21 +167,36 @@ bool readSlowAnalogInputs(adcsample_t* convertedSamples) { } // Average samples to get some noise filtering and oversampling - for (size_t i = 0; i < slowChannelCount; i++) { + for (size_t i = 0; i < adcChannelCount; i++) { uint32_t sum = 0; size_t index = i; for (size_t j = 0; j < SLOW_ADC_OVERSAMPLE; j++) { sum += slowSampleBuffer[index]; - index += slowChannelCount; + index += adcChannelCount; } adcsample_t value = static_cast(sum / SLOW_ADC_OVERSAMPLE); - convertedSamples[i] = value; + convertedSamples[start + i] = value; } return true; } +bool readSlowAnalogInputs(adcsample_t* convertedSamples) { + bool result = true; + + result &= readBatch(convertedSamples, 0); + +#ifdef ADC_MUX_PIN + muxControl.setValue(1); + // read the second batch, starting where we left off + result &= readBatch(convertedSamples, adcChannelCount); + muxControl.setValue(0); +#endif + + return result; +} + #if EFI_USE_FAST_ADC #include "AdcConfiguration.h" diff --git a/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp b/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp index b9f2195570..980920f972 100644 --- a/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp +++ b/firmware/hw_layer/ports/stm32/stm32_adc_v4.cpp @@ -10,6 +10,10 @@ #include "mpu_util.h" #include "map_averaging.h" +#ifdef ADC_MUX_PIN +#error "ADC mux not yet supported on STM32H7" +#endif + #ifndef H7_ADC_SPEED #define H7_ADC_SPEED (10000) #endif