rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
stm32_adc.cpp
Go to the documentation of this file.
1/**
2 * @file stm32_common_adc.cpp
3 * @brief Low level common STM32 code
4 *
5 * @date Mar 28, 2019
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9#include "pch.h"
10#include "efilib.h"
11
12#if HAL_USE_ADC
13
14static const struct {
17 uint8_t adc; /* bitmask of ADC available on this pin */
18} adcChannels[] = {
19 { Gpio::A0, EFI_ADC_0, BIT(0) | BIT(1) | BIT(2) },
20 { Gpio::A1, EFI_ADC_1, BIT(0) | BIT(1) | BIT(2) },
21 { Gpio::A2, EFI_ADC_2, BIT(0) | BIT(1) | BIT(2) },
22 { Gpio::A3, EFI_ADC_3, BIT(0) | BIT(1) | BIT(2) },
23 { Gpio::A4, EFI_ADC_4, BIT(0) | BIT(1) },
24 { Gpio::F6, EFI_ADC_32, BIT(2) }, //ADC3 only
25 { Gpio::A5, EFI_ADC_5, BIT(0) | BIT(1) },
26 { Gpio::F7, EFI_ADC_33, BIT(2) }, //ADC3 only
27 { Gpio::A6, EFI_ADC_6, BIT(0) | BIT(1) },
28 { Gpio::F8, EFI_ADC_34, BIT(2) }, //ADC3 only
29 { Gpio::A7, EFI_ADC_7, BIT(0) | BIT(1) },
30 { Gpio::F9, EFI_ADC_35, BIT(2) }, //ADC3 only
31 { Gpio::B0, EFI_ADC_8, BIT(0) | BIT(1) },
32 { Gpio::F10, EFI_ADC_36, BIT(2) }, //ADC3 only
33 { Gpio::B1, EFI_ADC_9, BIT(0) | BIT(1) },
34 { Gpio::F3, EFI_ADC_37, BIT(2) }, //ADC3 only
35 { Gpio::C0, EFI_ADC_10, BIT(0) | BIT(1) | BIT(2) },
36 { Gpio::C1, EFI_ADC_11, BIT(0) | BIT(1) | BIT(2) },
37 { Gpio::C2, EFI_ADC_12, BIT(0) | BIT(1) | BIT(2) },
38 { Gpio::C3, EFI_ADC_13, BIT(0) | BIT(1) | BIT(2) },
39 { Gpio::C4, EFI_ADC_14, BIT(0) | BIT(1) },
40 { Gpio::F4, EFI_ADC_38, BIT(2) }, //ADC3 only
41 { Gpio::C5, EFI_ADC_15, BIT(0) | BIT(1) },
42 { Gpio::F5, EFI_ADC_39, BIT(2) }, //ADC3 only
43 /* TODO: add ADC3 channels */
44};
45
46brain_pin_e getAdcChannelBrainPin(const char *msg, adc_channel_e hwChannel) {
47 static_assert(EFI_ADC_NONE == ADC_CHANNEL_NONE);
48
49 /* Muxed adc inputs */
50 hwChannel = adcMuxedGetParent(hwChannel);
51
52 for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
53 if (adcChannels[idx].ch == hwChannel) {
54 return adcChannels[idx].pin;
55 }
56 }
57
58 /* todo: what is upper range ADC is used while lower range ADC is not used? how do we still mark pin used?
59 * external muxes for internal ADC #3350
60 * firmwareError(ObdCode::CUSTOM_ERR_ADC_UNKNOWN_CHANNEL, "Unknown hw channel %d [%s]", hwChannel, msg);
61 */
62 (void)msg;
63
64 return Gpio::Invalid;
65}
66
68#ifdef ADC_MUX_PIN
69 return ((hwChannel >= EFI_ADC_16) && (hwChannel <= EFI_ADC_31));
70#else
71 UNUSED(hwChannel);
72 return false;
73#endif
74}
75
76// If mux is not enabled or channel is already a root channel - return itself
78{
79 if (adcIsMuxedInput(hwChannel)) {
80 return (adc_channel_e)(EFI_ADC_0 + (hwChannel - EFI_ADC_16));
81 }
82
83 return hwChannel;
84}
85
87 if (pin == Gpio::Unassigned)
88 return EFI_ADC_NONE;
89
90 for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
91 if (adcChannels[idx].pin == pin) {
92 return adcChannels[idx].ch;
93 }
94 }
95
96 criticalError("getAdcChannel %d", pin);
97 return EFI_ADC_ERROR;
98}
99
100// Get ADC internal input index for given hwChannel
101int getAdcInternalChannel(ADC_TypeDef *adc, adc_channel_e hwChannel)
102{
103 uint8_t mask = 0;
104
105#if STM32_ADC_USE_ADC1
106 if (adc == ADC1) {
107 mask = BIT(0);
108 }
109#endif
110#if STM32_ADC_USE_ADC2
111 if (adc == ADC2) {
112 mask = BIT(1);
113 }
114#endif
115#if STM32_ADC_USE_ADC3
116 if (adc == ADC3) {
117 mask = BIT(2);
118 }
119#endif
120
121 if (mask == 0) {
122 // Unknown ADC instance
123 return -1;
124 }
125
126 int hwIndex = 0;
127 for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
128 if (adcChannels[idx].ch == hwChannel) {
129 return hwIndex;
130 }
131 if (adcChannels[idx].adc & mask) {
132 hwIndex++;
133 }
134 }
135
136 // Channel is not supported by this ADC
137 return -1;
138}
139
140adc_channel_e getHwChannelForAdcInput(ADC_TypeDef *adc, size_t hwIndex)
141{
142 uint8_t mask = 0;
143
144#if STM32_ADC_USE_ADC1
145 if (adc == ADC1) {
146 mask = BIT(0);
147 }
148#endif
149#if STM32_ADC_USE_ADC2
150 if (adc == ADC2) {
151 mask = BIT(1);
152 }
153#endif
154#if STM32_ADC_USE_ADC3
155 if (adc == ADC3) {
156 mask = BIT(2);
157 }
158#endif
159
160 if (mask == 0) {
161 // Unknown ADC instance
162 return EFI_ADC_ERROR;
163 }
164
165 size_t tmpIndex = 0;
166 for (size_t idx = 0; idx < efi::size(adcChannels); idx++) {
167 if (adcChannels[idx].adc & mask) {
168 if (hwIndex == tmpIndex) {
169 return adcChannels[idx].ch;
170 }
171 tmpIndex++;
172 }
173 }
174
175 // Channel is not supported by this ADC
176 return EFI_ADC_ERROR;
177
178}
179
180// deprecated - inline?
181ioportid_t getAdcChannelPort(const char *msg, adc_channel_e hwChannel) {
182 brain_pin_e brainPin = getAdcChannelBrainPin(msg, hwChannel);
183 return getHwPort(msg, brainPin);
184}
185
186// deprecated - inline?
188 brain_pin_e brainPin = getAdcChannelBrainPin("get_pin", hwChannel);
189 return getHwPin("get_pin", brainPin);
190}
191
192#endif /* HAL_USE_ADC */
@ Unassigned
@ Invalid
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
GPIO_TypeDef * ioportid_t
Port Identifier.
UNUSED(samplingTimeSeconds)
brain_pin_e getAdcChannelBrainPin(const char *msg, adc_channel_e hwChannel)
Definition stm32_adc.cpp:46
int getAdcInternalChannel(ADC_TypeDef *adc, adc_channel_e hwChannel)
int getAdcChannelPin(adc_channel_e hwChannel)
brain_pin_e pin
Definition stm32_adc.cpp:15
bool adcIsMuxedInput(adc_channel_e hwChannel)
Definition stm32_adc.cpp:67
static const struct @48 adcChannels[]
uint8_t adc
Definition stm32_adc.cpp:17
adc_channel_e getHwChannelForAdcInput(ADC_TypeDef *adc, size_t hwIndex)
adc_channel_e getAdcChannel(brain_pin_e pin)
Definition stm32_adc.cpp:86
adc_channel_e ch
Definition stm32_adc.cpp:16
adc_channel_e adcMuxedGetParent(adc_channel_e hwChannel)
Definition stm32_adc.cpp:77
ioportid_t getAdcChannelPort(const char *msg, adc_channel_e hwChannel)