17ff344d3a228ee9310bbf009bfeefaa665692be
[fw/altos] / src / stm / ao_adc_stm.c
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
4  * This program 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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <ao.h>
19 #include <ao_data.h>
20
21 static uint8_t                  ao_adc_ready;
22
23 #define AO_ADC_CR2_VAL          ((0 << STM_ADC_CR2_SWSTART) |           \
24                                  (STM_ADC_CR2_EXTEN_DISABLE << STM_ADC_CR2_EXTEN) | \
25                                  (0 << STM_ADC_CR2_EXTSEL) |            \
26                                  (0 << STM_ADC_CR2_JWSTART) |           \
27                                  (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \
28                                  (0 << STM_ADC_CR2_JEXTSEL) |           \
29                                  (0 << STM_ADC_CR2_ALIGN) |             \
30                                  (0 << STM_ADC_CR2_EOCS) |              \
31                                  (1 << STM_ADC_CR2_DDS) |               \
32                                  (1 << STM_ADC_CR2_DMA) |               \
33                                  (STM_ADC_CR2_DELS_UNTIL_READ << STM_ADC_CR2_DELS) | \
34                                  (0 << STM_ADC_CR2_CONT) |              \
35                                  (1 << STM_ADC_CR2_ADON))
36
37 /*
38  * Callback from DMA ISR
39  *
40  * Mark time in ring, shut down DMA engine
41  */
42 static void ao_adc_done(int index)
43 {
44         (void) index;
45         AO_DATA_PRESENT(AO_DATA_ADC);
46         ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
47         if (ao_data_present == AO_DATA_ALL) {
48 #if HAS_MS5607
49                 ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current;
50 #endif
51 #if HAS_MMA655X
52                 ao_data_ring[ao_data_head].mma655x = ao_mma655x_current;
53 #endif
54 #if HAS_HMC5883
55                 ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current;
56 #endif
57 #if HAS_MPU6000
58                 ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current;
59 #endif
60                 ao_data_ring[ao_data_head].tick = ao_tick_count;
61                 ao_data_head = ao_data_ring_next(ao_data_head);
62                 ao_wakeup((void *) &ao_data_head);
63         }
64         ao_adc_ready = 1;
65 }
66
67 /*
68  * Start the ADC sequence using the DMA engine
69  */
70 void
71 ao_adc_poll(void)
72 {
73         if (!ao_adc_ready)
74                 return;
75         ao_adc_ready = 0;
76         stm_adc.sr = 0;
77         ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1),
78                             &stm_adc.dr,
79                             (void *) (&ao_data_ring[ao_data_head].adc),
80                             AO_NUM_ADC,
81                             (0 << STM_DMA_CCR_MEM2MEM) |
82                             (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
83                             (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) |
84                             (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) |
85                             (1 << STM_DMA_CCR_MINC) |
86                             (0 << STM_DMA_CCR_PINC) |
87                             (0 << STM_DMA_CCR_CIRC) |
88                             (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
89         ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done);
90         ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
91
92         stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART);
93 }
94
95 /*
96  * Fetch a copy of the most recent ADC data
97  */
98 void
99 ao_adc_get(__xdata struct ao_adc *packet)
100 {
101 #if HAS_FLIGHT
102         uint8_t i = ao_data_ring_prev(ao_sample_data);
103 #else
104         uint8_t i = ao_data_ring_prev(ao_data_head);
105 #endif
106         memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc));
107 }
108
109 #ifdef AO_ADC_SQ1_NAME
110 static const char *ao_adc_name[AO_NUM_ADC] = {
111         AO_ADC_SQ1_NAME,
112 #ifdef AO_ADC_SQ2_NAME
113         AO_ADC_SQ2_NAME,
114 #endif
115 #ifdef AO_ADC_SQ3_NAME
116         AO_ADC_SQ3_NAME,
117 #endif
118 #ifdef AO_ADC_SQ4_NAME
119         AO_ADC_SQ4_NAME,
120 #endif
121 #ifdef AO_ADC_SQ5_NAME
122         AO_ADC_SQ5_NAME,
123 #endif
124 #ifdef AO_ADC_SQ6_NAME
125         AO_ADC_SQ6_NAME,
126 #endif
127 #ifdef AO_ADC_SQ7_NAME
128         AO_ADC_SQ7_NAME,
129 #endif
130 #ifdef AO_ADC_SQ8_NAME
131         AO_ADC_SQ8_NAME,
132 #endif
133 #ifdef AO_ADC_SQ9_NAME
134         AO_ADC_SQ9_NAME,
135 #endif
136 #ifdef AO_ADC_SQ10_NAME
137         AO_ADC_SQ10_NAME,
138 #endif
139 #ifdef AO_ADC_SQ11_NAME
140         AO_ADC_SQ11_NAME,
141 #endif
142 #ifdef AO_ADC_SQ12_NAME
143         AO_ADC_SQ12_NAME,
144 #endif
145 #ifdef AO_ADC_SQ13_NAME
146         AO_ADC_SQ13_NAME,
147 #endif
148 #ifdef AO_ADC_SQ14_NAME
149         AO_ADC_SQ14_NAME,
150 #endif
151 #ifdef AO_ADC_SQ15_NAME
152         AO_ADC_SQ15_NAME,
153 #endif
154 #ifdef AO_ADC_SQ16_NAME
155         AO_ADC_SQ16_NAME,
156 #endif
157 #ifdef AO_ADC_SQ17_NAME
158         AO_ADC_SQ17_NAME,
159 #endif
160 #ifdef AO_ADC_SQ18_NAME
161         AO_ADC_SQ18_NAME,
162 #endif
163 #ifdef AO_ADC_SQ19_NAME
164         AO_ADC_SQ19_NAME,
165 #endif
166 #ifdef AO_ADC_SQ20_NAME
167         AO_ADC_SQ20_NAME,
168 #endif
169 #ifdef AO_ADC_SQ21_NAME
170         #error "too many ADC names"
171 #endif
172 };
173 #endif
174
175 static void
176 ao_adc_dump(void) __reentrant
177 {
178         struct ao_data  packet;
179 #ifndef AO_ADC_DUMP
180         uint8_t i;
181         int16_t *d;
182 #endif
183
184         ao_data_get(&packet);
185 #ifdef AO_ADC_DUMP
186         AO_ADC_DUMP(&packet);
187 #else
188         printf("tick: %5u",  packet.tick);
189         d = (int16_t *) (&packet.adc);
190         for (i = 0; i < AO_NUM_ADC; i++) {
191 #ifdef AO_ADC_SQ1_NAME
192                 if (ao_adc_name[i])
193                         printf ("\t%s: %5d\n", ao_adc_name[i], d[i]);
194                 else            
195 #endif
196                         printf (" %2d: %5d", i, d[i]);
197         }
198         printf("\n");
199 #endif
200 }
201
202 __code struct ao_cmds ao_adc_cmds[] = {
203         { ao_adc_dump,  "a\0Display current ADC values" },
204         { 0, NULL },
205 };
206
207 void
208 ao_adc_init(void)
209 {
210 #ifdef AO_ADC_PIN0_PORT
211         stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR;
212 #endif
213
214 #ifdef AO_ADC_PIN0_PORT
215         stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG);
216 #endif
217 #ifdef AO_ADC_PIN1_PORT
218         stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG);
219 #endif
220 #ifdef AO_ADC_PIN2_PORT
221         stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG);
222 #endif
223 #ifdef AO_ADC_PIN3_PORT
224         stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG);
225 #endif
226 #ifdef AO_ADC_PIN4_PORT
227         stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG);
228 #endif
229 #ifdef AO_ADC_PIN5_PORT
230         stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG);
231 #endif
232 #ifdef AO_ADC_PIN6_PORT
233         stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG);
234 #endif
235 #ifdef AO_ADC_PIN7_PORT
236         stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG);
237 #endif
238 #ifdef AO_ADC_PIN8_PORT
239         stm_moder_set(AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG);
240 #endif
241 #ifdef AO_ADC_PIN9_PORT
242         stm_moder_set(AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG);
243 #endif
244 #ifdef AO_ADC_PIN10_PORT
245         stm_moder_set(AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG);
246 #endif
247 #ifdef AO_ADC_PIN11_PORT
248         stm_moder_set(AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG);
249 #endif
250 #ifdef AO_ADC_PIN12_PORT
251         stm_moder_set(AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG);
252 #endif
253 #ifdef AO_ADC_PIN13_PORT
254         stm_moder_set(AO_ADC_PIN13_PORT, AO_ADC_PIN13_PIN, STM_MODER_ANALOG);
255 #endif
256 #ifdef AO_ADC_PIN14_PORT
257         stm_moder_set(AO_ADC_PIN14_PORT, AO_ADC_PIN14_PIN, STM_MODER_ANALOG);
258 #endif
259 #ifdef AO_ADC_PIN15_PORT
260         stm_moder_set(AO_ADC_PIN15_PORT, AO_ADC_PIN15_PIN, STM_MODER_ANALOG);
261 #endif
262 #ifdef AO_ADC_PIN16_PORT
263         stm_moder_set(AO_ADC_PIN16_PORT, AO_ADC_PIN16_PIN, STM_MODER_ANALOG);
264 #endif
265 #ifdef AO_ADC_PIN17_PORT
266         stm_moder_set(AO_ADC_PIN17_PORT, AO_ADC_PIN17_PIN, STM_MODER_ANALOG);
267 #endif
268 #ifdef AO_ADC_PIN18_PORT
269         stm_moder_set(AO_ADC_PIN18_PORT, AO_ADC_PIN18_PIN, STM_MODER_ANALOG);
270 #endif
271 #ifdef AO_ADC_PIN19_PORT
272         stm_moder_set(AO_ADC_PIN19_PORT, AO_ADC_PIN19_PIN, STM_MODER_ANALOG);
273 #endif
274 #ifdef AO_ADC_PIN20_PORT
275         stm_moder_set(AO_ADC_PIN20_PORT, AO_ADC_PIN20_PIN, STM_MODER_ANALOG);
276 #endif
277 #ifdef AO_ADC_PIN21_PORT
278         stm_moder_set(AO_ADC_PIN21_PORT, AO_ADC_PIN21_PIN, STM_MODER_ANALOG);
279 #endif
280 #ifdef AO_ADC_PIN22_PORT
281         stm_moder_set(AO_ADC_PIN22_PORT, AO_ADC_PIN22_PIN, STM_MODER_ANALOG);
282 #endif
283 #ifdef AO_ADC_PIN23_PORT
284         stm_moder_set(AO_ADC_PIN23_PORT, AO_ADC_PIN23_PIN, STM_MODER_ANALOG);
285 #endif
286 #ifdef AO_ADC_PIN24_PORT
287         #error "Too many ADC ports"
288 #endif
289
290         stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN);
291
292         /* Turn off ADC during configuration */
293         stm_adc.cr2 = 0;
294
295         stm_adc.cr1 = ((0 << STM_ADC_CR1_OVRIE ) |
296                        (STM_ADC_CR1_RES_12 << STM_ADC_CR1_RES ) |
297                        (0 << STM_ADC_CR1_AWDEN ) |
298                        (0 << STM_ADC_CR1_JAWDEN ) |
299                        (0 << STM_ADC_CR1_PDI ) |
300                        (0 << STM_ADC_CR1_PDD ) |
301                        (0 << STM_ADC_CR1_DISCNUM ) |
302                        (0 << STM_ADC_CR1_JDISCEN ) |
303                        (0 << STM_ADC_CR1_DISCEN ) |
304                        (0 << STM_ADC_CR1_JAUTO ) |
305                        (0 << STM_ADC_CR1_AWDSGL ) |
306                        (1 << STM_ADC_CR1_SCAN ) |
307                        (0 << STM_ADC_CR1_JEOCIE ) |
308                        (0 << STM_ADC_CR1_AWDIE ) |
309                        (0 << STM_ADC_CR1_EOCIE ) |
310                        (0 << STM_ADC_CR1_AWDCH ));
311
312         /* 384 cycle sample time for everyone */
313         stm_adc.smpr1 = 0x3ffff;
314         stm_adc.smpr2 = 0x3fffffff;
315         stm_adc.smpr3 = 0x3fffffff;
316
317         stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20);
318         stm_adc.sqr2 = 0;
319         stm_adc.sqr3 = 0;
320         stm_adc.sqr4 = 0;
321         stm_adc.sqr5 = 0;
322 #if AO_NUM_ADC > 0
323         stm_adc.sqr5 |= (AO_ADC_SQ1 << 0);
324 #endif
325 #if AO_NUM_ADC > 1
326         stm_adc.sqr5 |= (AO_ADC_SQ2 << 5);
327 #endif
328 #if AO_NUM_ADC > 2
329         stm_adc.sqr5 |= (AO_ADC_SQ3 << 10);
330 #endif
331 #if AO_NUM_ADC > 3
332         stm_adc.sqr5 |= (AO_ADC_SQ4 << 15);
333 #endif
334 #if AO_NUM_ADC > 4
335         stm_adc.sqr5 |= (AO_ADC_SQ5 << 20);
336 #endif
337 #if AO_NUM_ADC > 5
338         stm_adc.sqr5 |= (AO_ADC_SQ6 << 25);
339 #endif
340 #if AO_NUM_ADC > 6
341         stm_adc.sqr4 |= (AO_ADC_SQ7 << 0);
342 #endif
343 #if AO_NUM_ADC > 7
344         stm_adc.sqr4 |= (AO_ADC_SQ8 << 5);
345 #endif
346 #if AO_NUM_ADC > 8
347         stm_adc.sqr4 |= (AO_ADC_SQ9 << 10);
348 #endif
349 #if AO_NUM_ADC > 9
350         stm_adc.sqr4 |= (AO_ADC_SQ10 << 15);
351 #endif
352 #if AO_NUM_ADC > 10
353         stm_adc.sqr4 |= (AO_ADC_SQ11 << 20);
354 #endif
355 #if AO_NUM_ADC > 11
356         stm_adc.sqr4 |= (AO_ADC_SQ12 << 25);
357 #endif
358 #if AO_NUM_ADC > 12
359         stm_adc.sqr3 |= (AO_ADC_SQ13 << 0);
360 #endif
361 #if AO_NUM_ADC > 13
362         stm_adc.sqr3 |= (AO_ADC_SQ14 << 5);
363 #endif
364 #if AO_NUM_ADC > 14
365         stm_adc.sqr3 |= (AO_ADC_SQ15 << 10);
366 #endif
367 #if AO_NUM_ADC > 15
368         stm_adc.sqr3 |= (AO_ADC_SQ16 << 15);
369 #endif
370 #if AO_NUM_ADC > 16
371         stm_adc.sqr3 |= (AO_ADC_SQ17 << 20);
372 #endif
373 #if AO_NUM_ADC > 17
374         stm_adc.sqr3 |= (AO_ADC_SQ18 << 25);
375 #endif
376 #if AO_NUM_ADC > 18
377 #error "need to finish stm_adc.sqr settings"
378 #endif
379         
380         /* Turn ADC on */
381         stm_adc.cr2 = AO_ADC_CR2_VAL;
382
383         /* Wait for ADC to be ready */
384         while (!(stm_adc.sr & (1 << STM_ADC_SR_ADONS)))
385                 ;
386
387 #ifndef HAS_ADC_TEMP
388 #error Please define HAS_ADC_TEMP
389 #endif
390 #if HAS_ADC_TEMP
391         stm_adc.ccr = ((1 << STM_ADC_CCR_TSVREFE));
392 #else
393         stm_adc.ccr = 0;
394 #endif
395         /* Clear any stale status bits */
396         stm_adc.sr = 0;
397
398         ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1));
399
400         ao_cmd_register(&ao_adc_cmds[0]);
401
402         ao_adc_ready = 1;
403 }