rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
adc_onchip_fast.cpp
Go to the documentation of this file.
1/**
2 * @file adc_inputs_onchip.cpp
3 * @brief Low level ADC code
4 *
5 * rusEfi uses two ADC devices on the same 16 pins at the moment. Two ADC devices are used in order to distinguish between
6 * fast and slow devices. The idea is that but only having few channels in 'fast' mode we can sample those faster?
7 *
8 * Slow ADC group is used for IAT, CLT, AFR, VBATT etc - this one is currently sampled at 500Hz
9 *
10 * Fast ADC group is used for MAP, MAF HIP - this one is currently sampled at 10KHz
11 * We need frequent MAP for map_averaging.cpp
12 *
13 * 10KHz equals one measurement every 3.6 degrees at 6000 RPM
14 *
15 * PS: analog muxes allow to double number of analog inputs
16 * oh, and ADC3 is dedicated for knock
17 *
18 * @date Jan 14, 2013
19 * @author Andrey Belomutskiy, (c) 2012-2020
20 */
21
22#include "pch.h"
23
24#if HAL_USE_ADC
25
26#include "adc_device.h"
27#include "adc_subscription.h"
28#include "mpu_util.h"
30#include "protected_gpio.h"
31
32#ifndef ADC_MAX_CHANNELS_COUNT
33#define ADC_MAX_CHANNELS_COUNT 16
34#endif /* ADC_MAX_CHANNELS_COUNT */
35
36#if EFI_USE_FAST_ADC
37
38// is there a reason to have this configurable at runtime?
39#ifndef ADC_FAST_DEVICE
40#define ADC_FAST_DEVICE ADCD2
41#endif
42
43// Depth of the conversion buffer, channels are sampled X times each
44#ifndef ADC_BUF_DEPTH_FAST
45#define ADC_BUF_DEPTH_FAST 4
46#endif
47
48// See https://github.com/rusefi/rusefi/issues/976 for discussion on this value
49#ifndef ADC_SAMPLING_FAST
50#define ADC_SAMPLING_FAST ADC_SAMPLE_28
51#endif
52
53AdcDevice::AdcDevice(ADCDriver *p_adcp, ADCConversionGroup* p_hwConfig, volatile adcsample_t *p_buf, size_t p_depth) {
54 adcp = p_adcp;
55 depth = p_depth;
56 hwConfig = p_hwConfig;
57 samples = p_buf;
58
59 hwConfig->sqr1 = 0;
60 hwConfig->sqr2 = 0;
61 hwConfig->sqr3 = 0;
62#if ADC_MAX_CHANNELS_COUNT > 16
63 hwConfig->sqr4 = 0;
64 hwConfig->sqr5 = 0;
65#endif /* ADC_MAX_CHANNELS_COUNT */
67}
68
69static void fastAdcDoneCB(ADCDriver *adcp);
70static void fastAdcErrorCB(ADCDriver *, adcerror_t err);
71
72static ADCConversionGroup adcgrpcfgFast = {
73#if defined(EFI_INTERNAL_FAST_ADC_PWM)
74 .circular = TRUE,
75#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
76 .circular = FALSE,
77#endif
78 .num_channels = 0,
79 .end_cb = fastAdcDoneCB,
80 .error_cb = fastAdcErrorCB,
81 /* HW dependent part.*/
82 .cr1 = 0,
83#if defined(EFI_INTERNAL_FAST_ADC_PWM)
84 /* HW start using TIM8 CC 1 event rising edge
85 * See "External trigger for regular channels" for magic 13 number
86 * NOTE: Currently only TIM8 in PWM mode is supported */
87 .cr2 = ADC_CR2_EXTEN_0 | (13 << ADC_CR2_EXTSEL_Pos),
88#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
89 /* SW start through GPT callback and SW kick */
90 .cr2 = ADC_CR2_SWSTART,
91#endif
92 /**
93 * here we configure all possible channels for fast mode. Some channels would not actually
94 * be used hopefully that's fine to configure all possible channels.
95 *
96 */
97 // sample times for channels 10...18
98 .smpr1 =
99 ADC_SMPR1_SMP_AN10(ADC_SAMPLING_FAST) |
100 ADC_SMPR1_SMP_AN11(ADC_SAMPLING_FAST) |
101 ADC_SMPR1_SMP_AN12(ADC_SAMPLING_FAST) |
102 ADC_SMPR1_SMP_AN13(ADC_SAMPLING_FAST) |
103 ADC_SMPR1_SMP_AN14(ADC_SAMPLING_FAST) |
104 ADC_SMPR1_SMP_AN15(ADC_SAMPLING_FAST),
105 // In this field must be specified the sample times for channels 0...9
106 .smpr2 =
107 ADC_SMPR2_SMP_AN0(ADC_SAMPLING_FAST) |
108 ADC_SMPR2_SMP_AN1(ADC_SAMPLING_FAST) |
109 ADC_SMPR2_SMP_AN2(ADC_SAMPLING_FAST) |
110 ADC_SMPR2_SMP_AN3(ADC_SAMPLING_FAST) |
111 ADC_SMPR2_SMP_AN4(ADC_SAMPLING_FAST) |
112 ADC_SMPR2_SMP_AN5(ADC_SAMPLING_FAST) |
113 ADC_SMPR2_SMP_AN6(ADC_SAMPLING_FAST) |
114 ADC_SMPR2_SMP_AN7(ADC_SAMPLING_FAST) |
115 ADC_SMPR2_SMP_AN8(ADC_SAMPLING_FAST) |
116 ADC_SMPR2_SMP_AN9(ADC_SAMPLING_FAST),
117 .htr = 0,
118 .ltr = 0,
119 .sqr1 = 0, // Conversion group sequence 13...16 + sequence length
120 .sqr2 = 0, // Conversion group sequence 7...12
121 .sqr3 = 0, // Conversion group sequence 1...6
122#if ADC_MAX_CHANNELS_COUNT > 16
123 .sqr4 = 0, // Conversion group sequence 19...24
124 .sqr5 = 0 // Conversion group sequence 25...30
125#endif /* ADC_MAX_CHANNELS_COUNT */
126};
127
128static volatile NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST * ADC_MAX_CHANNELS_COUNT];
129
131
132static efitick_t lastTick = 0;
133
134static void fastAdcDoneCB(ADCDriver *adcp) {
135 // State may not be complete if we get a callback for "half done"
136 if (adcIsBufferComplete(adcp)) {
137 efitick_t nowTick = getTimeNowNt();
138 efitick_t diff = nowTick - lastTick;
139 lastTick = nowTick;
140
141 engine->outputChannels.fastAdcPeriod = (uint32_t)diff;
143
144 onFastAdcComplete(adcp->samples);
145 }
146}
147
148static void fastAdcErrorCB(ADCDriver *, adcerror_t err) {
149 engine->outputChannels.fastAdcLastError = (uint8_t)err;
151 if (err == ADC_ERR_OVERFLOW) {
153 }
154 // TODO: restart?
155}
156
157#if defined(EFI_INTERNAL_FAST_ADC_PWM)
158
159static const PWMConfig pwmcfg = {
160 /* on each trigger event regular group of channels is converted,
161 * to get whole buffer filled we need ADC_BUF_DEPTH_FAST trigger events */
162 .frequency = GPT_FREQ_FAST * ADC_BUF_DEPTH_FAST,
163 .period = GPT_PERIOD_FAST,
164 .callback = nullptr,
165 .channels = {
166 {PWM_OUTPUT_ACTIVE_HIGH, nullptr},
167 {PWM_OUTPUT_ACTIVE_HIGH, nullptr},
168 {PWM_OUTPUT_ACTIVE_HIGH, nullptr},
169 {PWM_OUTPUT_ACTIVE_HIGH, nullptr}
170 },
171 .cr2 = 0,
172 .bdtr = 0,
173 .dier = 0,
174};
175
176#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
177
179{
180#if EFI_INTERNAL_ADC
181 /*
182 * Starts an asynchronous ADC conversion operation, the conversion
183 * will be executed in parallel to the current PWM cycle and will
184 * terminate before the next PWM cycle.
185 */
187#endif /* EFI_INTERNAL_ADC */
188}
189
191 .frequency = GPT_FREQ_FAST,
192 .callback = fastAdcStartTrigger,
193 .cr2 = 0,
194 .dier = 0,
195};
196
197#else
198 #error Please define EFI_INTERNAL_FAST_ADC_PWM or EFI_INTERNAL_FAST_ADC_GPT for Fast ADC
199#endif
200
201int AdcDevice::size() const {
202 return channelCount;
203}
204
205void AdcDevice::init(void) {
206 hwConfig->num_channels = size();
207 /* driver does this internally */
208 //hwConfig->sqr1 += ADC_SQR1_NUM_CH(size());
209
210#if defined(EFI_INTERNAL_FAST_ADC_PWM)
211 // Start the timer running
212 pwmStart(EFI_INTERNAL_FAST_ADC_PWM, &pwmcfg);
213 pwmEnableChannel(EFI_INTERNAL_FAST_ADC_PWM, 0, /* width */ 1);
214 adcStartConversion(adcp, hwConfig, (adcsample_t *)samples, depth);
215#elif defined (EFI_INTERNAL_FAST_ADC_GPT)
216 gptStart(EFI_INTERNAL_FAST_ADC_GPT, &fast_adc_config);
217 gptStartContinuous(EFI_INTERNAL_FAST_ADC_GPT, GPT_PERIOD_FAST);
218#endif
219}
220
222 if ((channelCount + 1) >= ADC_MAX_CHANNELS_COUNT) {
223 criticalError("Too many ADC channels configured");
224 return -1;
225 }
226
227 int logicChannel = channelCount++;
228
229 /* TODO: following is correct for STM32 ADC1/2.
230 * ADC3 has another input to gpio mapping
231 * and should be handled separately */
232 size_t channelAdcIndex = hwChannel - EFI_ADC_0;
233
234 internalAdcIndexByHardwareIndex[hwChannel] = logicChannel;
235 if (logicChannel < 6) {
236 hwConfig->sqr3 |= channelAdcIndex << (5 * logicChannel);
237 } else if (logicChannel < 12) {
238 hwConfig->sqr2 |= channelAdcIndex << (5 * (logicChannel - 6));
239 } else if (logicChannel < 18) {
240 hwConfig->sqr1 |= channelAdcIndex << (5 * (logicChannel - 12));
241 }
242#if ADC_MAX_CHANNELS_COUNT > 16
243 else if (logicChannel < 24) {
244 hwConfig->sqr4 |= channelAdcIndex << (5 * (logicChannel - 18));
245 }
246 else if (logicChannel < 30) {
247 hwConfig->sqr5 |= channelAdcIndex << (5 * (logicChannel - 24));
248 }
249#endif /* ADC_MAX_CHANNELS_COUNT */
250
251 return channelAdcIndex;
252}
253
255{
256 chSysLockFromISR();
257 if ((ADC_FAST_DEVICE.state == ADC_READY) ||
258 (ADC_FAST_DEVICE.state == ADC_ERROR)) {
259 /* drop volatile type qualifier - this is safe */
260 adcStartConversionI(adcp, hwConfig, (adcsample_t *)samples, depth);
261 } else {
263 // todo: when? why? criticalError("ADC fast not ready?");
264 // see notes at https://github.com/rusefi/rusefi/issues/6399
265 }
266 chSysUnlockFromISR();
267}
268
270 uint32_t result = 0;
271 int numChannels = size();
272 int index = fastAdc.internalAdcIndexByHardwareIndex[hwChannel];
273 if (index == 0xff) {
274 criticalError("Fast ADC attempt to read unconfigured input %d.", hwChannel);
275 return 0;
276 }
277
278 for (size_t i = 0; i < depth; i++) {
279 adcsample_t sample = samples[index];
280 if (sample > ADC_MAX_VALUE) {
281 // 12bit ADC expected right now. An error here usually means major RAM corruption?
282 criticalError("ADC unexpected sample %d at %ld uptime.",
283 sample,
284 (uint32_t)getTimeNowS());
285 }
286 result += sample;
287 index += numChannels;
288 }
289
290 // this truncation is guaranteed to not be lossy - the average can't be larger than adcsample_t
291 return static_cast<adcsample_t>(result / depth);
292}
293
295 for (size_t idx = EFI_ADC_0; idx < EFI_ADC_TOTAL_CHANNELS; idx++) {
296 if (internalAdcIndexByHardwareIndex[idx] == hwChannel) {
297 return (adc_channel_e)idx;
298 }
299 }
300 return EFI_ADC_NONE;
301}
302
306
307#endif // EFI_USE_FAST_ADC
308
309#endif // HAL_USE_ADC
AdcDevice fastAdc
uint32_t AdcToken
Definition adc_inputs.h:98
static void fastAdcStartTrigger(GPTDriver *)
static const PWMConfig pwmcfg
AdcDevice fastAdc & ADC_FAST_DEVICE
static volatile NO_CACHE adcsample_t fastAdcSampleBuf[ADC_BUF_DEPTH_FAST *ADC_MAX_CHANNELS_COUNT]
static efitick_t lastTick
static const GPTConfig fast_adc_config
static void fastAdcDoneCB(ADCDriver *adcp)
static void fastAdcErrorCB(ADCDriver *, adcerror_t err)
static ADCConversionGroup adcgrpcfgFast
void init(void)
void startConversionI(void)
size_t depth
Definition adc_device.h:35
uint8_t internalAdcIndexByHardwareIndex[EFI_ADC_TOTAL_CHANNELS]
Definition adc_device.h:36
int size() const
adc_channel_e getAdcChannelByInternalIndex(int index) const
AdcToken getAdcChannelToken(adc_channel_e hwChannel)
int enableChannel(adc_channel_e hwChannel)
ADCConversionGroup * hwConfig
Definition adc_device.h:33
size_t channelCount
Definition adc_device.h:40
adcsample_t getAvgAdcValue(adc_channel_e hwChannel)
AdcDevice(ADCDriver *p_adcp, ADCConversionGroup *p_hwConfig, volatile adcsample_t *p_buf, size_t p_depth)
volatile adcsample_t * samples
Definition adc_device.h:34
ADCDriver * adcp
Definition adc_device.h:32
TunerStudioOutputChannels outputChannels
Definition engine.h:109
efitick_t getTimeNowNt()
Definition efitime.cpp:19
efitimesec_t getTimeNowS()
Current system time in seconds (32 bits)
Definition efitime.cpp:42
static EngineAccessor engine
Definition engine.h:413
adcerror_t
Possible ADC failure causes.
uint16_t adcsample_t
ADC sample data type.
@ ADC_ERR_OVERFLOW
gptfreq_t frequency
Timer clock in Hz.
void onFastAdcComplete(adcsample_t *)
Definition hardware.cpp:275
static union @47 NO_CACHE
Driver configuration structure.
Structure representing a GPT driver.
Type of a PWM driver configuration structure.
uint32_t frequency
Timer clock in Hz.