Merge pull request #11297 from SteveCEvans/baro_state
[betaflight.git] / src / main / drivers / adc_stm32f10x.c
blobff3b5341e3a4fa9b362b0af2fe9a26db155b63ff
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #ifdef USE_ADC
29 #include "build/build_config.h"
31 #include "drivers/sensor.h"
32 #include "adc.h"
33 #include "adc_impl.h"
34 #include "drivers/io.h"
35 #include "rcc.h"
36 #include "dma.h"
38 #include "pg/adc.h"
41 const adcDevice_t adcHardware[] = {
42 { .ADCx = ADC1, .rccADC = RCC_APB2(ADC1), .dmaResource = (dmaResource_t *)DMA1_Channel1 }
45 const adcTagMap_t adcTagMap[] = {
46 { DEFIO_TAG_E__PA0, ADC_Channel_0 }, // ADC12
47 { DEFIO_TAG_E__PA1, ADC_Channel_1 }, // ADC12
48 { DEFIO_TAG_E__PA2, ADC_Channel_2 }, // ADC12
49 { DEFIO_TAG_E__PA3, ADC_Channel_3 }, // ADC12
50 { DEFIO_TAG_E__PA4, ADC_Channel_4 }, // ADC12
51 { DEFIO_TAG_E__PA5, ADC_Channel_5 }, // ADC12
52 { DEFIO_TAG_E__PA6, ADC_Channel_6 }, // ADC12
53 { DEFIO_TAG_E__PA7, ADC_Channel_7 }, // ADC12
54 { DEFIO_TAG_E__PB0, ADC_Channel_8 }, // ADC12
55 { DEFIO_TAG_E__PB1, ADC_Channel_9 }, // ADC12
58 // Driver for STM32F103CB onboard ADC
60 // Naze32
61 // Battery Voltage (VBAT) is connected to PA4 (ADC1_IN4) with 10k:1k divider
62 // RSSI ADC uses CH2 (PA1, ADC1_IN1)
63 // Current ADC uses CH8 (PB1, ADC1_IN9)
65 // NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board
68 void adcInit(const adcConfig_t *config)
70 uint8_t configuredAdcChannels = 0;
72 memset(&adcOperatingConfig, 0, sizeof(adcOperatingConfig));
74 if (config->vbat.enabled) {
75 adcOperatingConfig[ADC_BATTERY].tag = config->vbat.ioTag;
78 if (config->rssi.enabled) {
79 adcOperatingConfig[ADC_RSSI].tag = config->rssi.ioTag; //RSSI_ADC_CHANNEL;
82 if (config->external1.enabled) {
83 adcOperatingConfig[ADC_EXTERNAL1].tag = config->external1.ioTag; //EXTERNAL1_ADC_CHANNEL;
86 if (config->current.enabled) {
87 adcOperatingConfig[ADC_CURRENT].tag = config->current.ioTag; //CURRENT_METER_ADC_CHANNEL;
90 ADCDevice device = adcDeviceByInstance(ADC_INSTANCE);
91 if (device == ADCINVALID) {
92 return;
95 const adcDevice_t adc = adcHardware[device];
97 if (!dmaAllocate(dmaGetIdentifier(adc.dmaResource), OWNER_ADC, 0)) {
98 return;
101 bool adcActive = false;
102 for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
103 if (!adcOperatingConfig[i].tag)
104 continue;
106 adcActive = true;
107 IOInit(IOGetByTag(adcOperatingConfig[i].tag), OWNER_ADC_BATT + i, 0);
108 IOConfigGPIO(IOGetByTag(adcOperatingConfig[i].tag), IO_CONFIG(GPIO_Mode_AIN, 0));
109 adcOperatingConfig[i].adcChannel = adcChannelByTag(adcOperatingConfig[i].tag);
110 adcOperatingConfig[i].dmaIndex = configuredAdcChannels++;
111 adcOperatingConfig[i].sampleTime = ADC_SampleTime_239Cycles5;
112 adcOperatingConfig[i].enabled = true;
115 if (!adcActive) {
116 return;
119 RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI)
120 RCC_ClockCmd(adc.rccADC, ENABLE);
122 dmaEnable(dmaGetIdentifier(adc.dmaResource));
124 xDMA_DeInit(adc.dmaResource);
125 DMA_InitTypeDef DMA_InitStructure;
126 DMA_StructInit(&DMA_InitStructure);
127 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&adc.ADCx->DR;
128 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)adcValues;
129 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
130 DMA_InitStructure.DMA_BufferSize = configuredAdcChannels;
131 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
132 DMA_InitStructure.DMA_MemoryInc = configuredAdcChannels > 1 ? DMA_MemoryInc_Enable : DMA_MemoryInc_Disable;
133 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
134 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
135 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
136 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
137 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
138 xDMA_Init(adc.dmaResource, &DMA_InitStructure);
139 xDMA_Cmd(adc.dmaResource, ENABLE);
141 ADC_InitTypeDef ADC_InitStructure;
142 ADC_StructInit(&ADC_InitStructure);
143 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
144 ADC_InitStructure.ADC_ScanConvMode = configuredAdcChannels > 1 ? ENABLE : DISABLE;
145 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
146 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
147 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
148 ADC_InitStructure.ADC_NbrOfChannel = configuredAdcChannels;
149 ADC_Init(adc.ADCx, &ADC_InitStructure);
151 uint8_t rank = 1;
152 for (int i = 0; i < ADC_CHANNEL_COUNT; i++) {
153 if (!adcOperatingConfig[i].enabled) {
154 continue;
156 ADC_RegularChannelConfig(adc.ADCx, adcOperatingConfig[i].adcChannel, rank++, adcOperatingConfig[i].sampleTime);
159 ADC_DMACmd(adc.ADCx, ENABLE);
160 ADC_Cmd(adc.ADCx, ENABLE);
162 ADC_ResetCalibration(adc.ADCx);
163 while (ADC_GetResetCalibrationStatus(adc.ADCx));
164 ADC_StartCalibration(adc.ADCx);
165 while (ADC_GetCalibrationStatus(adc.ADCx));
167 ADC_SoftwareStartConvCmd(adc.ADCx, ENABLE);
170 void adcGetChannelValues(void)
172 // Nothing to do
174 #endif