Mozzi  version v2.0
sound synthesis library for Arduino
MozziGuts_impl_STM32duino_analog.hpp
1 /*
2  * MozziGuts_impl_STM32duino_analog.hpp
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2023-2024 Thomas Friedrichsmeier and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10 // NOTE: The contents of this file are copied mostly verbatim from Arduino_Core_STM32, (c) STMicroelectronics, BSD 3-clause license.
11 */
12 
13 namespace MozziPrivate {
14 static PinName g_current_pin = NC;
15 
16 #ifndef ADC_SAMPLINGTIME
17 #if defined(ADC_SAMPLETIME_8CYCLES_5)
18 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_8CYCLES_5;
19 #elif defined(ADC_SAMPLETIME_12CYCLES)
20 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_12CYCLES;
21 #elif defined(ADC_SAMPLETIME_12CYCLES_5)
22 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_12CYCLES_5;
23 #elif defined(ADC_SAMPLETIME_13CYCLES_5)
24 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_13CYCLES_5;
25 #elif defined(ADC_SAMPLETIME_15CYCLES)
26 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_15CYCLES;
27 #elif defined(ADC_SAMPLETIME_16CYCLES)
28 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_16CYCLES;
29 #elif defined(ADC_SAMPLETIME_19CYCLES_5)
30 #define ADC_SAMPLINGTIME ADC_SAMPLETIME_19CYCLES_5;
31 #endif
32 #endif /* !ADC_SAMPLINGTIME */
33 
34 #if defined(ADC_VER_V5_V90) && !defined(ADC3_SAMPLINGTIME)
35 #define ADC3_SAMPLINGTIME ADC3_SAMPLETIME_24CYCLES_5;
36 #endif
37 
38 #if defined(ADC4_SAMPLETIME_19CYCLES_5) && !defined(ADC4_SAMPLINGTIME)
39 #define ADC4_SAMPLINGTIME ADC4_SAMPLETIME_19CYCLES_5;
40 #endif
41 
42 /*
43  * Minimum ADC sampling time is required when reading
44  * internal channels so set it to max possible value.
45  * It can be defined more precisely by defining:
46  * ADC_SAMPLINGTIME_INTERNAL
47  * to the desired ADC sample time.
48  */
49 #ifndef ADC_SAMPLINGTIME_INTERNAL
50 #if defined(ADC_SAMPLETIME_480CYCLES)
51 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_480CYCLES
52 #elif defined(ADC_SAMPLETIME_384CYCLES)
53 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_384CYCLES
54 #elif defined(ADC_SAMPLETIME_810CYCLES_5)
55 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_810CYCLES_5
56 #elif defined(ADC_SAMPLETIME_814CYCLES)
57 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_814CYCLES
58 #elif defined(ADC_SAMPLETIME_640CYCLES_5)
59 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_640CYCLES_5
60 #elif defined(ADC_SAMPLETIME_601CYCLES_5)
61 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_601CYCLES_5
62 #elif defined(ADC_SAMPLETIME_247CYCLES_5)
63 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_247CYCLES_5
64 #elif defined(ADC_SAMPLETIME_239CYCLES_5)
65 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_239CYCLES_5
66 #elif defined(ADC_SAMPLETIME_160CYCLES_5)
67 #define ADC_SAMPLINGTIME_INTERNAL ADC_SAMPLETIME_160CYCLES_5
68 #else
69 #error "ADC sampling time could not be defined for internal channels!"
70 #endif
71 #endif /* !ADC_SAMPLINGTIME_INTERNAL */
72 
73 
74 #ifndef ADC_CLOCK_DIV
75 #ifdef ADC_CLOCK_SYNC_PCLK_DIV4
76 #define ADC_CLOCK_DIV ADC_CLOCK_SYNC_PCLK_DIV4
77 #elif ADC_CLOCK_SYNC_PCLK_DIV2
78 #define ADC_CLOCK_DIV ADC_CLOCK_SYNC_PCLK_DIV2
79 #elif defined(ADC_CLOCK_ASYNC_DIV4)
80 #define ADC_CLOCK_DIV ADC_CLOCK_ASYNC_DIV4
81 #endif
82 #endif /* !ADC_CLOCK_DIV */
83 
84 #ifndef ADC_REGULAR_RANK_1
85 #define ADC_REGULAR_RANK_1 1
86 #endif
87 
88 // adc_read_value() modified to keep only the ADC setup, but not the (blocking) ADC read
89 bool adc_setup_read(PinName pin, uint32_t resolution) {
90  AdcHandle = {};
91  ADC_ChannelConfTypeDef AdcChannelConf = {};
92  uint32_t samplingTime = ADC_SAMPLINGTIME;
93  uint32_t channel = 0;
94  uint32_t bank = 0;
95 
96  if ((pin & PADC_BASE) && (pin < ANA_START)) {
97 #if defined(STM32H7xx) || defined(STM32MP1xx)
98 #ifdef ADC3
99  AdcHandle.Instance = ADC3;
100 #else
101  AdcHandle.Instance = ADC2;
102 #endif
103 #else
104  AdcHandle.Instance = ADC1;
105 #if defined(ADC5) && defined(ADC_CHANNEL_TEMPSENSOR_ADC5)
106  if (pin == PADC_TEMP_ADC5) {
107  AdcHandle.Instance = ADC5;
108  }
109 #endif
110 #endif
111  channel = get_adc_internal_channel(pin);
112  samplingTime = ADC_SAMPLINGTIME_INTERNAL;
113  } else {
114  AdcHandle.Instance = (ADC_TypeDef *)pinmap_peripheral(pin, PinMap_ADC);
115  channel = get_adc_channel(pin, &bank);
116 #if defined(ADC_VER_V5_V90)
117  if (AdcHandle.Instance == ADC3) {
118  samplingTime = ADC3_SAMPLINGTIME;
119  }
120 #endif
121 #if defined(ADC4_SAMPLINGTIME)
122  if (AdcHandle.Instance == ADC4) {
123  samplingTime = ADC4_SAMPLINGTIME;
124  }
125 #endif
126  }
127 
128  if (AdcHandle.Instance == NP) {
129  return 0;
130  }
131 
132 #ifdef ADC_CLOCK_DIV
133  AdcHandle.Init.ClockPrescaler = ADC_CLOCK_DIV; /* (A)synchronous clock mode, input ADC clock divided */
134 #endif
135 #ifdef ADC_RESOLUTION_12B
136  switch (resolution) {
137 #ifdef ADC_RESOLUTION_6B
138  case 6:
139  AdcHandle.Init.Resolution = ADC_RESOLUTION_6B; /* resolution for converted data */
140  break;
141 #endif
142  case 8:
143  AdcHandle.Init.Resolution = ADC_RESOLUTION_8B; /* resolution for converted data */
144  break;
145  case 10:
146  AdcHandle.Init.Resolution = ADC_RESOLUTION_10B; /* resolution for converted data */
147  break;
148  case 12:
149  default:
150  AdcHandle.Init.Resolution = ADC_RESOLUTION_12B; /* resolution for converted data */
151  break;
152 #ifdef ADC_RESOLUTION_14B
153  case 14:
154  AdcHandle.Init.Resolution = ADC_RESOLUTION_14B; /* resolution for converted data */
155  break;
156 #endif
157 #ifdef ADC_RESOLUTION_16B
158  case 16:
159  AdcHandle.Init.Resolution = ADC_RESOLUTION_16B; /* resolution for converted data */
160  break;
161 #endif
162  }
163 #else
164  UNUSED(resolution);
165 #endif
166 #ifdef ADC_DATAALIGN_RIGHT
167  AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT; /* Right-alignment for converted data */
168 #endif
169 #ifdef ADC_SCAN_SEQ_FIXED
170  AdcHandle.Init.ScanConvMode = ADC_SCAN_SEQ_FIXED; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
171 #else
172  AdcHandle.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
173 #endif
174 #ifdef ADC_EOC_SINGLE_CONV
175  AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* EOC flag picked-up to indicate conversion end */
176 #endif
177 #if !defined(STM32F1xx) && !defined(STM32F2xx) && !defined(STM32F4xx) &&
178  !defined(STM32F7xx) && !defined(ADC1_V2_5)
179  AdcHandle.Init.LowPowerAutoWait = DISABLE; /* Auto-delayed conversion feature disabled */
180 #endif
181 #if !defined(STM32F1xx) && !defined(STM32F2xx) && !defined(STM32F3xx) &&
182  !defined(STM32F4xx) && !defined(STM32F7xx) && !defined(STM32G4xx) &&
183  !defined(STM32H7xx) && !defined(STM32L4xx) && !defined(STM32L5xx) &&
184  !defined(STM32MP1xx) && !defined(STM32WBxx) || defined(ADC_SUPPORT_2_5_MSPS)
185  AdcHandle.Init.LowPowerAutoPowerOff = DISABLE; /* ADC automatically powers-off after a conversion and automatically wakes-up when a new conversion is triggered */
186 #endif
187 #ifdef ADC_CHANNELS_BANK_B
188  AdcHandle.Init.ChannelsBank = bank;
189 #elif defined(ADC_CHANNELS_BANK_A)
190  AdcHandle.Init.ChannelsBank = ADC_CHANNELS_BANK_A;
191 #endif
192  AdcHandle.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 conversion at each conversion trig */
193 #if !defined(STM32F0xx) && !defined(STM32L0xx)
194  AdcHandle.Init.NbrOfConversion = 1; /* Specifies the number of ranks that will be converted within the regular group sequencer. */
195 #endif
196  AdcHandle.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */
197 #if !defined(STM32C0xx) && !defined(STM32F0xx) && !defined(STM32G0xx) &&
198  !defined(STM32L0xx) && !defined(STM32WLxx) && !defined(ADC_SUPPORT_2_5_MSPS)
199  AdcHandle.Init.NbrOfDiscConversion = 0; /* Parameter discarded because sequencer is disabled */
200 #endif
201  AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* Software start to trig the 1st conversion manually, without external event */
202 #if !defined(STM32F1xx) && !defined(ADC1_V2_5)
203  AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */
204 #endif
205 #if !defined(STM32F1xx) && !defined(STM32H7xx) && !defined(STM32MP1xx) &&
206  !defined(ADC1_V2_5)
207  AdcHandle.Init.DMAContinuousRequests = DISABLE; /* DMA one-shot mode selected (not applied to this example) */
208 #endif
209 #ifdef ADC_CONVERSIONDATA_DR
210  AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; /* Regular Conversion data stored in DR register only */
211 #endif
212 #ifdef ADC_OVR_DATA_OVERWRITTEN
213  AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; /* DR register is overwritten with the last conversion result in case of overrun */
214 #endif
215 #ifdef ADC_LEFTBITSHIFT_NONE
216  AdcHandle.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; /* No bit shift left applied on the final ADC conversion data */
217 #endif
218 
219 #if defined(STM32F0xx)
220  AdcHandle.Init.SamplingTimeCommon = samplingTime;
221 #endif
222 #if defined(STM32C0xx) || defined(STM32G0xx) || defined(STM32U5xx) ||
223  defined(STM32WLxx) || defined(ADC_SUPPORT_2_5_MSPS)
224  AdcHandle.Init.SamplingTimeCommon1 = samplingTime; /* Set sampling time common to a group of channels. */
225  AdcHandle.Init.SamplingTimeCommon2 = samplingTime; /* Set sampling time common to a group of channels, second common setting possible.*/
226 #endif
227 #if defined(STM32L0xx)
228  AdcHandle.Init.LowPowerFrequencyMode = DISABLE; /* To be enabled only if ADC clock < 2.8 MHz */
229  AdcHandle.Init.SamplingTime = samplingTime;
230 #endif
231 #if !defined(STM32F0xx) && !defined(STM32F1xx) && !defined(STM32F2xx) &&
232  !defined(STM32F3xx) && !defined(STM32F4xx) && !defined(STM32F7xx) &&
233  !defined(STM32L1xx) && !defined(ADC_SUPPORT_2_5_MSPS)
234  AdcHandle.Init.OversamplingMode = DISABLE;
235  /* AdcHandle.Init.Oversample ignore for STM32L0xx as oversampling disabled */
236  /* AdcHandle.Init.Oversampling ignored for other as oversampling disabled */
237 #endif
238 #if defined(ADC_CFGR_DFSDMCFG) && defined(DFSDM1_Channel0)
239  AdcHandle.Init.DFSDMConfig = ADC_DFSDM_MODE_DISABLE; /* ADC conversions are not transferred by DFSDM. */
240 #endif
241 #ifdef ADC_TRIGGER_FREQ_HIGH
242  AdcHandle.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
243 #endif
244 #ifdef ADC_VREF_PPROT_NONE
245  AdcHandle.Init.VrefProtection = ADC_VREF_PPROT_NONE;
246 #endif
247 
248  AdcHandle.State = HAL_ADC_STATE_RESET;
249  AdcHandle.DMA_Handle = NULL;
250  AdcHandle.Lock = HAL_UNLOCKED;
251  /* Some other ADC_HandleTypeDef fields exists but not required */
252 
253  g_current_pin = pin; /* Needed for HAL_ADC_MspInit*/
254 
255  if (HAL_ADC_Init(&AdcHandle) != HAL_OK) {
256  return 0;
257  }
258 
259  AdcChannelConf.Channel = channel; /* Specifies the channel to configure into ADC */
260 
261 #if defined(STM32G4xx) || defined(STM32L4xx) || defined(STM32L5xx) ||
262  defined(STM32WBxx)
263  if (!IS_ADC_CHANNEL(&AdcHandle, AdcChannelConf.Channel)) {
264 #else
265  if (!IS_ADC_CHANNEL(AdcChannelConf.Channel)) {
266 #endif
267  return 0;
268  }
269 #if defined(ADC_SCAN_SEQ_FIXED) && defined(ADC_RANK_CHANNEL_NUMBER)
270  AdcChannelConf.Rank = ADC_RANK_CHANNEL_NUMBER; /* Enable the rank of the selected channels when not fully configurable */
271 #else
272  AdcChannelConf.Rank = ADC_REGULAR_RANK_1; /* Specifies the rank in the regular group sequencer */
273 #endif
274 #if !defined(STM32L0xx)
275 #if !defined(STM32G0xx)
276  AdcChannelConf.SamplingTime = samplingTime; /* Sampling time value to be set for the selected channel */
277 #else
278  AdcChannelConf.SamplingTime = ADC_SAMPLINGTIME_COMMON_1; /* Sampling time value to be set for the selected channel */
279 #endif
280 #endif
281 #if defined(ADC_DIFFERENTIAL_ENDED) && !defined(ADC1_V2_5)
282  AdcChannelConf.SingleDiff = ADC_SINGLE_ENDED; /* Single-ended input channel */
283  AdcChannelConf.OffsetNumber = ADC_OFFSET_NONE; /* No offset subtraction */
284 #endif
285 #if !defined(STM32C0xx) && !defined(STM32F0xx) && !defined(STM32F1xx) &&
286  !defined(STM32F2xx) && !defined(STM32G0xx) && !defined(STM32L0xx) &&
287  !defined(STM32L1xx) && !defined(STM32WBxx) && !defined(STM32WLxx) &&
288  !defined(ADC1_V2_5)
289  AdcChannelConf.Offset = 0; /* Parameter discarded because offset correction is disabled */
290 #endif
291 #if defined (STM32H7xx) || defined(STM32MP1xx)
292  AdcChannelConf.OffsetRightShift = DISABLE; /* No Right Offset Shift */
293  AdcChannelConf.OffsetSignedSaturation = DISABLE; /* Signed saturation feature is not used */
294 #endif
295 
296  /*##-2- Configure ADC regular channel ######################################*/
297  if (HAL_ADC_ConfigChannel(&AdcHandle, &AdcChannelConf) != HAL_OK) {
298  /* Channel Configuration Error */
299  return 0;
300  }
301 
302 #if defined(ADC_CR_ADCAL) || defined(ADC_CR2_RSTCAL)
303  /*##-2.1- Calibrate ADC then Start the conversion process ####################*/
304 #if defined(ADC_CALIB_OFFSET)
305  if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
306 #elif defined(ADC_SINGLE_ENDED) && !defined(ADC1_V2_5)
307  if (HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED) != HAL_OK)
308 #else
309  if (HAL_ADCEx_Calibration_Start(&AdcHandle) != HAL_OK)
310 #endif
311  {
312  /* ADC Calibration Error */
313  return 0;
314  }
315 #endif
316 
317  /*##-3- Start the conversion process ####################*/
318  if (HAL_ADC_Start(&AdcHandle) != HAL_OK) {
319  /* Start Conversion Error */
320  return 0;
321  }
322 
323  return HAL_OK;
324 }
325 
326 } // namespace MozziPrivate