2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
24 #include "build/build_config.h"
25 #include "build/debug.h"
27 #include "drivers/time.h"
29 #include "drivers/io.h"
30 #include "drivers/adc.h"
31 #include "drivers/adc_impl.h"
33 #include "common/utils.h"
36 #define ADC_INSTANCE ADC1
39 #ifndef ADC_CHANNEL_1_INSTANCE
40 #define ADC_CHANNEL_1_INSTANCE ADC_INSTANCE
42 #ifndef ADC_CHANNEL_2_INSTANCE
43 #define ADC_CHANNEL_2_INSTANCE ADC_INSTANCE
45 #ifndef ADC_CHANNEL_3_INSTANCE
46 #define ADC_CHANNEL_3_INSTANCE ADC_INSTANCE
48 #ifndef ADC_CHANNEL_4_INSTANCE
49 #define ADC_CHANNEL_4_INSTANCE ADC_INSTANCE
54 #if defined(USE_ADC_AVERAGING)
55 static uint8_t activeChannelCount
[ADCDEV_COUNT
] = {0};
58 static int adcFunctionMap
[ADC_FUNCTION_COUNT
];
59 adc_config_t adcConfig
[ADC_CHN_COUNT
]; // index 0 is dummy for ADC_CHN_NONE
60 volatile uint16_t adcValues
[ADCDEV_COUNT
][ADC_CHN_COUNT
* ADC_AVERAGE_N_SAMPLES
];
62 uint8_t adcChannelByTag(ioTag_t ioTag
)
64 for (uint8_t i
= 0; i
< ARRAYLEN(adcTagMap
); i
++) {
65 if (ioTag
== adcTagMap
[i
].tag
)
66 return adcTagMap
[i
].channel
;
71 int adcGetFunctionChannelAllocation(uint8_t function
)
73 return adcFunctionMap
[function
];
76 bool adcIsFunctionAssigned(uint8_t function
)
78 // Map function to ADC channel
79 return (adcFunctionMap
[function
] != ADC_CHN_NONE
);
82 uint16_t adcGetChannel(uint8_t function
)
84 int channel
= adcFunctionMap
[function
];
85 if (channel
== ADC_CHN_NONE
)
88 if (adcConfig
[channel
].adcDevice
!= ADCINVALID
&& adcConfig
[channel
].enabled
) {
89 #if !defined(USE_ADC_AVERAGING)
90 return adcValues
[adcConfig
[channel
].adcDevice
][adcConfig
[channel
].dmaIndex
];
93 for (int i
= 0; i
< ADC_AVERAGE_N_SAMPLES
; i
++) {
94 acc
+= adcValues
[adcConfig
[channel
].adcDevice
][adcConfig
[channel
].dmaIndex
+ i
* activeChannelCount
[adcConfig
[channel
].adcDevice
]];
96 return acc
/ ADC_AVERAGE_N_SAMPLES
;
103 #if defined(ADC_CHANNEL_1_PIN) || defined(ADC_CHANNEL_2_PIN) || defined(ADC_CHANNEL_3_PIN) || defined(ADC_CHANNEL_4_PIN)
104 static bool isChannelInUse(int channel
)
106 for (int i
= 0; i
< ADC_FUNCTION_COUNT
; i
++) {
107 if (adcFunctionMap
[i
] == channel
)
115 #if !defined(ADC_CHANNEL_1_PIN) || !defined(ADC_CHANNEL_2_PIN) || !defined(ADC_CHANNEL_3_PIN) || !defined(ADC_CHANNEL_4_PIN)
116 static void disableChannelMapping(int channel
)
118 for (int i
= 0; i
< ADC_FUNCTION_COUNT
; i
++) {
119 if (adcFunctionMap
[i
] == channel
) {
120 adcFunctionMap
[i
] = ADC_CHN_NONE
;
126 void adcInit(drv_adc_config_t
*init
)
128 memset(&adcConfig
, 0, sizeof(adcConfig
));
130 // Remember ADC function to ADC channel mapping
131 for (int i
= 0; i
< ADC_FUNCTION_COUNT
; i
++) {
132 if (init
->adcFunctionChannel
[i
] >= ADC_CHN_1
&& init
->adcFunctionChannel
[i
] <= ADC_CHN_MAX
) {
133 adcFunctionMap
[i
] = init
->adcFunctionChannel
[i
];
136 adcFunctionMap
[i
] = ADC_CHN_NONE
;
140 #ifdef ADC_CHANNEL_1_PIN
141 if (isChannelInUse(ADC_CHN_1
)) {
142 adcConfig
[ADC_CHN_1
].adcDevice
= adcDeviceByInstance(ADC_CHANNEL_1_INSTANCE
);
143 if (adcConfig
[ADC_CHN_1
].adcDevice
!= ADCINVALID
) {
144 adcConfig
[ADC_CHN_1
].tag
= IO_TAG(ADC_CHANNEL_1_PIN
);
145 #if defined(USE_ADC_AVERAGING)
146 activeChannelCount
[adcConfig
[ADC_CHN_1
].adcDevice
] += 1;
151 disableChannelMapping(ADC_CHN_1
);
154 #ifdef ADC_CHANNEL_2_PIN
155 if (isChannelInUse(ADC_CHN_2
)) {
156 adcConfig
[ADC_CHN_2
].adcDevice
= adcDeviceByInstance(ADC_CHANNEL_2_INSTANCE
);
157 if (adcConfig
[ADC_CHN_2
].adcDevice
!= ADCINVALID
) {
158 adcConfig
[ADC_CHN_2
].tag
= IO_TAG(ADC_CHANNEL_2_PIN
);
159 #if defined(USE_ADC_AVERAGING)
160 activeChannelCount
[adcConfig
[ADC_CHN_2
].adcDevice
] += 1;
165 disableChannelMapping(ADC_CHN_2
);
168 #ifdef ADC_CHANNEL_3_PIN
169 if (isChannelInUse(ADC_CHN_3
)) {
170 adcConfig
[ADC_CHN_3
].adcDevice
= adcDeviceByInstance(ADC_CHANNEL_3_INSTANCE
);
171 if (adcConfig
[ADC_CHN_3
].adcDevice
!= ADCINVALID
) {
172 adcConfig
[ADC_CHN_3
].tag
= IO_TAG(ADC_CHANNEL_3_PIN
);
173 #if defined(USE_ADC_AVERAGING)
174 activeChannelCount
[adcConfig
[ADC_CHN_3
].adcDevice
] += 1;
179 disableChannelMapping(ADC_CHN_3
);
182 #ifdef ADC_CHANNEL_4_PIN
183 if (isChannelInUse(ADC_CHN_4
)) {
184 adcConfig
[ADC_CHN_4
].adcDevice
= adcDeviceByInstance(ADC_CHANNEL_4_INSTANCE
);
185 if (adcConfig
[ADC_CHN_4
].adcDevice
!= ADCINVALID
) {
186 adcConfig
[ADC_CHN_4
].tag
= IO_TAG(ADC_CHANNEL_4_PIN
);
187 #if defined(USE_ADC_AVERAGING)
188 activeChannelCount
[adcConfig
[ADC_CHN_4
].adcDevice
] += 1;
193 disableChannelMapping(ADC_CHN_4
);
197 adcHardwareInit(init
);
202 uint16_t adcGetChannel(uint8_t channel
)