Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
adc_arch.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2013 AggieAir, A Remote Sensing Unmanned Aerial System for Scientific Applications
3 * Utah State University, http://aggieair.usu.edu/
4 *
5 * Michal Podhradsky (michal.podhradsky@aggiemail.usu.edu)
6 * Calvin Coopmans (c.r.coopmans@ieee.org)
7 *
8 * Copyright (C) 2015 Gautier Hattenberger, Alexandre Bustico
9 *
10 * This file is part of paparazzi.
11 *
12 * paparazzi is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * paparazzi is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with paparazzi; see the file COPYING. If not, write to
24 * the Free Software Foundation, 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
26 */
53#include "mcu_periph/adc.h"
54#include "mcu_periph/gpio.h"
55#include "hal.h"
56#include "std.h"
57#include "mcu_periph/ram_arch.h"
58
59
60// Macros to automatically enable the correct ADC
61// FIXME we can't use NB_ADC1_CHANNELS it is not a macro
62//#if NB_ADC1_CHANNELS != 0
63#ifndef USE_AD1
64#define USE_AD1 1
65#endif
67
68
69/* Set the default sample rate */
70#if !defined(ADC_SAMPLE_RATE)
71#if defined(STM32H7XX)
72#define ADC_SAMPLE_RATE ADC_SMPR_SMP_384P5
73#elif defined(STM32F3XX)
74#define ADC_SAMPLE_RATE ADC_SMPR_SMP_601P5
75#else
76#define ADC_SAMPLE_RATE ADC_SAMPLE_480
77#endif
78#endif
79
80// Create channel map
82#ifdef AD1_1_CHANNEL
84#endif
85#ifdef AD1_2_CHANNEL
87#endif
88#ifdef AD1_3_CHANNEL
90#endif
91#ifdef AD1_4_CHANNEL
93#endif
94#ifdef AD1_5_CHANNEL
96#endif
97#ifdef AD1_6_CHANNEL
99#endif
100#ifdef AD1_7_CHANNEL
102#endif
103#ifdef AD1_8_CHANNEL
105#endif
106#ifdef AD1_9_CHANNEL
108#endif
109#ifdef AD1_10_CHANNEL
111#endif
112#ifdef AD1_11_CHANNEL
114#endif
115#ifdef AD1_12_CHANNEL
117#endif
118#ifdef AD1_13_CHANNEL
120#endif
121#ifdef AD1_14_CHANNEL
123#endif
124#ifdef AD1_15_CHANNEL
126#endif
127#ifdef AD1_16_CHANNEL
129#endif
130};
131
134
135// adc_samples buffer
136// FIXME compute size to have to correct number of samples ?
137#ifndef ADC_BUF_DEPTH
138#define ADC_BUF_DEPTH (MAX_AV_NB_SAMPLE/2)
139#endif
141
142#if USE_AD1
147#endif
148#if USE_AD2
149#error ADC2_not implemented in ChibiOS
150#endif
151#if USE_AD3
152#error ADC3_not implemented in ChibiOS
153#endif
154
155#if USE_ADC_WATCHDOG
156// watchdog structure with adc bank and callback
157static struct {
158 ADCDriver *adc;
159 adc_channels_num_t channel;
163#endif
164
175static void adc_configure(ADCConversionGroup *cfg, uint8_t num_channels, const uint8_t channels[], uint32_t sample_rate,
177{
178 // Set the general configuration
179 cfg->circular = true;
180 cfg->num_channels = num_channels;
181 cfg->end_cb = end_cb;
182 cfg->error_cb = error_cb;
183
184 // Set to 16bits by default else try 12bit
185#if defined(ADC_CFGR_RES_16BITS)
187#elif defined(ADC_CFGR_RES_12BITS)
189#else
190 cfg->sqr1 = ADC_SQR1_NUM_CH(num_channels);
191 cfg->cr2 = ADC_CR2_SWSTART;
192
193#if defined(ADC_CR2_TSVREFE)
194 cfg->cr2 |= ADC_CR2_TSVREFE;
195#endif
196#endif
197
198 // Go through all the channels
199 for (uint8_t i = 0; i < num_channels; i++) {
200 uint8_t chan = channels[i];
201
202#if defined(STM32H7XX) || defined(STM32F3XX) || defined(STM32G4XX) || defined(STM32L4XX)
203 cfg->pcsel |= (1 << chan);
204 cfg->smpr[chan / 10] |= sample_rate << (3 * (chan % 10));
205
206 if (i < 4) {
207 cfg->sqr[0] |= chan << (6 * (i + 1));
208 } else if (i < 9) {
209 cfg->sqr[1] |= chan << (6 * (i - 4));
210 } else {
211 cfg->sqr[2] |= chan << (6 * (i - 9));
212 }
213#else
214 if (chan < 10) {
215 cfg->smpr2 |= sample_rate << (3 * chan);
216 } else {
217 cfg->smpr1 |= sample_rate << (3 * (chan - 10));
218 }
219
220 if (i < 6) {
221 cfg->sqr3 |= chan << (5 * i);
222 } else if (i < 12) {
223 cfg->sqr2 |= chan << (5 * (i - 6));
224 } else {
225 cfg->sqr3 |= chan << (5 * (i - 12));
226 }
227#endif
228 }
229}
230
244{
245 if (adcp->state != ADC_STOP) {
246#if USE_AD1
247 const size_t n = ADC_BUF_DEPTH / 2U;
248 // depending on half buffer that has just been filled
249 // if adcIsBufferComplete return true, the last filled
250 // half buffer start in the middle of buffer, else, is start at
251 // beginiing of buffer
252 const adcsample_t *buffer = adc_samples + (adcIsBufferComplete(adcp) ?
253 n *ADC_NUM_CHANNELS : 0U);
255
256 for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
257 if (adc1_buffers[channel] != NULL) {
258 adc1_sum_tmp[channel] = 0;
259 if (n > 0) {
260 adc1_samples_tmp[channel] = n;
261 } else {
262 adc1_samples_tmp[channel] = 1;
263 }
264 for (unsigned int sample = 0; sample < n; sample++) {
265 adc1_sum_tmp[channel] += buffer[channel + sample * ADC_NUM_CHANNELS];
266 }
267 }
268 }
270 for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
271 if (adc1_buffers[channel] != NULL) {
272 adc1_buffers[channel]->sum = adc1_sum_tmp[channel];
273 adc1_buffers[channel]->av_nb_sample = adc1_samples_tmp[channel];
274 }
275 }
276#if USE_ADC_WATCHDOG
277#pragma GCC diagnostic push
278#pragma GCC diagnostic ignored "-Wtype-limits" // remove warning when ADC_NUM_CHANNELS is 0 and test always false
279 if ((adc_watchdog.adc == adcp) &&
280 (adc_watchdog.channel < ADC_NUM_CHANNELS) &&
281 (adc_watchdog.cb != NULL)) {
282 if (adc1_buffers[adc_watchdog.channel]->sum <
283 (adc1_buffers[adc_watchdog.channel]->av_nb_sample * adc_watchdog.vmin)) {
284 adc_watchdog.cb();
285 }
286 }
287#pragma GCC diagnostic pop
288#endif // USE_ADC_WATCHDOG
289
291#endif
292 }
293}
294
295
302{
304 adcp_err = adcp;
305 adc_error_flag = err;
307}
308
313{
314 // check for out-of-bounds access
315#pragma GCC diagnostic push
316#pragma GCC diagnostic ignored "-Wtype-limits" // remove warning when ADC_NUM_CHANNELS is 0 and test always true
317 if (adc_channel >= ADC_NUM_CHANNELS) { return; }
318#pragma GCC diagnostic pop
320 if (av_nb_sample <= MAX_AV_NB_SAMPLE) {
321 s->av_nb_sample = av_nb_sample;
322 } else {
323 s->av_nb_sample = MAX_AV_NB_SAMPLE;
324 }
325}
326
332void adc_init(void)
333{
334 /* Init GPIO ports for ADC operation
335 */
336#if USE_ADC_1
337 PRINT_CONFIG_MSG("Info: Using ADC_1");
339#endif
340#if USE_ADC_2
341 PRINT_CONFIG_MSG("Info: Using ADC_2");
343#endif
344#if USE_ADC_3
345 PRINT_CONFIG_MSG("Info: Using ADC_3");
347#endif
348#if USE_ADC_4
349 PRINT_CONFIG_MSG("Info: Using ADC_4");
351#endif
352#if USE_ADC_5
353 PRINT_CONFIG_MSG("Info: Using ADC_5");
355#endif
356#if USE_ADC_6
357 PRINT_CONFIG_MSG("Info: Using ADC_6");
359#endif
360#if USE_ADC_7
361 PRINT_CONFIG_MSG("Info: Using ADC_7");
363#endif
364#if USE_ADC_8
365 PRINT_CONFIG_MSG("Info: Using ADC_8");
367#endif
368#if USE_ADC_9
369 PRINT_CONFIG_MSG("Info: Using ADC_9");
371#endif
372
373#if USE_ADC_WATCHDOG
374 adc_watchdog.adc = NULL;
375 adc_watchdog.cb = NULL;
376 adc_watchdog.channel = 0;
377 adc_watchdog.vmin = (1 << 12) - 1; // max adc
378#endif
379
380 // Configure the ADC structure
382
383 // Start ADC in continious conversion mode
386}
387
388#if USE_ADC_WATCHDOG
391{
392 for (int i = 0; i < NB_ADC1_CHANNELS; i++) { // FIXME when more than ADC1 will be in use
393 if (adc_channel_map[i] == channel) {
394 adc_watchdog.adc = adc;
395 adc_watchdog.channel = i;
396 adc_watchdog.vmin = vmin;
397 adc_watchdog.cb = cb;
398 break;
399 }
400 }
401}
402#endif
arch independent ADC (Analog to Digital Converter) API
#define MAX_AV_NB_SAMPLE
Definition adc.h:40
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition adc.h:53
void adc1callback(ADCDriver *adcp)
Adc1 callback.
Definition adc_arch.c:243
void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
Link between ChibiOS ADC drivers and Paparazzi adc_buffers.
Definition adc_arch.c:312
void adc_init(void)
Adc init.
Definition adc_arch.c:332
#define ADC_BUF_DEPTH
Definition adc_arch.c:138
#define ADC_SAMPLE_RATE
#endif
Definition adc_arch.c:76
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
Adc error callback.
Definition adc_arch.c:301
static void adc_configure(ADCConversionGroup *cfg, uint8_t num_channels, const uint8_t channels[], uint32_t sample_rate, adccallback_t end_cb, adcerrorcallback_t error_cb)
Configure the ADC conversion group depending on the architecture.
Definition adc_arch.c:175
static const uint8_t adc_channel_map[ADC_NUM_CHANNELS]
Definition adc_arch.c:81
ADCDriver * adcp_err
Definition adc_arch.c:133
uint8_t adc_error_flag
Definition adc_arch.c:132
@ NB_ADC1_CHANNELS
Definition adc_arch.h:90
#define ADC_NUM_CHANNELS
Definition adc_arch.h:93
void gpio_setup_pin_analog(ioportid_t port, uint16_t pin)
Setup a gpio for analog use.
Definition gpio_arch.c:90
Some architecture independent helper functions for GPIOs.
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
static uint32_t s
uint16_t foo
Definition main_demo5.c:58
float vmin
Specific RAM section for DMA usage on F7.
#define IN_DMA_SECTION(var)
Definition ram_arch.h:87
#define error_cb
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.