2017-03-24 10:41:36 -07:00
|
|
|
/**
|
|
|
|
* @file adc_inputs.cpp
|
|
|
|
* @brief Low level ADC code
|
|
|
|
*
|
|
|
|
* @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
|
|
|
|
2024-07-27 09:36:35 -07:00
|
|
|
float PUBLIC_API_WEAK getAnalogInputDividerCoefficient(adc_channel_e) {
|
2023-01-08 14:29:29 -08:00
|
|
|
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"
|
2024-06-20 02:24:43 -07:00
|
|
|
#include "AdcDevice.h"
|
2017-03-24 10:41:36 -07:00
|
|
|
#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
|
|
|
|
2024-06-20 06:22:47 -07:00
|
|
|
extern AdcDevice fastAdc;
|
2019-09-22 13:41:10 -07:00
|
|
|
|
2024-06-20 06:22:47 -07:00
|
|
|
static volatile NO_CACHE adcsample_t slowAdcSamples[SLOW_ADC_CHANNEL_COUNT];
|
2024-05-09 13:12:49 -07:00
|
|
|
|
2024-06-20 06:22:47 -07:00
|
|
|
static uint32_t slowAdcConversionCount = 0;
|
|
|
|
static uint32_t slowAdcErrorsCount = 0;
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2024-06-20 06:22:47 -07:00
|
|
|
static float mcuTemperature;
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2024-07-22 16:47:57 -07:00
|
|
|
static AdcChannelMode adcHwChannelMode[EFI_ADC_TOTAL_CHANNELS];
|
2017-03-24 10:41:36 -07:00
|
|
|
|
|
|
|
// todo: move this flag to Engine god object
|
|
|
|
static int adcDebugReporting = false;
|
|
|
|
|
2024-07-22 16:47:57 -07:00
|
|
|
AdcChannelMode getAdcMode(adc_channel_e hwChannel) {
|
2024-06-20 06:22:47 -07:00
|
|
|
return adcHwChannelMode[hwChannel];
|
2024-05-09 09:05:31 -07:00
|
|
|
}
|
|
|
|
|
2024-06-25 01:51:37 -07:00
|
|
|
float getMCUInternalTemperature() {
|
|
|
|
return mcuTemperature;
|
|
|
|
}
|
|
|
|
|
|
|
|
int getInternalAdcValue(const char *msg, adc_channel_e hwChannel) {
|
|
|
|
if (!isAdcChannelValid(hwChannel)) {
|
|
|
|
warning(ObdCode::CUSTOM_OBD_ANALOG_INPUT_NOT_CONFIGURED, "ADC: %s input is not configured", msg);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if EFI_USE_FAST_ADC
|
2024-07-22 16:47:57 -07:00
|
|
|
if (adcHwChannelMode[hwChannel] == AdcChannelMode::Fast) {
|
2024-06-25 01:51:37 -07:00
|
|
|
return fastAdc.getAvgAdcValue(hwChannel);
|
|
|
|
}
|
|
|
|
#endif // EFI_USE_FAST_ADC
|
|
|
|
|
|
|
|
return slowAdcSamples[hwChannel - EFI_ADC_0];
|
|
|
|
}
|
|
|
|
|
2019-03-02 15:41:25 -08:00
|
|
|
static void printAdcValue(int channel) {
|
2024-05-09 13:00:59 -07:00
|
|
|
/* Do this check before conversion to adc_channel_e that is uint8_t based */
|
|
|
|
if ((channel < EFI_ADC_NONE) || (channel >= EFI_ADC_TOTAL_CHANNELS)) {
|
|
|
|
efiPrintf("Invalid ADC channel %d", channel);
|
|
|
|
return;
|
|
|
|
}
|
2019-03-02 15:41:25 -08:00
|
|
|
int value = getAdcValue("print", (adc_channel_e)channel);
|
2023-01-08 14:29:29 -08:00
|
|
|
float volts = adcToVoltsDivided(value, (adc_channel_e)channel);
|
2024-05-09 13:00:59 -07:00
|
|
|
efiPrintf("adc %d voltage : %.3f", channel, volts);
|
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
|
2024-06-10 00:51:14 -07:00
|
|
|
efiPrintf("fast %lu 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
|
2024-06-10 00:51:14 -07:00
|
|
|
efiPrintf("slow %lu 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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2024-05-12 06:13:01 -07:00
|
|
|
/* drop volatile type qualifier - this is safe */
|
|
|
|
if (!readSlowAnalogInputs((adcsample_t *)slowAdcSamples)) {
|
2021-03-04 16:55:09 -08:00
|
|
|
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);
|
|
|
|
|
2020-02-08 14:48:15 -08:00
|
|
|
AdcSubscription::UpdateSubscribers(nowNt);
|
2022-05-17 20:49:18 -07:00
|
|
|
|
2024-07-20 19:08:10 -07:00
|
|
|
slowAdcConversionCount++;
|
|
|
|
|
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-07-22 16:28:17 -07:00
|
|
|
void addFastAdcChannel(const char*, adc_channel_e hwChannel) {
|
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
|
2024-07-22 16:28:17 -07:00
|
|
|
fastAdc.enableChannel(hwChannel);
|
2021-02-28 04:30:19 -08:00
|
|
|
#endif
|
|
|
|
|
2024-07-22 16:47:57 -07:00
|
|
|
adcHwChannelMode[hwChannel] = AdcChannelMode::Fast;
|
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
|
2024-07-22 16:47:57 -07:00
|
|
|
if (adcHwChannelMode[hwChannel] == AdcChannelMode::Fast) {
|
2024-05-05 13:02:14 -07:00
|
|
|
/* TODO: */
|
|
|
|
//fastAdc.disableChannel(hwChannel);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2024-07-22 16:47:57 -07:00
|
|
|
adcHwChannelMode[hwChannel] = AdcChannelMode::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-07-22 16:47:57 -07:00
|
|
|
memset(adcHwChannelMode, (int)AdcChannelMode::Off, 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.
|
|
|
|
*/
|
|
|
|
|
2024-07-22 16:28:17 -07:00
|
|
|
addFastAdcChannel("MAP", engineConfiguration->map.sensor.hwChannel);
|
2020-03-29 16:07:07 -07:00
|
|
|
|
2024-07-22 16:28:17 -07:00
|
|
|
addFastAdcChannel("HIP9011", engineConfiguration->hipOutputChannel);
|
2017-03-24 10:41:36 -07:00
|
|
|
|
2024-07-22 16:28:17 -07:00
|
|
|
// not currently used addFastAdcChannel("Vref", engineConfiguration->vRefAdcChannel, ADC_SLOW);
|
2020-09-21 03:10:25 -07:00
|
|
|
|
2024-07-22 16:28:17 -07:00
|
|
|
addFastAdcChannel("AUXF#1", engineConfiguration->auxFastSensor1_adcChannel);
|
2020-09-21 03:10:25 -07:00
|
|
|
|
2019-03-28 19:46:10 -07:00
|
|
|
setAdcChannelOverrides();
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
2024-06-20 06:22:47 -07:00
|
|
|
void waitForSlowAdc(uint32_t lastAdcCounter) {
|
2024-07-20 19:55:03 -07:00
|
|
|
// note that having ADC reading is one thing while having new sensor API is a totally different thing!
|
2024-06-20 06:22:47 -07:00
|
|
|
// todo: use sync.objects?
|
|
|
|
while (slowAdcConversionCount <= lastAdcCounter) {
|
|
|
|
chThdSleepMilliseconds(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
2024-06-25 05:04:11 -07:00
|
|
|
// After this point fastAdc is not allowed to add channels
|
2020-09-29 03:34:39 -07:00
|
|
|
fastAdc.init();
|
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);
|
2024-06-25 05:04:11 -07:00
|
|
|
#else // ! EFI_INTERNAL_ADC
|
2021-04-19 05:11:59 -07:00
|
|
|
efiPrintf("ADC disabled");
|
2024-06-25 05:04:11 -07:00
|
|
|
#endif // EFI_INTERNAL_ADC
|
2017-03-24 10:41:36 -07:00
|
|
|
}
|
|
|
|
|
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
|