Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
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 
58 // From active ADC channels
59 //#define ADC_NUM_CHANNELS NB_ADC
60 
61 // Macros to automatically enable the correct ADC
62 
63 // FIXME we can't use NB_ADC1_CHANNELS it is not a macro
64 //#if NB_ADC1_CHANNELS != 0
65 #ifndef USE_AD1
66 #define USE_AD1 1
67 #endif
68 
70 // Create channel map
72 #ifdef AD1_1_CHANNEL
74 #endif
75 #ifdef AD1_2_CHANNEL
77 #endif
78 #ifdef AD1_3_CHANNEL
80 #endif
81 #ifdef AD1_4_CHANNEL
83 #endif
84 #ifdef AD1_5_CHANNEL
86 #endif
87 #ifdef AD1_6_CHANNEL
88  AD1_6_CHANNEL,
89 #endif
90 #ifdef AD1_7_CHANNEL
91  AD1_7_CHANNEL,
92 #endif
93 #ifdef AD1_8_CHANNEL
94  AD1_8_CHANNEL,
95 #endif
96 #ifdef AD1_9_CHANNEL
97  AD1_9_CHANNEL,
98 #endif
99 #ifdef AD1_10_CHANNEL
100  AD1_10_CHANNEL,
101 #endif
102 #ifdef AD1_11_CHANNEL
103  AD1_11_CHANNEL,
104 #endif
105 #ifdef AD1_12_CHANNEL
106  AD1_12_CHANNEL,
107 #endif
108 #ifdef AD1_13_CHANNEL
109  AD1_13_CHANNEL,
110 #endif
111 #ifdef AD1_14_CHANNEL
112  AD1_14_CHANNEL,
113 #endif
114 #ifdef AD1_15_CHANNEL
115  AD1_15_CHANNEL,
116 #endif
117 #ifdef AD1_16_CHANNEL
118  AD1_16_CHANNEL,
119 #endif
120 };
121 
123 ADCDriver *adcp_err = NULL;
124 
125 // adc_samples buffer
126 // FIXME compute size to have to correct number of samples ?
127 #ifndef ADC_BUF_DEPTH
128 #define ADC_BUF_DEPTH (MAX_AV_NB_SAMPLE/2)
129 #endif
131 
132 #if USE_AD1
136 #endif
137 #if USE_AD2
138 #error ADC2_not implemented in ChibiOS
139 #endif
140 #if USE_AD3
141 #error ADC3_not implemented in ChibiOS
142 #endif
143 
144 #if USE_ADC_WATCHDOG
145 // watchdog structure with adc bank and callback
146 static struct {
147  ADCDriver *adc;
148  adc_channels_num_t channel;
149  adcsample_t vmin;
150  adc_watchdog_callback cb;
151 } adc_watchdog;
152 #endif
153 
154 // From libopencm3
155 static void adc_regular_sequence(uint32_t *sqr1, uint32_t *sqr2, uint32_t *sqr3, uint8_t length, const uint8_t channel[])
156 {
157  uint32_t first6 = 0;
158  uint32_t second6 = 0;
159  uint32_t third6 = ADC_SQR1_NUM_CH(length);
160  uint8_t i = 0;
161 
162  for (i = 1; i <= length; i++) {
163  if (i <= 6) {
164  first6 |= (channel[i - 1] << ((i - 1) * 5));
165  }
166  if ((i > 6) & (i <= 12)) {
167  second6 |= (channel[i - 1] << ((i - 6 - 1) * 5));
168  }
169  if ((i > 12) & (i <= 18)) {
170  third6 |= (channel[i - 1] << ((i - 12 - 1) * 5));
171  }
172  }
173  *sqr3 = first6;
174  *sqr2 = second6;
175  *sqr1 = third6;
176 }
177 
178 // From libopencm3
179 static void adc_sample_time_on_all_channels(uint32_t *smpr1, uint32_t *smpr2, uint8_t time)
180 {
181  uint8_t i;
182  uint32_t reg32 = 0;
183 
184  for (i = 0; i <= 9; i++) {
185  reg32 |= (time << (i * 3));
186  }
187  *smpr2 = reg32;
188 
189  reg32 = 0;
190  for (i = 10; i <= 17; i++) {
191  reg32 |= (time << ((i - 10) * 3));
192  }
193  *smpr1 = reg32;
194 }
195 
208 void adc1callback(ADCDriver *adcp, adcsample_t *buffer, size_t n)
209 {
210  if (adcp->state != ADC_STOP) {
211 #if USE_AD1
212  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
213  if (adc1_buffers[channel] != NULL) {
214  adc1_sum_tmp[channel] = 0;
215  if (n > 0) {
217  } else {
219  }
220  for (unsigned int sample = 0; sample < n; sample++) {
221  adc1_sum_tmp[channel] += buffer[channel + sample * ADC_NUM_CHANNELS];
222  }
223  }
224  }
225  chSysLockFromISR();
226  for (int channel = 0; channel < ADC_NUM_CHANNELS; channel++) {
227  if (adc1_buffers[channel] != NULL) {
228  adc1_buffers[channel]->sum = adc1_sum_tmp[channel];
229  adc1_buffers[channel]->av_nb_sample = adc1_samples_tmp[channel];
230  }
231  }
232 #if USE_ADC_WATCHDOG
233  if ((adc_watchdog.adc == adcp) &&
234  (adc_watchdog.channel < ADC_NUM_CHANNELS) &&
235  (adc_watchdog.cb != NULL)) {
236  if (adc1_buffers[adc_watchdog.channel]->sum <
237  (adc1_buffers[adc_watchdog.channel]->av_nb_sample * adc_watchdog.vmin)) {
238  adc_watchdog.cb ();
239  }
240  }
241 #endif // USE_ADC_WATCHDOG
242 
243  chSysUnlockFromISR();
244 #endif
245  }
246 }
247 
248 
254 static void adcerrorcallback(ADCDriver *adcp, adcerror_t err)
255 {
256  chSysLockFromISR();
257  adcp_err = adcp;
258  adc_error_flag = err;
259  chSysUnlockFromISR();
260 }
261 
265 void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
266 {
267  adc1_buffers[adc_channel] = s;
268  if (av_nb_sample <= MAX_AV_NB_SAMPLE) {
269  s->av_nb_sample = av_nb_sample;
270  } else {
272  }
273 }
274 
279 static ADCConversionGroup adcgrpcfg;
280 
286 void adc_init(void)
287 {
288  /* Init GPIO ports for ADC operation
289  */
290 #if USE_ADC_1
291  PRINT_CONFIG_MSG("Info: Using ADC_1");
293 #endif
294 #if USE_ADC_2
295  PRINT_CONFIG_MSG("Info: Using ADC_2");
297 #endif
298 #if USE_ADC_3
299  PRINT_CONFIG_MSG("Info: Using ADC_3");
301 #endif
302 #if USE_ADC_4
303  PRINT_CONFIG_MSG("Info: Using ADC_4");
305 #endif
306 #if USE_ADC_5
307  PRINT_CONFIG_MSG("Info: Using ADC_5");
309 #endif
310 #if USE_ADC_6
311  PRINT_CONFIG_MSG("Info: Using ADC_6");
313 #endif
314 #if USE_ADC_7
315  PRINT_CONFIG_MSG("Info: Using ADC_7");
316  gpio_setup_pin_analog(ADC_7_GPIO_PORT, ADC_7_GPIO_PIN);
317 #endif
318 #if USE_ADC_8
319  PRINT_CONFIG_MSG("Info: Using ADC_8");
320  gpio_setup_pin_analog(ADC_8_GPIO_PORT, ADC_8_GPIO_PIN);
321 #endif
322 #if USE_ADC_9
323  PRINT_CONFIG_MSG("Info: Using ADC_9");
324  gpio_setup_pin_analog(ADC_9_GPIO_PORT, ADC_9_GPIO_PIN);
325 #endif
326 
327  // Configurtion register
328  uint32_t sqr1, sqr2, sqr3;
330 
331 #ifdef __STM32F10x_H
332  uint32_t smpr1, smpr2;
333  adc_sample_time_on_all_channels(&smpr1, &smpr2, ADC_SAMPLE_41P5);
334 
335  adcgrpcfg.cr2 = ADC_CR2_TSVREFE;
336 #elif defined(__STM32F4xx_H)
337  uint32_t smpr1, smpr2;
338  adc_sample_time_on_all_channels(&smpr1, &smpr2, ADC_SAMPLE_480);
339 
340  adcgrpcfg.cr2 = ADC_CR2_SWSTART;
341 #endif
342 
343 #if USE_ADC_WATCHDOG
344  adc_watchdog.adc = NULL;
345  adc_watchdog.cb = NULL;
346  adc_watchdog.channel = 0;
347  adc_watchdog.vmin = (1<<12)-1; // max adc
348 #endif
349 
350  adcgrpcfg.circular = TRUE;
351  adcgrpcfg.num_channels = ADC_NUM_CHANNELS;
352  adcgrpcfg.end_cb = adc1callback;
353  adcgrpcfg.error_cb = adcerrorcallback;
354  adcgrpcfg.cr1 = 0;
355  adcgrpcfg.smpr1 = smpr1;
356  adcgrpcfg.smpr2 = smpr2;
357  adcgrpcfg.sqr1 = sqr1;
358  adcgrpcfg.sqr2 = sqr2;
359  adcgrpcfg.sqr3 = sqr3;
360 
361  // Start ADC in continious conversion mode
362  adcStart(&ADCD1, NULL);
363  adcStartConversion(&ADCD1, &adcgrpcfg, adc_samples, ADC_BUF_DEPTH);
364 }
365 
366 #if USE_ADC_WATCHDOG
367 void register_adc_watchdog(ADCDriver *adc, adc_channels_num_t channel, adcsample_t vmin,
368  adc_watchdog_callback cb)
369 {
370  for (int i=0; i< NB_ADC1_CHANNELS; i++) { // FIXME when more than ADC1 will be in use
371  if (adc_channel_map[i] == channel) {
372  adc_watchdog.adc = adc;
373  adc_watchdog.channel = i;
374  adc_watchdog.vmin = vmin;
375  adc_watchdog.cb = cb;
376  break;
377  }
378  }
379 }
380 #endif
uint8_t av_nb_sample
Definition: adc.h:57
#define ADC_4_GPIO_PIN
Definition: board.h:758
#define AD1_1_CHANNEL
Definition: cjmcu.h:62
ADCDriver * adcp_err
Definition: adc_arch.c:123
Some architecture independent helper functions for GPIOs.
static uint32_t adc1_sum_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:134
#define AD1_5_CHANNEL
Definition: board.h:1151
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:265
uint32_t sum
Definition: adc.h:54
#define ADC_6_GPIO_PIN
static ADCConversionGroup adcgrpcfg
Configuration structure must be global.
Definition: adc_arch.c:279
static adcsample_t adc_samples[ADC_NUM_CHANNELS *ADC_BUF_DEPTH]
Definition: adc_arch.c:130
arch independent ADC (Analog to Digital Converter) API
#define ADC_5_GPIO_PORT
#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:133
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:71
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:68
#define ADC_1_GPIO_PIN
Definition: cjmcu.h:65
uint8_t adc_error_flag
Definition: adc_arch.c:122
#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:179
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:254
void adc1callback(ADCDriver *adcp, adcsample_t *buffer, size_t n)
Adc1 callback.
Definition: adc_arch.c:208
static uint8_t adc1_samples_tmp[ADC_NUM_CHANNELS]
Definition: adc_arch.c:135
void adc_init(void)
Adc init.
Definition: adc_arch.c:286
#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:155
#define ADC_NUM_CHANNELS
Definition: adc_arch.h:93
#define ADC_5_GPIO_PIN
#define ADC_BUF_DEPTH
Definition: adc_arch.c:128