2017-03-24 10:41:36 -07:00
|
|
|
/**
|
|
|
|
* @file adc_inputs.cpp
|
|
|
|
* @brief Low level ADC code
|
|
|
|
*
|
2019-05-15 01:16:41 -07:00
|
|
|
* rusEfi uses two ADC devices on the same 16 pins at the moment. Two ADC devices are used in orde to distinguish between
|
|
|
|
* fast and slow devices. The idea is that but only having few channels in 'fast' mode we can sample those faster?
|
|
|
|
*
|
|
|
|
* At the moment rusEfi does not allow to have more than 16 ADC channels combined. At the moment there is no flexibility to use
|
2019-05-28 15:19:51 -07:00
|
|
|
* any ADC pins, only the hardcoded choice of 16 pins.
|
2019-05-15 01:16:41 -07:00
|
|
|
*
|
2020-09-18 00:04:07 -07:00
|
|
|
* Slow ADC group is used for IAT, CLT, AFR, VBATT etc - this one is currently sampled at 500Hz
|
2017-03-24 10:41:36 -07:00
|
|
|
*
|
2020-09-18 00:04:07 -07:00
|
|
|
* Fast ADC group is used for MAP, MAF HIP - this one is currently sampled at 10KHz
|
2018-04-08 08:38:14 -07:00
|
|
|
* We need frequent MAP for map_averaging.cpp
|
2017-03-24 10:41:36 -07:00
|
|
|
*
|
2018-12-23 20:29:19 -08:00
|
|
|
* 10KHz equals one measurement every 3.6 degrees at 6000 RPM
|
|
|
|
*
|
2017-03-24 10:41:36 -07:00
|
|
|
* @date Jan 14, 2013
|
2020-01-13 18:57:43 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2017-03-24 10:41:36 -07:00
|
|
|
*/
|
|
|
|
|
2021-08-03 19:05:01 -07:00
|
|
|
#include "pch.h"
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2023-01-08 14:29:29 -08:00
|
|
|
float __attribute__((weak)) getAnalogInputDividerCoefficient(adc_channel_e) {
|
|
|
|
return engineConfiguration->analogInputDividerCoefficient;
|
|
|
|
}
|
2022-09-07 12:56:45 -07:00
|
|
|
|
2023-01-08 14:29:29 -08:00
|
|
|
#if HAL_USE_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2019-09-21 11:33:38 -07:00
|
|
|
#include "adc_subscription.h"
|
2017-03-24 10:41:36 -07:00
|
|
|
#include "AdcConfiguration.h"
|
|
|
|
#include "mpu_util.h"
|
2019-12-11 06:28:11 -08:00
|
|
|
#include "periodic_thread_controller.h"
|
2022-05-17 20:49:18 -07:00
|
|
|
#include "protected_gpio.h"
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2021-03-08 11:50:50 -08:00
|
|
|
/* Depth of the conversion buffer, channels are sampled X times each.*/
|
|
|
|
#ifndef ADC_BUF_DEPTH_FAST
|
|
|
|
#define ADC_BUF_DEPTH_FAST 4
|
|
|
|
#endif
|
|
|
|
|
2022-07-26 04:12:00 -07:00
|
|
|
static NO_CACHE adcsample_t slowAdcSamples[SLOW_ADC_CHANNEL_COUNT];
|
2020-09-08 14:20:55 -07:00
|
|
|
|
2024-05-05 13:02:14 -07:00
|
|
|
static adc_channel_mode_e adcHwChannelMode[HW_MAX_ADC_INDEX];
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2019-09-22 06:56:06 -07:00
|
|
|
// Board voltage, with divider coefficient accounted for
|
2021-11-16 01:15:29 -08:00
|
|
|
float getVoltageDivided(const char *msg, adc_channel_e hwChannel) {
|
2023-01-08 14:29:29 -08:00
|
|
|
return getVoltage(msg, hwChannel) * getAnalogInputDividerCoefficient(hwChannel);
|
2019-09-22 06:56:06 -07:00
|
|
|
}
|
|
|
|
|
2019-09-22 13:41:10 -07:00
|
|
|
// voltage in MCU universe, from zero to VDD
|
2021-11-16 01:15:29 -08:00
|
|
|
float getVoltage(const char *msg, adc_channel_e hwChannel) {
|
2019-09-22 13:41:10 -07:00
|
|
|
return adcToVolts(getAdcValue(msg, hwChannel));
|
|
|
|
}
|
|
|
|
|
2021-03-04 16:55:09 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
2023-11-01 07:21:27 -07:00
|
|
|
AdcDevice::AdcDevice(ADCConversionGroup* p_hwConfig, adcsample_t *p_buf, size_t p_buf_len) {
|
|
|
|
this->hwConfig = p_hwConfig;
|
|
|
|
this->samples = p_buf;
|
|
|
|
this->buf_len = p_buf_len;
|
2017-03-24 10:41:36 -07:00
|
|
|
|
|
|
|
hwConfig->sqr1 = 0;
|
|
|
|
hwConfig->sqr2 = 0;
|
|
|
|
hwConfig->sqr3 = 0;
|
2020-09-12 06:04:26 -07:00
|
|
|
#if ADC_MAX_CHANNELS_COUNT > 16
|
|
|
|
hwConfig->sqr4 = 0;
|
|
|
|
hwConfig->sqr5 = 0;
|
|
|
|
#endif /* ADC_MAX_CHANNELS_COUNT */
|
2021-05-13 12:51:18 -07:00
|
|
|
memset(internalAdcIndexByHardwareIndex, 0xFF, sizeof(internalAdcIndexByHardwareIndex));
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2021-03-04 16:55:09 -08:00
|
|
|
#endif // EFI_USE_FAST_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2019-05-14 13:38:14 -07:00
|
|
|
// is there a reason to have this configurable at runtime?
|
2019-03-28 19:46:10 -07:00
|
|
|
#ifndef ADC_FAST_DEVICE
|
2017-03-24 10:41:36 -07:00
|
|
|
#define ADC_FAST_DEVICE ADCD2
|
2019-03-28 19:46:10 -07:00
|
|
|
#endif /* ADC_FAST_DEVICE */
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2021-03-04 16:55:09 -08:00
|
|
|
static uint32_t slowAdcCounter = 0;
|
2017-03-24 10:41:36 -07:00
|
|
|
|
|
|
|
// todo: move this flag to Engine god object
|
|
|
|
static int adcDebugReporting = false;
|
|
|
|
|
2023-11-04 06:45:22 -07:00
|
|
|
#if EFI_USE_FAST_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
static adcsample_t getAvgAdcValue(int index, adcsample_t *samples, int bufDepth, int numChannels) {
|
2019-12-11 06:28:11 -08:00
|
|
|
uint32_t result = 0;
|
2017-03-24 10:41:36 -07:00
|
|
|
for (int i = 0; i < bufDepth; i++) {
|
2024-04-22 07:57:14 -07:00
|
|
|
adcsample_t sample = samples[index];
|
2024-04-22 15:27:26 -07:00
|
|
|
// if (sample > 0x1FFF) {
|
|
|
|
// // 12bit ADC expected right now, make this configurable one day
|
|
|
|
// criticalError("fast ADC unexpected sample %d", sample);
|
|
|
|
// } else
|
|
|
|
if (sample > 0xFFF) {
|
2024-04-22 16:52:30 -07:00
|
|
|
if (!engineConfiguration->skipADC12bitAssert) {
|
|
|
|
criticalError("fast ADC unexpected sample %d. Please report and use skipADC12bitAssert to disable", sample);
|
|
|
|
}
|
|
|
|
engine->outputChannels.unexpectedAdcSample = sample;
|
2024-04-22 15:27:26 -07:00
|
|
|
sample = sample & 0xFFF; // sad hack which works around https://github.com/rusefi/rusefi/issues/6376 which we do not understand
|
2024-04-22 09:45:19 -07:00
|
|
|
engine->outputChannels.adc13bitCounter++;
|
2024-04-22 07:57:14 -07:00
|
|
|
}
|
|
|
|
result += sample;
|
2017-03-24 10:41:36 -07:00
|
|
|
index += numChannels;
|
|
|
|
}
|
2019-12-11 06:28:11 -08:00
|
|
|
|
|
|
|
// this truncation is guaranteed to not be lossy - the average can't be larger than adcsample_t
|
|
|
|
return static_cast<adcsample_t>(result / bufDepth);
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-13 12:51:18 -07:00
|
|
|
// See https://github.com/rusefi/rusefi/issues/976 for discussion on this value
|
2024-04-22 06:16:05 -07:00
|
|
|
#ifndef ADC_SAMPLING_FAST
|
2017-03-24 10:41:36 -07:00
|
|
|
#define ADC_SAMPLING_FAST ADC_SAMPLE_28
|
2024-04-22 06:16:05 -07:00
|
|
|
#endif
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2021-07-23 11:19:59 -07:00
|
|
|
static void adc_callback_fast(ADCDriver *adcp) {
|
|
|
|
// State may not be complete if we get a callback for "half done"
|
|
|
|
if (adcp->state == ADC_COMPLETE) {
|
|
|
|
onFastAdcComplete(adcp->samples);
|
|
|
|
}
|
|
|
|
}
|
2019-07-05 17:34:41 -07:00
|
|
|
|
2024-05-09 03:45:25 -07:00
|
|
|
static volatile adcerror_t fastAdcLastError;
|
|
|
|
|
|
|
|
static void fastAdcErrorCB(ADCDriver *, adcerror_t err)
|
|
|
|
{
|
|
|
|
fastAdcLastError = err;
|
|
|
|
}
|
|
|
|
|
2020-09-08 14:20:55 -07:00
|
|
|
static ADCConversionGroup adcgrpcfgFast = {
|
2020-09-01 04:38:35 -07:00
|
|
|
.circular = FALSE,
|
|
|
|
.num_channels = 0,
|
|
|
|
.end_cb = adc_callback_fast,
|
2024-05-09 03:45:25 -07:00
|
|
|
.error_cb = fastAdcErrorCB,
|
2020-09-01 04:38:35 -07:00
|
|
|
/* HW dependent part.*/
|
|
|
|
.cr1 = 0,
|
|
|
|
.cr2 = ADC_CR2_SWSTART,
|
2017-05-01 04:39:32 -07:00
|
|
|
/**
|
|
|
|
* here we configure all possible channels for fast mode. Some channels would not actually
|
|
|
|
* be used hopefully that's fine to configure all possible channels.
|
|
|
|
*
|
|
|
|
*/
|
2020-09-01 04:38:35 -07:00
|
|
|
// sample times for channels 10...18
|
|
|
|
.smpr1 =
|
2017-05-01 04:39:32 -07:00
|
|
|
ADC_SMPR1_SMP_AN10(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR1_SMP_AN11(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR1_SMP_AN12(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR1_SMP_AN13(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR1_SMP_AN14(ADC_SAMPLING_FAST) |
|
2020-09-01 04:38:35 -07:00
|
|
|
ADC_SMPR1_SMP_AN15(ADC_SAMPLING_FAST),
|
|
|
|
// In this field must be specified the sample times for channels 0...9
|
|
|
|
.smpr2 =
|
2017-05-01 04:39:32 -07:00
|
|
|
ADC_SMPR2_SMP_AN0(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN1(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN2(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN3(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN4(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN5(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN6(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN7(ADC_SAMPLING_FAST) |
|
|
|
|
ADC_SMPR2_SMP_AN8(ADC_SAMPLING_FAST) |
|
2020-09-01 04:38:35 -07:00
|
|
|
ADC_SMPR2_SMP_AN9(ADC_SAMPLING_FAST),
|
|
|
|
.htr = 0,
|
|
|
|
.ltr = 0,
|
|
|
|
.sqr1 = 0, // Conversion group sequence 13...16 + sequence length
|
|
|
|
.sqr2 = 0, // Conversion group sequence 7...12
|
2020-09-12 06:04:26 -07:00
|
|
|
.sqr3 = 0, // Conversion group sequence 1...6
|
|
|
|
#if ADC_MAX_CHANNELS_COUNT > 16
|
|
|
|
.sqr4 = 0, // Conversion group sequence 19...24
|
|
|
|
.sqr5 = 0 // Conversion group sequence 25...30
|
|
|
|
#endif /* ADC_MAX_CHANNELS_COUNT */
|
2020-09-01 04:38:35 -07:00
|
|
|
};
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2023-11-02 15:31:03 -07:00
|
|
|
static NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST * ADC_MAX_CHANNELS_COUNT];
|
2022-10-27 17:32:35 -07:00
|
|
|
AdcDevice fastAdc(&adcgrpcfgFast, fastAdcSampleBuf, efi::size(fastAdcSampleBuf));
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2020-04-23 19:50:18 -07:00
|
|
|
static void fast_adc_callback(GPTDriver*) {
|
2019-04-12 17:52:51 -07:00
|
|
|
#if EFI_INTERNAL_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
/*
|
|
|
|
* Starts an asynchronous ADC conversion operation, the conversion
|
|
|
|
* will be executed in parallel to the current PWM cycle and will
|
|
|
|
* terminate before the next PWM cycle.
|
|
|
|
*/
|
2024-05-05 09:21:48 -07:00
|
|
|
chSysLockFromISR();
|
|
|
|
if ((ADC_FAST_DEVICE.state != ADC_READY) &&
|
|
|
|
(ADC_FAST_DEVICE.state != ADC_COMPLETE) &&
|
|
|
|
(ADC_FAST_DEVICE.state != ADC_ERROR)) {
|
2024-04-22 10:33:18 -07:00
|
|
|
engine->outputChannels.fastAdcErrorsCount++;
|
2023-08-20 19:23:44 -07:00
|
|
|
// todo: when? why? criticalError("ADC fast not ready?");
|
2024-04-23 13:34:22 -07:00
|
|
|
// see notes at https://github.com/rusefi/rusefi/issues/6399
|
2024-05-09 03:45:25 -07:00
|
|
|
} else {
|
|
|
|
adcStartConversionI(&ADC_FAST_DEVICE, &adcgrpcfgFast, fastAdc.samples, ADC_BUF_DEPTH_FAST);
|
|
|
|
fastAdc.conversionCount++;
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
2023-12-10 07:21:56 -08:00
|
|
|
chSysUnlockFromISR();
|
2017-11-27 18:49:58 -08:00
|
|
|
#endif /* EFI_INTERNAL_ADC */
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
2021-02-28 04:30:19 -08:00
|
|
|
#endif // EFI_USE_FAST_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2021-02-09 19:04:36 -08:00
|
|
|
static float mcuTemperature;
|
2020-10-14 19:39:16 -07:00
|
|
|
|
2021-02-09 19:04:36 -08:00
|
|
|
float getMCUInternalTemperature() {
|
|
|
|
return mcuTemperature;
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int getInternalAdcValue(const char *msg, adc_channel_e hwChannel) {
|
2021-01-05 13:02:20 -08:00
|
|
|
if (!isAdcChannelValid(hwChannel)) {
|
2023-04-11 17:01:34 -07:00
|
|
|
warning(ObdCode::CUSTOM_OBD_ANALOG_INPUT_NOT_CONFIGURED, "ADC: %s input is not configured", msg);
|
2017-03-24 10:41:36 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-02-28 04:30:19 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
2024-05-05 13:02:14 -07:00
|
|
|
if (adcHwChannelMode[hwChannel] == ADC_FAST) {
|
2017-03-24 10:41:36 -07:00
|
|
|
int internalIndex = fastAdc.internalAdcIndexByHardwareIndex[hwChannel];
|
|
|
|
// todo if ADC_BUF_DEPTH_FAST EQ 1
|
|
|
|
// return fastAdc.samples[internalIndex];
|
|
|
|
int value = getAvgAdcValue(internalIndex, fastAdc.samples, ADC_BUF_DEPTH_FAST, fastAdc.size());
|
|
|
|
return value;
|
|
|
|
}
|
2021-02-28 04:30:19 -08:00
|
|
|
#endif // EFI_USE_FAST_ADC
|
|
|
|
|
2021-05-13 12:51:18 -07:00
|
|
|
return slowAdcSamples[hwChannel - EFI_ADC_0];
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2021-02-28 04:30:19 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
2020-04-23 19:50:18 -07:00
|
|
|
static GPTConfig fast_adc_config = {
|
2024-04-29 01:23:04 -07:00
|
|
|
.frequency = GPT_FREQ_FAST,
|
|
|
|
.callback = fast_adc_callback,
|
|
|
|
.cr2 = 0,
|
|
|
|
.dier = 0,
|
2020-04-23 19:50:18 -07:00
|
|
|
};
|
2021-02-28 04:30:19 -08:00
|
|
|
#endif /* EFI_USE_FAST_ADC */
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2020-09-08 14:20:55 -07:00
|
|
|
adc_channel_mode_e getAdcMode(adc_channel_e hwChannel) {
|
2024-05-05 13:02:14 -07:00
|
|
|
return adcHwChannelMode[hwChannel];
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2021-03-04 16:55:09 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
|
|
|
|
2019-06-08 06:51:36 -07:00
|
|
|
int AdcDevice::size() const {
|
2017-03-24 10:41:36 -07:00
|
|
|
return channelCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AdcDevice::init(void) {
|
|
|
|
hwConfig->num_channels = size();
|
2020-09-08 14:20:55 -07:00
|
|
|
/* driver does this internally */
|
|
|
|
//hwConfig->sqr1 += ADC_SQR1_NUM_CH(size());
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void AdcDevice::enableChannel(adc_channel_e hwChannel) {
|
2021-05-13 12:51:18 -07:00
|
|
|
if ((channelCount + 1) >= ADC_MAX_CHANNELS_COUNT) {
|
2023-08-20 19:23:44 -07:00
|
|
|
criticalError("Too many ADC channels configured");
|
2020-09-21 02:37:51 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-24 10:41:36 -07:00
|
|
|
int logicChannel = channelCount++;
|
|
|
|
|
2021-05-13 12:51:18 -07:00
|
|
|
/* TODO: following is correct for STM32 ADC1/2.
|
|
|
|
* ADC3 has another input to gpio mapping
|
|
|
|
* and should be handled separately */
|
|
|
|
size_t channelAdcIndex = hwChannel - EFI_ADC_0;
|
2020-09-06 15:25:26 -07:00
|
|
|
|
2017-03-24 10:41:36 -07:00
|
|
|
internalAdcIndexByHardwareIndex[hwChannel] = logicChannel;
|
|
|
|
if (logicChannel < 6) {
|
2020-11-22 09:23:27 -08:00
|
|
|
hwConfig->sqr3 |= channelAdcIndex << (5 * logicChannel);
|
2017-03-24 10:41:36 -07:00
|
|
|
} else if (logicChannel < 12) {
|
2020-11-22 09:23:27 -08:00
|
|
|
hwConfig->sqr2 |= channelAdcIndex << (5 * (logicChannel - 6));
|
2020-09-12 06:04:26 -07:00
|
|
|
} else if (logicChannel < 18) {
|
2020-11-22 09:23:27 -08:00
|
|
|
hwConfig->sqr1 |= channelAdcIndex << (5 * (logicChannel - 12));
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
2020-09-12 06:04:26 -07:00
|
|
|
#if ADC_MAX_CHANNELS_COUNT > 16
|
|
|
|
else if (logicChannel < 24) {
|
2020-11-22 09:23:27 -08:00
|
|
|
hwConfig->sqr4 |= channelAdcIndex << (5 * (logicChannel - 18));
|
2020-09-12 06:04:26 -07:00
|
|
|
}
|
|
|
|
else if (logicChannel < 30) {
|
2020-11-22 09:23:27 -08:00
|
|
|
hwConfig->sqr5 |= channelAdcIndex << (5 * (logicChannel - 24));
|
2020-09-12 06:04:26 -07:00
|
|
|
}
|
|
|
|
#endif /* ADC_MAX_CHANNELS_COUNT */
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2024-05-09 04:26:51 -07:00
|
|
|
adc_channel_e AdcDevice::getAdcChannelByInternalIndex(int hwChannel) const {
|
|
|
|
for (size_t idx = EFI_ADC_0; idx < EFI_ADC_TOTAL_CHANNELS; idx++) {
|
|
|
|
if (internalAdcIndexByHardwareIndex[idx] == hwChannel) {
|
|
|
|
return (adc_channel_e)idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return EFI_ADC_NONE;
|
2021-03-04 16:55:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // EFI_USE_FAST_ADC
|
|
|
|
|
2019-03-02 15:41:25 -08:00
|
|
|
static void printAdcValue(int channel) {
|
|
|
|
int value = getAdcValue("print", (adc_channel_e)channel);
|
2023-01-08 14:29:29 -08:00
|
|
|
float volts = adcToVoltsDivided(value, (adc_channel_e)channel);
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("adc voltage : %.2f", volts);
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2021-03-04 16:55:09 -08:00
|
|
|
static uint32_t slowAdcConversionCount = 0;
|
|
|
|
static uint32_t slowAdcErrorsCount = 0;
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2024-05-09 04:59:52 -07:00
|
|
|
static void printAdcChannedReport(const char *prefix, int internalIndex, adc_channel_e hwChannel)
|
|
|
|
{
|
|
|
|
if (isAdcChannelValid(hwChannel)) {
|
|
|
|
ioportid_t port = getAdcChannelPort("print", hwChannel);
|
|
|
|
int pin = getAdcChannelPin(hwChannel);
|
|
|
|
int adcValue = getAdcValue("print", hwChannel);
|
|
|
|
float volts = getVoltage("print", hwChannel);
|
|
|
|
float voltsDivided = getVoltageDivided("print", hwChannel);
|
|
|
|
/* Human index starts from 1 */
|
|
|
|
efiPrintf(" %s ch[%2d] @ %s%d ADC%d 12bit=%4d %.3fV (input %.3fV)",
|
|
|
|
prefix, internalIndex, portname(port), pin,
|
|
|
|
/* TODO: */ hwChannel - EFI_ADC_0 + 1,
|
|
|
|
adcValue, volts, voltsDivided);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-17 10:42:10 -07:00
|
|
|
void printFullAdcReport(void) {
|
2021-02-28 04:30:19 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
2021-05-03 13:44:19 -07:00
|
|
|
efiPrintf("fast %d samples", fastAdc.conversionCount);
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2021-05-03 13:44:19 -07:00
|
|
|
for (int internalIndex = 0; internalIndex < fastAdc.size(); internalIndex++) {
|
2024-05-09 04:26:51 -07:00
|
|
|
adc_channel_e hwChannel = fastAdc.getAdcChannelByInternalIndex(internalIndex);
|
2020-09-08 14:20:55 -07:00
|
|
|
|
2024-05-09 04:59:52 -07:00
|
|
|
printAdcChannedReport("F", internalIndex, hwChannel);
|
2020-09-08 14:20:55 -07:00
|
|
|
}
|
2021-02-28 04:30:19 -08:00
|
|
|
#endif // EFI_USE_FAST_ADC
|
2021-05-03 13:44:19 -07:00
|
|
|
efiPrintf("slow %d samples", slowAdcConversionCount);
|
2020-09-08 14:20:55 -07:00
|
|
|
|
2021-05-03 13:44:19 -07:00
|
|
|
/* we assume that all slow ADC channels are enabled */
|
|
|
|
for (int internalIndex = 0; internalIndex < ADC_MAX_CHANNELS_COUNT; internalIndex++) {
|
2024-05-05 08:51:47 -07:00
|
|
|
adc_channel_e hwChannel = static_cast<adc_channel_e>(internalIndex + EFI_ADC_0);
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2024-05-09 04:59:52 -07:00
|
|
|
printAdcChannedReport("S", internalIndex, hwChannel);
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setAdcDebugReporting(int value) {
|
|
|
|
adcDebugReporting = value;
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("adcDebug=%d", adcDebugReporting);
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2021-03-15 07:23:19 -07:00
|
|
|
void waitForSlowAdc(uint32_t lastAdcCounter) {
|
2017-08-07 04:28:21 -07:00
|
|
|
// we use slowAdcCounter instead of slowAdc.conversionCount because we need ADC_COMPLETE state
|
|
|
|
// todo: use sync.objects?
|
2018-01-22 14:45:10 -08:00
|
|
|
while (slowAdcCounter <= lastAdcCounter) {
|
2017-08-07 04:28:21 -07:00
|
|
|
chThdSleepMilliseconds(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-22 14:45:10 -08:00
|
|
|
int getSlowAdcCounter() {
|
|
|
|
return slowAdcCounter;
|
|
|
|
}
|
|
|
|
|
2019-10-11 17:43:21 -07:00
|
|
|
|
2023-06-11 20:23:17 -07:00
|
|
|
class SlowAdcController : public PeriodicController<UTILITY_THREAD_STACK_SIZE> {
|
2019-12-11 06:28:11 -08:00
|
|
|
public:
|
2024-01-06 18:31:18 -08:00
|
|
|
SlowAdcController()
|
2021-02-28 04:30:45 -08:00
|
|
|
: PeriodicController("ADC", PRIO_ADC, SLOW_ADC_RATE)
|
2019-12-11 06:28:11 -08:00
|
|
|
{
|
|
|
|
}
|
2019-10-08 17:44:59 -07:00
|
|
|
|
2019-12-21 18:11:09 -08:00
|
|
|
void PeriodicTask(efitick_t nowNt) override {
|
2019-12-11 06:28:11 -08:00
|
|
|
{
|
|
|
|
ScopePerf perf(PE::AdcConversionSlow);
|
2019-10-08 17:44:59 -07:00
|
|
|
|
2021-03-04 16:55:09 -08:00
|
|
|
slowAdcConversionCount++;
|
|
|
|
if (!readSlowAnalogInputs(slowAdcSamples)) {
|
|
|
|
slowAdcErrorsCount++;
|
2019-12-11 06:28:11 -08:00
|
|
|
return;
|
|
|
|
}
|
2019-12-17 05:34:56 -08:00
|
|
|
|
2021-02-09 19:04:36 -08:00
|
|
|
// Ask the port to sample the MCU temperature
|
|
|
|
mcuTemperature = getMcuTemperature();
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
2019-09-21 11:33:38 -07:00
|
|
|
|
2019-12-11 06:28:11 -08:00
|
|
|
{
|
|
|
|
ScopePerf perf(PE::AdcProcessSlow);
|
|
|
|
|
|
|
|
slowAdcCounter++;
|
|
|
|
|
2020-02-08 14:48:15 -08:00
|
|
|
AdcSubscription::UpdateSubscribers(nowNt);
|
2022-05-17 20:49:18 -07:00
|
|
|
|
|
|
|
protectedGpio_check(nowNt);
|
2019-12-11 06:28:11 -08:00
|
|
|
}
|
2019-10-08 17:44:59 -07:00
|
|
|
}
|
2019-12-11 06:28:11 -08:00
|
|
|
};
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2024-05-05 13:02:14 -07:00
|
|
|
void addChannel(const char*, adc_channel_e hwChannel, adc_channel_mode_e mode) {
|
2024-05-05 08:51:47 -07:00
|
|
|
if (!isAdcChannelValid(hwChannel)) {
|
2017-03-24 10:41:36 -07:00
|
|
|
return;
|
|
|
|
}
|
2019-12-02 17:32:21 -08:00
|
|
|
|
2021-02-28 04:30:19 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
|
|
|
if (mode == ADC_FAST) {
|
2024-05-05 08:51:47 -07:00
|
|
|
fastAdc.enableChannel(hwChannel);
|
2021-02-28 04:30:19 -08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-05-05 13:02:14 -07:00
|
|
|
adcHwChannelMode[hwChannel] = mode;
|
2021-08-24 13:41:16 -07:00
|
|
|
// Nothing to do for slow channels, input is mapped to analog in init_sensors.cpp
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2024-05-05 13:02:14 -07:00
|
|
|
void removeChannel(const char*, adc_channel_e hwChannel) {
|
2024-05-05 08:51:47 -07:00
|
|
|
if (!isAdcChannelValid(hwChannel)) {
|
2019-03-28 19:46:10 -07:00
|
|
|
return;
|
|
|
|
}
|
2024-05-05 13:02:14 -07:00
|
|
|
#if EFI_USE_FAST_ADC
|
|
|
|
if (adcHwChannelMode[hwChannel] == ADC_FAST) {
|
|
|
|
/* TODO: */
|
|
|
|
//fastAdc.disableChannel(hwChannel);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
adcHwChannelMode[hwChannel] = ADC_OFF;
|
2019-03-28 19:46:10 -07:00
|
|
|
}
|
|
|
|
|
2021-02-28 13:57:57 -08:00
|
|
|
// Weak link a stub so that every board doesn't have to implement this function
|
|
|
|
__attribute__((weak)) void setAdcChannelOverrides() { }
|
|
|
|
|
2021-11-15 04:02:34 -08:00
|
|
|
static void configureInputs() {
|
2024-05-05 13:02:14 -07:00
|
|
|
memset(adcHwChannelMode, 0, sizeof(adcHwChannelMode));
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2019-12-03 20:55:18 -08:00
|
|
|
/**
|
|
|
|
* order of analog channels here is totally random and has no meaning
|
|
|
|
* we also have some weird implementation with internal indices - that all has no meaning, it's just a random implementation
|
|
|
|
* which does not mean anything.
|
|
|
|
*/
|
|
|
|
|
2017-03-24 10:41:36 -07:00
|
|
|
addChannel("MAP", engineConfiguration->map.sensor.hwChannel, ADC_FAST);
|
2020-03-29 16:07:07 -07:00
|
|
|
|
|
|
|
addChannel("HIP9011", engineConfiguration->hipOutputChannel, ADC_FAST);
|
2017-03-24 10:41:36 -07:00
|
|
|
|
|
|
|
// not currently used addChannel("Vref", engineConfiguration->vRefAdcChannel, ADC_SLOW);
|
2020-09-21 03:10:25 -07:00
|
|
|
|
|
|
|
addChannel("AUXF#1", engineConfiguration->auxFastSensor1_adcChannel, ADC_FAST);
|
|
|
|
|
2019-03-28 19:46:10 -07:00
|
|
|
setAdcChannelOverrides();
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2019-12-11 06:28:11 -08:00
|
|
|
static SlowAdcController slowAdcController;
|
|
|
|
|
2019-08-01 22:36:02 -07:00
|
|
|
void initAdcInputs() {
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("initAdcInputs()");
|
2017-03-24 10:41:36 -07:00
|
|
|
|
|
|
|
configureInputs();
|
|
|
|
|
|
|
|
// migrate to 'enable adcdebug'
|
2017-04-04 20:17:56 -07:00
|
|
|
addConsoleActionI("adcdebug", &setAdcDebugReporting);
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2019-04-12 17:52:51 -07:00
|
|
|
#if EFI_INTERNAL_ADC
|
2021-02-09 19:04:36 -08:00
|
|
|
portInitAdc();
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2019-12-11 06:28:11 -08:00
|
|
|
// Start the slow ADC thread
|
2022-07-21 12:17:32 -07:00
|
|
|
slowAdcController.start();
|
2017-04-05 19:41:51 -07:00
|
|
|
|
2021-02-28 04:30:19 -08:00
|
|
|
#if EFI_USE_FAST_ADC
|
2020-09-29 03:34:39 -07:00
|
|
|
fastAdc.init();
|
2021-02-28 04:30:19 -08:00
|
|
|
|
2020-09-29 03:34:39 -07:00
|
|
|
gptStart(EFI_INTERNAL_FAST_ADC_GPT, &fast_adc_config);
|
|
|
|
gptStartContinuous(EFI_INTERNAL_FAST_ADC_GPT, GPT_PERIOD_FAST);
|
2021-02-28 04:30:19 -08:00
|
|
|
#endif // EFI_USE_FAST_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
|
|
|
|
addConsoleActionI("adc", (VoidInt) printAdcValue);
|
|
|
|
#else
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("ADC disabled");
|
2017-03-24 10:41:36 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-05-03 13:44:19 -07:00
|
|
|
void printFullAdcReportIfNeeded(void) {
|
2017-03-24 10:41:36 -07:00
|
|
|
if (!adcDebugReporting)
|
|
|
|
return;
|
2021-05-03 13:44:19 -07:00
|
|
|
printFullAdcReport();
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2021-02-28 13:57:57 -08:00
|
|
|
#else /* not HAL_USE_ADC */
|
|
|
|
|
2021-11-16 01:15:29 -08:00
|
|
|
__attribute__((weak)) float getVoltageDivided(const char*, adc_channel_e) {
|
2021-02-28 13:57:57 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// voltage in MCU universe, from zero to VDD
|
2021-11-16 01:15:29 -08:00
|
|
|
__attribute__((weak)) float getVoltage(const char*, adc_channel_e) {
|
2021-02-28 13:57:57 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|