rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
adc_inputs.cpp
Go to the documentation of this file.
1/**
2 * @file adc_inputs.cpp
3 * @brief Low level ADC code
4 *
5 * @date Jan 14, 2013
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9#include "pch.h"
10
14
15float PUBLIC_API_WEAK boardAdjustVoltage(float voltage, adc_channel_e /* hwChannel */) {
16 // a hack useful when we do not trust voltage just after board EN was turned on. is this just hiding electrical design flaws?
17 return voltage;
18}
19
20/* overall analog health state
21 * return negative in case of any problems
22 * return 0 if everything is ok or no diagnostic is available */
23int PUBLIC_API_WEAK boardGetAnalogDiagnostic() {
24 return 0;
25}
26
27/* simple implementation if board does not provide advanced diagnostic */
29#if EFI_PROD_CODE
30 /* for on-chip ADC inputs we check common analog health */
33 }
34#endif // EFI_PROD_CODE
35
36 /* input is outside chip/ECU */
37 return 0;
38}
39
40/* Get analog part diagnostic */
42{
43 /* TODO: debounce? */
45}
46
47#if HAL_USE_ADC
48
49#include "adc_subscription.h"
50#include "AdcDevice.h"
51#include "mpu_util.h"
52#include "protected_gpio.h"
53
54extern AdcDevice fastAdc;
55
56/* TODO: Drop NO_CACHE for F4 and F7 couse with ADCv2 driver CPU does averaging and CPU stores result to this array */
57/* TODO: store summ of samples is this array and divide on oversample factor only when converting to float - this will increase accuracity */
58static volatile NO_CACHE adcsample_t slowAdcSamples[SLOW_ADC_CHANNEL_COUNT];
59
60static uint32_t slowAdcConversionCount = 0;
61
62static float mcuTemperature;
63
64static AdcChannelMode adcHwChannelMode[EFI_ADC_TOTAL_CHANNELS];
65
66// todo: move this flag to Engine god object
67static int adcDebugReporting = false;
68
70 return adcHwChannelMode[hwChannel];
71}
72
76
77int getInternalAdcValue(const char *msg, adc_channel_e hwChannel) {
78 if (!isAdcChannelValid(hwChannel)) {
79 warning(ObdCode::CUSTOM_OBD_ANALOG_INPUT_NOT_CONFIGURED, "ADC: %s input is not configured", msg);
80 return -1;
81 }
82
83#if EFI_USE_FAST_ADC
84 if (adcHwChannelMode[hwChannel] == AdcChannelMode::Fast) {
85 return fastAdc.getAvgAdcValue(hwChannel);
86 }
87#endif // EFI_USE_FAST_ADC
88
89 return slowAdcSamples[hwChannel - EFI_ADC_0];
90}
91
92static void printAdcValue(int channel) {
93 /* Do this check before conversion to adc_channel_e that is uint8_t based */
94 if ((channel < EFI_ADC_NONE) || (channel >= EFI_ADC_TOTAL_CHANNELS)) {
95 efiPrintf("Invalid ADC channel %d", channel);
96 return;
97 }
98 int adcValue = adcGetRawValue("print", (adc_channel_e)channel);
99 float voltsInput = adcRawValueToScaledVoltage(adcValue, (adc_channel_e)channel);
100 efiPrintf("adc %d input %.3fV", channel, voltsInput);
101}
102
103static void printAdcChannedReport(const char *prefix, int internalIndex, adc_channel_e hwChannel)
104{
105 if (isAdcChannelValid(hwChannel)) {
106 ioportid_t port = getAdcChannelPort("print", hwChannel);
107 int pin = getAdcChannelPin(hwChannel);
108 int adcValue = adcGetRawValue("print", hwChannel);
109 float volts = adcGetRawVoltage("print", hwChannel);
110 float voltsInput = adcGetScaledVoltage("print", hwChannel);
111 /* Human index starts from 1 */
112 efiPrintf(" %s ch[%2d] @ %s%d ADC%d 12bit=%4d %.3fV input %.3fV",
113 prefix, internalIndex, portname(port), pin,
114 /* TODO: */ hwChannel - EFI_ADC_0 + 1,
115 adcValue, volts, voltsInput);
116 }
117}
118
120#if EFI_USE_FAST_ADC
121 efiPrintf("fast %u samples", engine->outputChannels.fastAdcConversionCount);
122
123 for (int internalIndex = 0; internalIndex < fastAdc.size(); internalIndex++) {
124 adc_channel_e hwChannel = fastAdc.getAdcChannelByInternalIndex(internalIndex);
125
126 printAdcChannedReport("F", internalIndex, hwChannel);
127 }
128#endif // EFI_USE_FAST_ADC
129 efiPrintf("slow %lu samples", slowAdcConversionCount);
130
131 /* we assume that all slow ADC channels are enabled */
132 for (int internalIndex = 0; internalIndex < ADC_MAX_CHANNELS_COUNT; internalIndex++) {
133 adc_channel_e hwChannel = static_cast<adc_channel_e>(internalIndex + EFI_ADC_0);
134
135 printAdcChannedReport("S", internalIndex, hwChannel);
136 }
137}
138
139static void setAdcDebugReporting(int value) {
140 adcDebugReporting = value;
141 efiPrintf("adcDebug=%d", adcDebugReporting);
142}
143
144void updateSlowAdc(efitick_t nowNt) {
145 {
147
148 /* drop volatile type qualifier - this is safe */
151 return;
152 }
153
154 // Ask the port to sample the MCU temperature
156 if (mcuTemperature > 150.0f || mcuTemperature < -50.0f) {
157 /*
158 * we have a sporadic issue with this check todo https://github.com/rusefi/rusefi/issues/2552
159 */
160 //criticalError("Invalid CPU temperature measured %f", degrees);
161 }
162 }
163
164 {
166
168
170
171 protectedGpio_check(nowNt);
172 }
173}
174
175void addFastAdcChannel(const char*, adc_channel_e hwChannel) {
176 if (!isAdcChannelValid(hwChannel)) {
177 return;
178 }
179
180#if EFI_USE_FAST_ADC
181 fastAdc.enableChannel(hwChannel);
182#endif
183
185 // Nothing to do for slow channels, input is mapped to analog in init_sensors.cpp
186}
187
188void removeChannel(const char*, adc_channel_e hwChannel) {
189 if (!isAdcChannelValid(hwChannel)) {
190 return;
191 }
192#if EFI_USE_FAST_ADC
193 if (adcHwChannelMode[hwChannel] == AdcChannelMode::Fast) {
194 /* TODO: */
195 //fastAdc.disableChannel(hwChannel);
196 }
197#endif
198
200}
201
202// Weak link a stub so that every board doesn't have to implement this function
204
205static void configureInputs() {
207
208 /**
209 * order of analog channels here is totally random and has no meaning
210 * we also have some weird implementation with internal indices - that all has no meaning, it's just a random implementation
211 * which does not mean anything.
212 */
213
215
216 // not currently used addFastAdcChannel("Vref", engineConfiguration->vRefAdcChannel, ADC_SLOW);
217
219
221}
222
223void waitForSlowAdc(uint32_t lastAdcCounter) {
224 // note that having ADC reading is one thing while having new sensor API is a totally different thing!
225 // todo: use sync.objects?
226 while (slowAdcConversionCount <= lastAdcCounter) {
227 chThdSleepMilliseconds(1);
228 }
229}
230
232 efiPrintf("initAdcInputs()");
233
235
236 // migrate to 'enable adcdebug'
238
239#if EFI_INTERNAL_ADC
240 portInitAdc();
241
242#if EFI_USE_FAST_ADC
243 // After this point fastAdc is not allowed to add channels
244 fastAdc.init();
245#endif // EFI_USE_FAST_ADC
246
248#else // ! EFI_INTERNAL_ADC
249 efiPrintf("ADC disabled");
250#endif // EFI_INTERNAL_ADC
251
252 // Workaround to pre-feed all sensors with some data...
253 chThdSleepMilliseconds(1);
255}
256
259 return;
261}
262
263#else /* not HAL_USE_ADC */
264
265// voltage in MCU universe, from zero to VDD
266__attribute__((weak)) float adcGetRawVoltage(const char*, adc_channel_e) {
267 return 0;
268}
269
270// voltage in ECU universe, with all input dividers and OpAmps gains taken into account, voltage at ECU connector pin
271__attribute__((weak)) float adcGetScaledVoltage(const char*, adc_channel_e) {
272 return 0;
273}
274
275#endif
void initAdcInputs()
static float mcuTemperature
int PUBLIC_API_WEAK boardGetAnalogDiagnostic()
void updateSlowAdc(efitick_t nowNt)
static void setAdcDebugReporting(int value)
static void printAdcValue(int channel)
adc_channel_e
void waitForSlowAdc(uint32_t lastAdcCounter)
static volatile NO_CACHE adcsample_t slowAdcSamples[SLOW_ADC_CHANNEL_COUNT]
AdcChannelMode getAdcMode(adc_channel_e hwChannel)
static uint32_t slowAdcConversionCount
void removeChannel(const char *, adc_channel_e hwChannel)
int analogGetDiagnostic()
int PUBLIC_API_WEAK boardGetAnalogInputDiagnostic(adc_channel_e channel, float)
float PUBLIC_API_WEAK boardAdjustVoltage(float voltage, adc_channel_e)
int getInternalAdcValue(const char *msg, adc_channel_e hwChannel)
void printFullAdcReportIfNeeded(void)
static AdcChannelMode adcHwChannelMode[EFI_ADC_TOTAL_CHANNELS]
static int adcDebugReporting
static void printAdcChannedReport(const char *prefix, int internalIndex, adc_channel_e hwChannel)
float getMCUInternalTemperature()
float PUBLIC_API_WEAK getAnalogInputDividerCoefficient(adc_channel_e)
static void configureInputs()
void printFullAdcReport(void)
AdcDevice fastAdc
void addFastAdcChannel(const char *, adc_channel_e hwChannel)
bool isAdcChannelValid(adc_channel_e hwChannel)
Definition adc_inputs.h:21
uint16_t channel
Definition adc_inputs.h:109
bool isAdcChannelOnChip(adc_channel_e hwChannel)
Definition adc_inputs.h:34
AdcChannelMode
Definition adc_inputs.h:75
float adcGetScaledVoltage(const char *msg, adc_channel_e hwChannel)
float adcGetRawVoltage(const char *msg, adc_channel_e hwChannel)
typedef __attribute__
Ignition Mode.
int size() const
adc_channel_e getAdcChannelByInternalIndex(int index) const
int enableChannel(adc_channel_e hwChannel)
adcsample_t getAvgAdcValue(adc_channel_e hwChannel)
static void UpdateSubscribers(efitick_t nowNt)
TunerStudioOutputChannels outputChannels
Definition engine.h:108
void addConsoleActionI(const char *token, VoidInt callback)
Register a console command with one Integer parameter.
void(* VoidInt)(int)
void setAdcChannelOverrides()
bool readSlowAnalogInputs(adcsample_t *convertedSamples)
Definition mpu_util.cpp:269
float getMcuTemperature()
Definition mpu_util.cpp:264
void portInitAdc()
Definition mpu_util.cpp:256
int getAdcChannelPin(adc_channel_e hwChannel)
ioportid_t getAdcChannelPort(const char *msg, adc_channel_e hwChannel)
const char * portname(ioportid_t GPIOx)
efitick_t getTimeNowNt()
Definition efitime.cpp:19
static EngineAccessor engine
Definition engine.h:410
static constexpr engine_configuration_s * engineConfiguration
bool warning(ObdCode code, const char *fmt,...)
uint16_t adcsample_t
ADC sample data type.
GPIO_TypeDef * ioportid_t
Port Identifier.
static union @47 NO_CACHE
@ CUSTOM_OBD_ANALOG_INPUT_NOT_CONFIGURED
@ AdcConversionSlow
@ AdcProcessSlow
void protectedGpio_check(efitick_t nowNt)
brain_pin_e pin
Definition stm32_adc.cpp:15