dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_internal_adc_simple.c
Go to the documentation of this file.
1 
14 /*
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with this program; if not, see <http://www.gnu.org/licenses/>
27  */
28 
30 
31 #if defined(PIOS_INCLUDE_ADC)
32 
33 static void PIOS_INTERNAL_ADC_PinConfig(pios_internal_adc_t adc);
34 static void PIOS_INTERNAL_ADC_Converter_Config(pios_internal_adc_t adc);
35 static int32_t PIOS_INTERNAL_ADC_PinGet(uintptr_t internal_adc_id, uint32_t pin);
36 static uint8_t PIOS_INTERNAL_ADC_NumberOfChannels(uintptr_t internal_adc_id);
37 static float PIOS_INTERNAL_ADC_LSB_Voltage(uintptr_t internal_adc_id);
38 
40  .get_pin = PIOS_INTERNAL_ADC_PinGet,
41  .number_of_channels = PIOS_INTERNAL_ADC_NumberOfChannels,
42  .lsb_voltage = PIOS_INTERNAL_ADC_LSB_Voltage,
43 };
44 
45 #define MAX_CHANNELS 8
46 
47 struct pios_internal_adc_dev {
48  const struct pios_internal_adc_simple_cfg * cfg;
49 
50  uint8_t conversion_started : 1;
51  uint8_t current_pin : 3;
52 
53  volatile uint16_t pin_values[MAX_CHANNELS];
54 };
55 
60 static bool PIOS_INTERNAL_ADC_validate(pios_internal_adc_t dev)
61 {
62  if (dev == NULL )
63  return false;
64 
65  return true;
66 }
67 
71 static pios_internal_adc_t PIOS_INTERNAL_ADC_Allocate()
72 {
73  pios_internal_adc_t adc_dev = PIOS_malloc(sizeof(*adc_dev));
74  if (!adc_dev)
75  return (NULL);
76 
77  return (adc_dev);
78 }
79 
84 static void PIOS_INTERNAL_ADC_PinConfig(pios_internal_adc_t adc_dev)
85 {
86  if (!PIOS_INTERNAL_ADC_validate(adc_dev)) {
87  return;
88  }
89  /* Setup analog pins */
90  GPIO_InitTypeDef GPIO_InitStructure;
91  GPIO_StructInit(&GPIO_InitStructure);
92  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
93  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
94 
95  for (int32_t i = 0; i < adc_dev->cfg->adc_pin_count; i++) {
96  adc_dev->pin_values[i] = 0xffff;
97 
98  if (adc_dev->cfg->adc_pins[i].port == NULL )
99  continue;
100  GPIO_InitStructure.GPIO_Pin = adc_dev->cfg->adc_pins[i].pin;
101  GPIO_Init(adc_dev->cfg->adc_pins[i].port, (GPIO_InitTypeDef*) &GPIO_InitStructure);
102  }
103 }
104 
109 static void PIOS_INTERNAL_ADC_Converter_Config(pios_internal_adc_t adc_dev)
110 {
111  ADC_DeInit(adc_dev->cfg->adc_dev);
112 
113  /* Perform ADC calibration */
114  ADC1->CR |= ADC_CR_ADCAL;
115  while ((ADC1->CR & ADC_CR_ADCAL) != 0);
116 
117  ADC_InitTypeDef ADC_InitStructure;
118  ADC_StructInit(&ADC_InitStructure);
119 
120  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
121  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
122  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
123  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
124 
125  ADC_Init(adc_dev->cfg->adc_dev, &ADC_InitStructure);
126 
127  ADC_ClockModeConfig(adc_dev->cfg->adc_dev, ADC_ClockMode_AsynClk);
128  ADC_ContinuousModeCmd(adc_dev->cfg->adc_dev, DISABLE);
129  ADC_DiscModeCmd(adc_dev->cfg->adc_dev, ENABLE);
130 
131  /* Do common ADC init */
132  ADC_TempSensorCmd(ENABLE);
133  ADC_VrefintCmd(ENABLE);
134 
135  ADC_Cmd(adc_dev->cfg->adc_dev, ENABLE);
136 
137  while (!ADC_GetFlagStatus(adc_dev->cfg->adc_dev, ADC_FLAG_ADRDY));
138 }
139 
143 int32_t PIOS_INTERNAL_ADC_Init(pios_internal_adc_t * internal_adc_id, const struct pios_internal_adc_simple_cfg * cfg)
144 {
145  PIOS_DEBUG_Assert(internal_adc_id); PIOS_DEBUG_Assert(cfg);
146 
147  PIOS_Assert(cfg->adc_pin_count <= MAX_CHANNELS);
148 
150  adc_dev = PIOS_INTERNAL_ADC_Allocate();
151  if (adc_dev == NULL )
152  return -1;
153  adc_dev->cfg = cfg;
154 
155  *internal_adc_id = adc_dev;
156 
157  adc_dev->current_pin = 0;
158 
159  PIOS_INTERNAL_ADC_PinConfig(adc_dev);
160 
161  PIOS_INTERNAL_ADC_Converter_Config(adc_dev);
162  return 0;
163 }
164 
166 {
167  if (!adc_dev->conversion_started) {
168  /* Read the DR to ensure that the ADC_FLAG_EOC flag is not set */
169  ADC_GetConversionValue(adc_dev->cfg->adc_dev);
170 
171 
172  adc_dev->cfg->adc_dev->CHSELR = adc_dev->cfg->adc_pins[adc_dev->current_pin].adc_channel;
173  adc_dev->cfg->adc_dev->SMPR = ADC_SampleTime_41_5Cycles;
174  /* 41.5 cycles is a very long integration time, but we're in
175  * no rush */
176 
177  ADC_StartOfConversion(adc_dev->cfg->adc_dev);
178 
179  adc_dev->conversion_started = 1;
180  } else {
181  if (ADC_GetFlagStatus(adc_dev->cfg->adc_dev,
182  ADC_FLAG_ADSTART) == RESET) {
183  adc_dev->pin_values[adc_dev->current_pin] =
184  ADC_GetConversionValue(adc_dev->cfg->adc_dev);
185 
186  adc_dev->current_pin++;
187 
188  if (adc_dev->current_pin > adc_dev->cfg->adc_pin_count) {
189  adc_dev->current_pin = 0;
190  }
191 
192  adc_dev->conversion_started = 0;
193  }
194  }
195 }
196 
202 static uint8_t PIOS_INTERNAL_ADC_NumberOfChannels(uintptr_t internal_adc_id)
203 {
204  pios_internal_adc_t adc_dev = (pios_internal_adc_t) internal_adc_id;
205  if (!PIOS_INTERNAL_ADC_validate(adc_dev))
206  return 0;
207  return adc_dev->cfg->adc_pin_count;
208 }
209 
216 static int32_t PIOS_INTERNAL_ADC_PinGet(uintptr_t internal_adc_id, uint32_t pin)
217 {
218  pios_internal_adc_t adc_dev = (pios_internal_adc_t) internal_adc_id;
219 
220  /* Check if pin exists */
221  if (pin >= adc_dev->cfg->adc_pin_count) {
222  return -1;
223  }
224 
225  return adc_dev->pin_values[pin];
226 }
227 
231 static float PIOS_INTERNAL_ADC_LSB_Voltage(uintptr_t internal_adc_id)
232 {
233  pios_internal_adc_t adc_dev = (pios_internal_adc_t) internal_adc_id;
234  if (!PIOS_INTERNAL_ADC_validate(adc_dev)) {
235  return 0;
236  }
237 
238  // Though we have 12 bits of resolution, it's left-adjusted into a 16
239  // bit word.
240  return VREF_PLUS / (((uint32_t)1 << 16) - 16);
241 }
242 #endif /* PIOS_INCLUDE_ADC */
243 
int32_t PIOS_INTERNAL_ADC_Init(uintptr_t *internal_adc_id, const struct pios_internal_adc_cfg *cfg)
void PIOS_INTERNAL_ADC_DoStep(pios_internal_adc_t internal_adc_id)
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
struct pios_internal_adc_dev * pios_internal_adc_t
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
const struct pios_adc_driver pios_internal_adc_driver
#define VREF_PLUS
Definition: pios_board.h:222
uint8_t i
Definition: msp_messages.h:97
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t(* get_pin)(uintptr_t id, uint32_t pin)
Definition: pios_adc.h:41