Fix doc path
[opentx.git] / radio / src / targets / common / arm / stm32 / adc_driver.cpp
bloba96cfe8e39e5bd21e32dcdc2d38e22ffe8191a23
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "opentx.h"
23 #if defined(SIMU)
24 // not needed
25 #elif defined(PCBX10)
26 const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, 1,-1, 1, 1,1};
27 #elif defined(PCBX9E)
28 #if defined(HORUS_STICKS)
29 const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,-1,-1,1, -1,1,-1,-1, -1};
30 #else
31 const int8_t ana_direction[NUM_ANALOGS] = {1,1,-1,-1, -1,-1,-1,1, -1,1,-1,-1, -1};
32 #endif
33 const uint8_t ana_mapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/,
34 10 /*POT1*/, 4 /*POT2*/, 5 /*POT3*/, 6 /*POT4*/,
35 11 /*SLIDER1*/, 12 /*SLIDER2*/, 7 /*SLIDER3*/, 8 /*SLIDER4*/,
36 9 /*TX_VOLTAGE*/ };
37 #elif defined(PCBX9DP)
38 const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1};
39 #elif defined(PCBX7)
40 const int8_t ana_direction[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1};
41 #elif defined(PCBXLITE)
42 const int8_t ana_direction[NUM_ANALOGS] = {1,-1,-1,1, -1,1, 1};
43 #elif defined(REV4a)
44 const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,-1,0, 1,1, 1};
45 #else
46 const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,1,0, 1,1, 1};
47 #endif
49 #if NUM_PWMSTICKS > 0
50 #define FIRST_ANALOG_ADC (STICKS_PWM_ENABLED() ? NUM_PWMSTICKS : 0)
51 #define NUM_ANALOGS_ADC (STICKS_PWM_ENABLED() ? (NUM_ANALOGS - NUM_PWMSTICKS) : NUM_ANALOGS)
52 #elif defined(PCBX9E)
53 #define FIRST_ANALOG_ADC 0
54 #define NUM_ANALOGS_ADC 10
55 #define NUM_ANALOGS_ADC_EXT (NUM_ANALOGS - 10)
56 #else
57 #define FIRST_ANALOG_ADC 0
58 #define NUM_ANALOGS_ADC NUM_ANALOGS
59 #endif
61 uint16_t adcValues[NUM_ANALOGS] __DMA;
63 void adcInit()
65 GPIO_InitTypeDef GPIO_InitStructure;
66 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
67 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
68 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
69 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
71 #if defined(ADC_GPIOA_PINS)
72 GPIO_InitStructure.GPIO_Pin = ADC_GPIOA_PINS;
73 GPIO_Init(GPIOA, &GPIO_InitStructure);
74 #endif
76 #if defined(ADC_GPIOB_PINS)
77 GPIO_InitStructure.GPIO_Pin = ADC_GPIOB_PINS;
78 GPIO_Init(GPIOB, &GPIO_InitStructure);
79 #endif
81 #if defined(ADC_GPIOC_PINS)
82 GPIO_InitStructure.GPIO_Pin = ADC_GPIOC_PINS;
83 GPIO_Init(GPIOC, &GPIO_InitStructure);
84 #endif
86 #if defined(ADC_GPIOF_PINS)
87 GPIO_InitStructure.GPIO_Pin = ADC_GPIOF_PINS;
88 GPIO_Init(GPIOF, &GPIO_InitStructure);
89 #endif
91 ADC_MAIN->CR1 = ADC_CR1_SCAN;
92 ADC_MAIN->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
93 ADC_MAIN->SQR1 = (NUM_ANALOGS_ADC-1) << 20; // bits 23:20 = number of conversions
95 #if defined(PCBX10)
96 if (STICKS_PWM_ENABLED()) {
97 ADC_MAIN->SQR2 = (ADC_CHANNEL_EXT1<<0) + (ADC_CHANNEL_EXT2<<5); // conversions 7 and more
98 ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_POT3<<10) + (ADC_CHANNEL_SLIDER1<<15) + (ADC_CHANNEL_SLIDER2<<20) + (ADC_CHANNEL_BATT<<25); // conversions 1 to 6
100 else {
101 ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15) + (ADC_CHANNEL_EXT1<<20) + (ADC_CHANNEL_EXT2<<25); // conversions 7 and more
102 ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
104 #elif defined(PCBX9E)
105 ADC_MAIN->SQR2 = (ADC_CHANNEL_POT4<<0) + (ADC_CHANNEL_SLIDER3<<5) + (ADC_CHANNEL_SLIDER4<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
106 ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT2<<20) + (ADC_CHANNEL_POT3<<25); // conversions 1 to 6
107 #elif defined(PCBXLITE)
108 if (STICKS_PWM_ENABLED()) {
109 ADC_MAIN->SQR2 = 0;
110 ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_BATT<<10);
112 else {
113 ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0);
114 ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
116 #elif defined(PCBX7)
117 // TODO why do we invert POT1 and POT2 here?
118 ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0); // conversions 7 and more
119 ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<25) + (ADC_CHANNEL_POT2<<20); // conversions 1 to 6
120 #else
121 ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
122 ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
123 #endif
125 ADC_MAIN->SMPR1 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24);
126 ADC_MAIN->SMPR2 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24) + (ADC_SAMPTIME<<27);
128 ADC->CCR = 0;
130 ADC_DMA_Stream->CR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
131 ADC_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_MAIN->DR);
132 ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[FIRST_ANALOG_ADC]);
133 ADC_DMA_Stream->NDTR = NUM_ANALOGS_ADC;
134 ADC_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
136 #if defined(PCBX9E)
137 ADC_EXT->CR1 = ADC_CR1_SCAN;
138 ADC_EXT->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
139 ADC_EXT->SQR1 = (NUM_ANALOGS_ADC_EXT-1) << 20;
140 ADC_EXT->SQR2 = 0;
141 ADC_EXT->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10); // conversions 1 to 3
142 ADC_EXT->SMPR1 = 0;
143 ADC_EXT->SMPR2 = (ADC_EXT_SAMPTIME<<(3*ADC_CHANNEL_POT1)) + (ADC_EXT_SAMPTIME<<(3*ADC_CHANNEL_SLIDER1)) + (ADC_EXT_SAMPTIME<<(3*ADC_CHANNEL_SLIDER2));
145 ADC_EXT_DMA_Stream->CR = DMA_SxCR_PL | DMA_SxCR_CHSEL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
146 ADC_EXT_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_EXT->DR);
147 ADC_EXT_DMA_Stream->M0AR = CONVERT_PTR_UINT(adcValues + NUM_ANALOGS_ADC);
148 ADC_EXT_DMA_Stream->NDTR = NUM_ANALOGS_ADC_EXT;
149 ADC_EXT_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
150 #endif
152 #if NUM_PWMSTICKS > 0
153 if (STICKS_PWM_ENABLED()) {
154 sticksPwmInit();
156 #endif
159 void adcSingleRead()
161 ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
162 ADC_MAIN->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
163 ADC_SET_DMA_FLAGS();
164 ADC_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
165 ADC_MAIN->CR2 |= (uint32_t) ADC_CR2_SWSTART;
167 #if defined(PCBX9E)
168 ADC_EXT_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
169 ADC_EXT->SR &= ~(uint32_t) ( ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR );
170 ADC_EXT_SET_DMA_FLAGS();
171 ADC_EXT_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
172 ADC_EXT->CR2 |= (uint32_t)ADC_CR2_SWSTART;
173 #endif
175 #if defined(PCBX9E)
176 for (unsigned int i=0; i<10000; i++) {
177 if (ADC_TRANSFER_COMPLETE() && ADC_EXT_TRANSFER_COMPLETE()) {
178 break;
181 ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
182 ADC_EXT_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
183 #else
184 for (unsigned int i = 0; i < 10000; i++) {
185 if (ADC_TRANSFER_COMPLETE()) {
186 break;
189 ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
190 #endif
193 void adcRead()
195 uint16_t temp[NUM_ANALOGS] = { 0 };
197 for (int i=0; i<4; i++) {
198 adcSingleRead();
199 for (uint8_t x=FIRST_ANALOG_ADC; x<NUM_ANALOGS; x++) {
200 uint16_t val = adcValues[x];
201 #if defined(JITTER_MEASURE)
202 if (JITTER_MEASURE_ACTIVE()) {
203 rawJitter[x].measure(val);
205 #endif
206 temp[x] += val;
210 for (uint8_t x=FIRST_ANALOG_ADC; x<NUM_ANALOGS; x++) {
211 adcValues[x] = temp[x] >> 2;
214 #if NUM_PWMSTICKS > 0
215 if (STICKS_PWM_ENABLED()) {
216 sticksPwmRead(adcValues);
218 #endif
221 // TODO
222 void adcStop()
226 #if !defined(SIMU)
227 uint16_t getAnalogValue(uint8_t index)
229 if (IS_POT(index) && !IS_POT_SLIDER_AVAILABLE(index)) {
230 // Use fixed analog value for non-existing and/or non-connected pots.
231 // Non-connected analog inputs will slightly follow the adjacent connected analog inputs,
232 // which produces ghost readings on these inputs.
233 return 0;
235 #if defined(PCBX9E)
236 index = ana_mapping[index];
237 #endif
238 if (ana_direction[index] < 0)
239 return 4095 - adcValues[index];
240 else
241 return adcValues[index];
243 #endif // #if !defined(SIMU)