Paparazzi UAS  v5.12_stable-4-g9b43e9b
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
66 
68 
69 // architecture dependent settings
70 #if defined(__STM32F10x_H) || defined(__STM32F105xC_H) || defined (__STM32F107xC_H)
71 // STM32F1xx
72 #define ADC_SAMPLE_RATE ADC_SAMPLE_41P5
73 #define ADC_CR2_CFG ADC_CR2_TSVREFE
74 #elif defined(__STM32F4xx_H) || defined(__STM32F7xx_H)
75 // STM32F4xx | STM32F7xx
76 #define ADC_SAMPLE_RATE ADC_SAMPLE_480
77 #define ADC_CR2_CFG ADC_CR2_SWSTART
78 #endif
79 
80 
81 // Create channel map
83 #ifdef AD1_1_CHANNEL
85 #endif
86 #ifdef AD1_2_CHANNEL
88 #endif
89 #ifdef AD1_3_CHANNEL
91 #endif
92 #ifdef AD1_4_CHANNEL
94 #endif
95 #ifdef AD1_5_CHANNEL
97 #endif
98 #ifdef AD1_6_CHANNEL
99  AD1_6_CHANNEL,
100 #endif
101 #ifdef AD1_7_CHANNEL
103 #endif
104 #ifdef AD1_8_CHANNEL
105  AD1_8_CHANNEL,
106 #endif
107 #ifdef AD1_9_CHANNEL
108  AD1_9_CHANNEL,
109 #endif
110 #ifdef AD1_10_CHANNEL
111  AD1_10_CHANNEL,
112 #endif
113 #ifdef AD1_11_CHANNEL
114  AD1_11_CHANNEL,
115 #endif
116 #ifdef AD1_12_CHANNEL
117  AD1_12_CHANNEL,
118 #endif
119 #ifdef AD1_13_CHANNEL
120  AD1_13_CHANNEL,
121 #endif
122 #ifdef AD1_14_CHANNEL
123  AD1_14_CHANNEL,
124 #endif
125 #ifdef AD1_15_CHANNEL
126  AD1_15_CHANNEL,
127 #endif
128 #ifdef AD1_16_CHANNEL
129  AD1_16_CHANNEL,
130 #endif
131 };
132 
134 ADCDriver *adcp_err = NULL;
135 
136 // adc_samples buffer
137 // FIXME compute size to have to correct number of samples ?
138 #ifndef ADC_BUF_DEPTH
139 #define ADC_BUF_DEPTH (MAX_AV_NB_SAMPLE/2)
140 #endif
141 static IN_DMA_SECTION(adcsample_t adc_samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH]);
142 
143 #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
157 static struct {
158  ADCDriver *adc;
159  adc_channels_num_t channel;
160  adcsample_t vmin;
161  adc_watchdog_callback cb;
162 } adc_watchdog;
163 #endif
164 
165 // From libopencm3
166 static void adc_regular_sequence(uint32_t *sqr1, uint32_t *sqr2, uint32_t *sqr3, uint8_t length, const uint8_t channel[])
167 {
168  uint32_t first6 = 0;
169  uint32_t second6 = 0;
170  uint32_t third6 = ADC_SQR1_NUM_CH(length);
171  uint8_t i = 0;
172 
173  for (i = 1; i <= length; i++) {
174  if (i <= 6) {
175  first6 |= (channel[i - 1] << ((i - 1) * 5));
176  }
177  if ((i > 6) & (i <= 12)) {
178  second6 |= (channel[i - 1] << ((i - 6 - 1) * 5));
179  }
180  if ((i > 12) & (i <= 18)) {
181  third6 |= (channel[i - 1] << ((i - 12 - 1) * 5));
182  }
183  }
184  *sqr3 = first6;
185  *sqr2 = second6;
186  *sqr1 = third6;
187 }
188 
189 // From libopencm3
190 static void adc_sample_time_on_all_channels(uint32_t *smpr1, uint32_t *smpr2, uint8_t time)
191 {
192  uint8_t i;
193  uint32_t reg32 = 0;
194 
195  for (i = 0; i <= 9; i++) {
196  reg32 |= (time << (i * 3));
197  }
198  *smpr2 = reg32;
199 
200  reg32 = 0;
201  for (i = 10; i <= 17; i++) {
202  reg32 |= (time << ((i - 10) * 3));
203  }
204  *smpr1 = reg32;
205 }
206 
219 void adc1callback(ADCDriver *adcp, adcsample_t *buffer, size_t n)
220 {
221  if (adcp->state != ADC_STOP) {
222 #if USE_AD1
223  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
224  if (adc1_buffers[channel] != NULL) {
225  adc1_sum_tmp[channel] = 0;
226  if (n > 0) {
228  } else {
230  }
231  for (unsigned int sample = 0; sample < n; sample++) {
232  adc1_sum_tmp[channel] += buffer[channel + sample * ADC_NUM_CHANNELS];
233  }
234  }
235  }
236  chSysLockFromISR();
237  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
238  if (adc1_buffers[channel] != NULL) {
239  adc1_buffers[channel]->sum = adc1_sum_tmp[channel];
240  adc1_buffers[channel]->av_nb_sample = adc1_samples_tmp[channel];
241  }
242  }
243 #if USE_ADC_WATCHDOG
244  if ((adc_watchdog.adc == adcp) &&
245  (adc_watchdog.channel < ADC_NUM_CHANNELS) &&
246  (adc_watchdog.cb != NULL)) {
247  if (adc1_buffers[adc_watchdog.channel]->sum <
248  (adc1_buffers[adc_watchdog.channel]->av_nb_sample * adc_watchdog.vmin)) {
249  adc_watchdog.cb ();
250  }
251  }
252 #endif // USE_ADC_WATCHDOG
253 
254  chSysUnlockFromISR();
255 #endif
256  }
257 }
258 
259 
265 static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
266 {
267  chSysLockFromISR();
268  adcp_err = adcp;
269  adc_error_flag = err;
270  chSysUnlockFromISR();
271 }
272 
276 void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
277 {
278  // check for out-of-bounds access
279  if (adc_channel >= ADC_NUM_CHANNELS) return;
280  adc1_buffers[adc_channel] = s;
281  if (av_nb_sample <= MAX_AV_NB_SAMPLE) {
282  s->av_nb_sample = av_nb_sample;
283  } else {
285  }
286 }
287 
292 static ADCConversionGroup adcgrpcfg;
293 
299 void adc_init(void)
300 {
301  /* Init GPIO ports for ADC operation
302  */
303 #if USE_ADC_1
304  PRINT_CONFIG_MSG("Info: Using ADC_1");
306 #endif
307 #if USE_ADC_2
308  PRINT_CONFIG_MSG("Info: Using ADC_2");
310 #endif
311 #if USE_ADC_3
312  PRINT_CONFIG_MSG("Info: Using ADC_3");
314 #endif
315 #if USE_ADC_4
316  PRINT_CONFIG_MSG("Info: Using ADC_4");
318 #endif
319 #if USE_ADC_5
320  PRINT_CONFIG_MSG("Info: Using ADC_5");
322 #endif
323 #if USE_ADC_6
324  PRINT_CONFIG_MSG("Info: Using ADC_6");
326 #endif
327 #if USE_ADC_7
328  PRINT_CONFIG_MSG("Info: Using ADC_7");
330 #endif
331 #if USE_ADC_8
332  PRINT_CONFIG_MSG("Info: Using ADC_8");
333  gpio_setup_pin_analog(ADC_8_GPIO_PORT, ADC_8_GPIO_PIN);
334 #endif
335 #if USE_ADC_9
336  PRINT_CONFIG_MSG("Info: Using ADC_9");
337  gpio_setup_pin_analog(ADC_9_GPIO_PORT, ADC_9_GPIO_PIN);
338 #endif
339 
340  // Configuration register
341  uint32_t sqr1, sqr2, sqr3;
343 
344  uint32_t smpr1, smpr2;
345  adc_sample_time_on_all_channels(&smpr1, &smpr2, ADC_SAMPLE_RATE);
346 
347  adcgrpcfg.cr2 = ADC_CR2_CFG;
348 
349 #if USE_ADC_WATCHDOG
350  adc_watchdog.adc = NULL;
351  adc_watchdog.cb = NULL;
352  adc_watchdog.channel = 0;
353  adc_watchdog.vmin = (1<<12)-1; // max adc
354 #endif
355 
356  adcgrpcfg.circular = TRUE;
357  adcgrpcfg.num_channels = ADC_NUM_CHANNELS;
358  adcgrpcfg.end_cb = adc1callback;
359  adcgrpcfg.error_cb = adcerrorcallback;
360  adcgrpcfg.cr1 = 0;
361  adcgrpcfg.smpr1 = smpr1;
362  adcgrpcfg.smpr2 = smpr2;
363  adcgrpcfg.sqr1 = sqr1;
364  adcgrpcfg.sqr2 = sqr2;
365  adcgrpcfg.sqr3 = sqr3;
366 
367  // Start ADC in continious conversion mode
368  adcStart(&ADCD1, NULL);
369  adcStartConversion(&ADCD1, &adcgrpcfg, adc_samples, ADC_BUF_DEPTH);
370 }
371 
372 #if USE_ADC_WATCHDOG
373 void register_adc_watchdog(ADCDriver *adc, adc_channels_num_t channel, adcsample_t vmin,
374  adc_watchdog_callback cb)
375 {
376  for (int i=0; i< NB_ADC1_CHANNELS; i++) { // FIXME when more than ADC1 will be in use
377  if (adc_channel_map[i] == channel) {
378  adc_watchdog.adc = adc;
379  adc_watchdog.channel = i;
380  adc_watchdog.vmin = vmin;
381  adc_watchdog.cb = cb;
382  break;
383  }
384  }
385 }
386 #endif
uint8_t av_nb_sample
Definition: adc.h:57
Specific RAM section for DMA usage on F7.
#define ADC_7_GPIO_PIN
Definition: chimera.h:191
#define ADC_4_GPIO_PIN
Definition: board.h:758
#define AD1_1_CHANNEL
Definition: cjmcu.h:62
ADCDriver * adcp_err
Definition: adc_arch.c:134
Some architecture independent helper functions for GPIOs.
#define AD1_7_CHANNEL
Definition: chimera.h:188
static IN_DMA_SECTION(adcsample_t adc_samples[ADC_NUM_CHANNELS *ADC_BUF_DEPTH])
static uint32_t adc1_sum_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:145
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:276
uint32_t sum
Definition: adc.h:54
#define ADC_6_GPIO_PIN
#define ADC_7_GPIO_PORT
Definition: chimera.h:190
static ADCConversionGroup adcgrpcfg
Configuration structure must be global.
Definition: adc_arch.c:292
arch independent ADC (Analog to Digital Converter) API
#define ADC_1_GPIO_PORT
Definition: cjmcu.h:64
#define ADC_3_GPIO_PIN
Definition: lisa_l_1.0.h:151
static struct adc_buf * adc1_buffers[ADC_NUM_CHANNELS]
Definition: adc_arch.c:144
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:53
#define TRUE
Definition: std.h:4
static const uint8_t adc_channel_map[ADC_NUM_CHANNELS]
#endif
Definition: adc_arch.c:82
#define ADC_5_GPIO_PIN
Definition: board.h:284
unsigned long uint32_t
Definition: types.h:18
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
void gpio_setup_pin_analog(ioportid_t port, uint16_t pin)
Setup a gpio for analog use.
Definition: gpio_arch.c:86
#define ADC_1_GPIO_PIN
Definition: cjmcu.h:65
#define AD1_5_CHANNEL
Definition: board.h:281
#define ADC_5_GPIO_PORT
Definition: board.h:283
uint8_t adc_error_flag
Definition: adc_arch.c:133
#define AD1_4_CHANNEL
Definition: board.h:755
static void adc_sample_time_on_all_channels(uint32_t *smpr1, uint32_t *smpr2, uint8_t time)
Definition: adc_arch.c:190
float vmin
#define MAX_AV_NB_SAMPLE
Definition: adc.h:40
#define ADC_4_GPIO_PORT
Definition: board.h:757
#define ADC_3_GPIO_PORT
Definition: lisa_l_1.0.h:150
unsigned char uint8_t
Definition: types.h:14
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
Adc error callback.
Definition: adc_arch.c:265
void adc1callback(ADCDriver *adcp, adcsample_t *buffer, size_t n)
Adc1 callback.
Definition: adc_arch.c:219
static uint8_t adc1_samples_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:146
void adc_init(void)
Adc init.
Definition: adc_arch.c:299
#define ADC_6_GPIO_PORT
static uint8_t channel
Definition: ADS8344.c:80
#define AD1_3_CHANNEL
Definition: lisa_l_1.0.h:148
static void adc_regular_sequence(uint32_t *sqr1, uint32_t *sqr2, uint32_t *sqr3, uint8_t length, const uint8_t channel[])
Definition: adc_arch.c:166
#define ADC_NUM_CHANNELS
Definition: adc_arch.h:93
#define ADC_BUF_DEPTH
Definition: adc_arch.c:139