1 /***************************************************************************//**
\r
3 * @brief Analog to Digital Converter (ADC) peripheral API
\r
5 *******************************************************************************
\r
7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
\r
8 *******************************************************************************
\r
10 * Permission is granted to anyone to use this software for any purpose,
\r
11 * including commercial applications, and to alter it and redistribute it
\r
12 * freely, subject to the following restrictions:
\r
14 * 1. The origin of this software must not be misrepresented; you must not
\r
15 * claim that you wrote the original software.
\r
16 * 2. Altered source versions must be plainly marked as such, and must not be
\r
17 * misrepresented as being the original software.
\r
18 * 3. This notice may not be removed or altered from any source distribution.
\r
20 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
\r
21 * obligation to support this Software. Silicon Labs is providing the
\r
22 * Software "AS IS", with no express or implied warranties of any kind,
\r
23 * including, but not limited to, any implied warranties of merchantability
\r
24 * or fitness for any particular purpose or warranties against infringement
\r
25 * of any proprietary rights of a third party.
\r
27 * Silicon Labs will not be liable for any consequential, incidental, or
\r
28 * special damages, or any other relief, or for any claim by any third party,
\r
29 * arising from your use of this Software.
\r
31 ******************************************************************************/
\r
34 #ifndef __SILICON_LABS_EM_ADC_H_
\r
35 #define __SILICON_LABS_EM_ADC_H_
\r
37 #include "em_device.h"
\r
38 #if defined(ADC_COUNT) && (ADC_COUNT > 0)
\r
40 #include <stdbool.h>
\r
46 /***************************************************************************//**
\r
47 * @addtogroup EM_Library
\r
49 ******************************************************************************/
\r
51 /***************************************************************************//**
\r
54 ******************************************************************************/
\r
56 /*******************************************************************************
\r
57 ******************************** ENUMS ************************************
\r
58 ******************************************************************************/
\r
60 /** Acquisition time (in ADC clock cycles). */
\r
63 adcAcqTime1 = _ADC_SINGLECTRL_AT_1CYCLE, /**< 1 clock cycle. */
\r
64 adcAcqTime2 = _ADC_SINGLECTRL_AT_2CYCLES, /**< 2 clock cycles. */
\r
65 adcAcqTime4 = _ADC_SINGLECTRL_AT_4CYCLES, /**< 4 clock cycles. */
\r
66 adcAcqTime8 = _ADC_SINGLECTRL_AT_8CYCLES, /**< 8 clock cycles. */
\r
67 adcAcqTime16 = _ADC_SINGLECTRL_AT_16CYCLES, /**< 16 clock cycles. */
\r
68 adcAcqTime32 = _ADC_SINGLECTRL_AT_32CYCLES, /**< 32 clock cycles. */
\r
69 adcAcqTime64 = _ADC_SINGLECTRL_AT_64CYCLES, /**< 64 clock cycles. */
\r
70 adcAcqTime128 = _ADC_SINGLECTRL_AT_128CYCLES, /**< 128 clock cycles. */
\r
71 adcAcqTime256 = _ADC_SINGLECTRL_AT_256CYCLES /**< 256 clock cycles. */
\r
72 } ADC_AcqTime_TypeDef;
\r
75 /** Lowpass filter mode. */
\r
78 /** No filter or decoupling capacitor. */
\r
79 adcLPFilterBypass = _ADC_CTRL_LPFMODE_BYPASS,
\r
81 /** On-chip RC filter. */
\r
82 adcLPFilterRC = _ADC_CTRL_LPFMODE_RCFILT,
\r
84 /** On-chip decoupling capacitor. */
\r
85 adcLPFilterDeCap = _ADC_CTRL_LPFMODE_DECAP
\r
86 } ADC_LPFilter_TypeDef;
\r
89 /** Oversample rate select. */
\r
92 /** 2 samples per conversion result. */
\r
93 adcOvsRateSel2 = _ADC_CTRL_OVSRSEL_X2,
\r
95 /** 4 samples per conversion result. */
\r
96 adcOvsRateSel4 = _ADC_CTRL_OVSRSEL_X4,
\r
98 /** 8 samples per conversion result. */
\r
99 adcOvsRateSel8 = _ADC_CTRL_OVSRSEL_X8,
\r
101 /** 16 samples per conversion result. */
\r
102 adcOvsRateSel16 = _ADC_CTRL_OVSRSEL_X16,
\r
104 /** 32 samples per conversion result. */
\r
105 adcOvsRateSel32 = _ADC_CTRL_OVSRSEL_X32,
\r
107 /** 64 samples per conversion result. */
\r
108 adcOvsRateSel64 = _ADC_CTRL_OVSRSEL_X64,
\r
110 /** 128 samples per conversion result. */
\r
111 adcOvsRateSel128 = _ADC_CTRL_OVSRSEL_X128,
\r
113 /** 256 samples per conversion result. */
\r
114 adcOvsRateSel256 = _ADC_CTRL_OVSRSEL_X256,
\r
116 /** 512 samples per conversion result. */
\r
117 adcOvsRateSel512 = _ADC_CTRL_OVSRSEL_X512,
\r
119 /** 1024 samples per conversion result. */
\r
120 adcOvsRateSel1024 = _ADC_CTRL_OVSRSEL_X1024,
\r
122 /** 2048 samples per conversion result. */
\r
123 adcOvsRateSel2048 = _ADC_CTRL_OVSRSEL_X2048,
\r
125 /** 4096 samples per conversion result. */
\r
126 adcOvsRateSel4096 = _ADC_CTRL_OVSRSEL_X4096
\r
127 } ADC_OvsRateSel_TypeDef;
\r
130 /** Peripheral Reflex System signal used to trigger single sample. */
\r
133 adcPRSSELCh0 = _ADC_SINGLECTRL_PRSSEL_PRSCH0, /**< PRS channel 0. */
\r
134 adcPRSSELCh1 = _ADC_SINGLECTRL_PRSSEL_PRSCH1, /**< PRS channel 1. */
\r
135 adcPRSSELCh2 = _ADC_SINGLECTRL_PRSSEL_PRSCH2, /**< PRS channel 2. */
\r
136 adcPRSSELCh3 = _ADC_SINGLECTRL_PRSSEL_PRSCH3, /**< PRS channel 3. */
\r
137 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH4 )
\r
138 adcPRSSELCh4 = _ADC_SINGLECTRL_PRSSEL_PRSCH4, /**< PRS channel 4. */
\r
140 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH5 )
\r
141 adcPRSSELCh5 = _ADC_SINGLECTRL_PRSSEL_PRSCH5, /**< PRS channel 5. */
\r
143 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH6 )
\r
144 adcPRSSELCh6 = _ADC_SINGLECTRL_PRSSEL_PRSCH6, /**< PRS channel 6. */
\r
146 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH7 )
\r
147 adcPRSSELCh7 = _ADC_SINGLECTRL_PRSSEL_PRSCH7, /**< PRS channel 7. */
\r
149 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH8 )
\r
150 adcPRSSELCh8 = _ADC_SINGLECTRL_PRSSEL_PRSCH8, /**< PRS channel 8. */
\r
152 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH9 )
\r
153 adcPRSSELCh9 = _ADC_SINGLECTRL_PRSSEL_PRSCH9, /**< PRS channel 9. */
\r
155 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH10 )
\r
156 adcPRSSELCh10 = _ADC_SINGLECTRL_PRSSEL_PRSCH10, /**< PRS channel 10. */
\r
158 #if defined( _ADC_SINGLECTRL_PRSSEL_PRSCH11 )
\r
159 adcPRSSELCh11 = _ADC_SINGLECTRL_PRSSEL_PRSCH11, /**< PRS channel 11. */
\r
161 } ADC_PRSSEL_TypeDef;
\r
164 /** Reference to ADC sample. */
\r
167 /** Internal 1.25V reference. */
\r
168 adcRef1V25 = _ADC_SINGLECTRL_REF_1V25,
\r
170 /** Internal 2.5V reference. */
\r
171 adcRef2V5 = _ADC_SINGLECTRL_REF_2V5,
\r
173 /** Buffered VDD. */
\r
174 adcRefVDD = _ADC_SINGLECTRL_REF_VDD,
\r
176 /** Internal differential 5V reference. */
\r
177 adcRef5VDIFF = _ADC_SINGLECTRL_REF_5VDIFF,
\r
179 /** Single ended ext. ref. from pin 6. */
\r
180 adcRefExtSingle = _ADC_SINGLECTRL_REF_EXTSINGLE,
\r
182 /** Differential ext. ref. from pin 6 and 7. */
\r
183 adcRef2xExtDiff = _ADC_SINGLECTRL_REF_2XEXTDIFF,
\r
185 /** Unbuffered 2xVDD. */
\r
186 adcRef2xVDD = _ADC_SINGLECTRL_REF_2XVDD
\r
190 /** Sample resolution. */
\r
193 adcRes12Bit = _ADC_SINGLECTRL_RES_12BIT, /**< 12 bit sampling. */
\r
194 adcRes8Bit = _ADC_SINGLECTRL_RES_8BIT, /**< 8 bit sampling. */
\r
195 adcRes6Bit = _ADC_SINGLECTRL_RES_6BIT, /**< 6 bit sampling. */
\r
196 adcResOVS = _ADC_SINGLECTRL_RES_OVS /**< Oversampling. */
\r
200 /** Single sample input selection. */
\r
203 /* Differential mode disabled */
\r
204 adcSingleInpCh0 = _ADC_SINGLECTRL_INPUTSEL_CH0, /**< Channel 0. */
\r
205 adcSingleInpCh1 = _ADC_SINGLECTRL_INPUTSEL_CH1, /**< Channel 1. */
\r
206 adcSingleInpCh2 = _ADC_SINGLECTRL_INPUTSEL_CH2, /**< Channel 2. */
\r
207 adcSingleInpCh3 = _ADC_SINGLECTRL_INPUTSEL_CH3, /**< Channel 3. */
\r
208 adcSingleInpCh4 = _ADC_SINGLECTRL_INPUTSEL_CH4, /**< Channel 4. */
\r
209 adcSingleInpCh5 = _ADC_SINGLECTRL_INPUTSEL_CH5, /**< Channel 5. */
\r
210 adcSingleInpCh6 = _ADC_SINGLECTRL_INPUTSEL_CH6, /**< Channel 6. */
\r
211 adcSingleInpCh7 = _ADC_SINGLECTRL_INPUTSEL_CH7, /**< Channel 7. */
\r
212 adcSingleInpTemp = _ADC_SINGLECTRL_INPUTSEL_TEMP, /**< Temperature reference. */
\r
213 adcSingleInpVDDDiv3 = _ADC_SINGLECTRL_INPUTSEL_VDDDIV3, /**< VDD divided by 3. */
\r
214 adcSingleInpVDD = _ADC_SINGLECTRL_INPUTSEL_VDD, /**< VDD. */
\r
215 adcSingleInpVSS = _ADC_SINGLECTRL_INPUTSEL_VSS, /**< VSS. */
\r
216 adcSingleInpVrefDiv2 = _ADC_SINGLECTRL_INPUTSEL_VREFDIV2, /**< Vref divided by 2. */
\r
217 adcSingleInpDACOut0 = _ADC_SINGLECTRL_INPUTSEL_DAC0OUT0, /**< DAC output 0. */
\r
218 adcSingleInpDACOut1 = _ADC_SINGLECTRL_INPUTSEL_DAC0OUT1, /**< DAC output 1. */
\r
219 /* TBD: Use define when available */
\r
220 adcSingleInpATEST = 15, /**< ATEST. */
\r
222 /* Differential mode enabled */
\r
223 adcSingleInpCh0Ch1 = _ADC_SINGLECTRL_INPUTSEL_CH0CH1, /**< Positive Ch0, negative Ch1. */
\r
224 adcSingleInpCh2Ch3 = _ADC_SINGLECTRL_INPUTSEL_CH2CH3, /**< Positive Ch2, negative Ch3. */
\r
225 adcSingleInpCh4Ch5 = _ADC_SINGLECTRL_INPUTSEL_CH4CH5, /**< Positive Ch4, negative Ch5. */
\r
226 adcSingleInpCh6Ch7 = _ADC_SINGLECTRL_INPUTSEL_CH6CH7, /**< Positive Ch6, negative Ch7. */
\r
227 /* TBD: Use define when available */
\r
228 adcSingleInpDiff0 = 4 /**< Differential 0. */
\r
229 } ADC_SingleInput_TypeDef;
\r
232 /** ADC Start command. */
\r
235 /** Start single conversion. */
\r
236 adcStartSingle = ADC_CMD_SINGLESTART,
\r
238 /** Start scan sequence. */
\r
239 adcStartScan = ADC_CMD_SCANSTART,
\r
242 * Start scan sequence and single conversion, typically used when tailgating
\r
243 * single conversion after scan sequence.
\r
245 adcStartScanAndSingle = ADC_CMD_SCANSTART | ADC_CMD_SINGLESTART
\r
246 } ADC_Start_TypeDef;
\r
249 /** Warm-up mode. */
\r
252 /** ADC shutdown after each conversion. */
\r
253 adcWarmupNormal = _ADC_CTRL_WARMUPMODE_NORMAL,
\r
255 /** Do not warm-up bandgap references. */
\r
256 adcWarmupFastBG = _ADC_CTRL_WARMUPMODE_FASTBG,
\r
258 /** Reference selected for scan mode kept warm.*/
\r
259 adcWarmupKeepScanRefWarm = _ADC_CTRL_WARMUPMODE_KEEPSCANREFWARM,
\r
261 /** ADC and reference selected for scan mode kept warm.*/
\r
262 adcWarmupKeepADCWarm = _ADC_CTRL_WARMUPMODE_KEEPADCWARM
\r
263 } ADC_Warmup_TypeDef;
\r
266 /*******************************************************************************
\r
267 ******************************* STRUCTS ***********************************
\r
268 ******************************************************************************/
\r
270 /** ADC init structure, common for single conversion and scan sequence. */
\r
274 * Oversampling rate select. In order to have any effect, oversampling must
\r
275 * be enabled for single/scan mode.
\r
277 ADC_OvsRateSel_TypeDef ovsRateSel;
\r
279 /** Lowpass or decoupling capacitor filter to use. */
\r
280 ADC_LPFilter_TypeDef lpfMode;
\r
282 /** Warm-up mode to use for ADC. */
\r
283 ADC_Warmup_TypeDef warmUpMode;
\r
286 * Timebase used for ADC warm up. Select N to give (N+1)HFPERCLK cycles.
\r
287 * (Additional delay is added for bandgap references, please refer to the
\r
288 * reference manual.) Normally, N should be selected so that the timebase
\r
289 * is at least 1 us. See ADC_TimebaseCalc() for a way to obtain
\r
290 * a suggested timebase of at least 1 us.
\r
294 /** Clock division factor N, ADC clock = HFPERCLK / (N + 1). */
\r
297 /** Enable/disable conversion tailgating. */
\r
299 } ADC_Init_TypeDef;
\r
301 /** Default config for ADC init structure. */
\r
302 #define ADC_INIT_DEFAULT \
\r
303 { adcOvsRateSel2, /* 2x oversampling (if enabled). */ \
\r
304 adcLPFilterBypass, /* No input filter selected. */ \
\r
305 adcWarmupNormal, /* ADC shutdown after each conversion. */ \
\r
306 _ADC_CTRL_TIMEBASE_DEFAULT, /* Use HW default value. */ \
\r
307 _ADC_CTRL_PRESC_DEFAULT, /* Use HW default value. */ \
\r
308 false /* Do not use tailgate. */ \
\r
312 /** Scan sequence init structure. */
\r
316 * Peripheral reflex system trigger selection. Only applicable if @p prsEnable
\r
319 ADC_PRSSEL_TypeDef prsSel;
\r
321 /** Acquisition time (in ADC clock cycles). */
\r
322 ADC_AcqTime_TypeDef acqTime;
\r
325 * Sample reference selection. Notice that for external references, the
\r
326 * ADC calibration register must be set explicitly.
\r
328 ADC_Ref_TypeDef reference;
\r
330 /** Sample resolution. */
\r
331 ADC_Res_TypeDef resolution;
\r
334 * Input scan selection. If single ended (@p diff is false), use logical
\r
335 * combination of ADC_SCANCTRL_INPUTMASK_CHx defines. If differential input
\r
336 * (@p diff is true), use logical combination of ADC_SCANCTRL_INPUTMASK_CHxCHy
\r
337 * defines. (Notice underscore prefix for defines used.)
\r
341 /** Select if single ended or differential input. */
\r
344 /** Peripheral reflex system trigger enable. */
\r
347 /** Select if left adjustment should be done. */
\r
350 /** Select if continuous conversion until explicit stop. */
\r
352 } ADC_InitScan_TypeDef;
\r
354 /** Default config for ADC scan init structure. */
\r
355 #define ADC_INITSCAN_DEFAULT \
\r
356 { adcPRSSELCh0, /* PRS ch0 (if enabled). */ \
\r
357 adcAcqTime1, /* 1 ADC_CLK cycle acquisition time. */ \
\r
358 adcRef1V25, /* 1.25V internal reference. */ \
\r
359 adcRes12Bit, /* 12 bit resolution. */ \
\r
360 0, /* No input selected. */ \
\r
361 false, /* Single ended input. */ \
\r
362 false, /* PRS disabled. */ \
\r
363 false, /* Right adjust. */ \
\r
364 false /* Deactivate conversion after one scan sequence. */ \
\r
368 /** Single conversion init structure. */
\r
372 * Peripheral reflex system trigger selection. Only applicable if @p prsEnable
\r
375 ADC_PRSSEL_TypeDef prsSel;
\r
377 /** Acquisition time (in ADC clock cycles). */
\r
378 ADC_AcqTime_TypeDef acqTime;
\r
381 * Sample reference selection. Notice that for external references, the
\r
382 * ADC calibration register must be set explicitly.
\r
384 ADC_Ref_TypeDef reference;
\r
386 /** Sample resolution. */
\r
387 ADC_Res_TypeDef resolution;
\r
390 * Sample input selection, use single ended or differential input according
\r
391 * to setting of @p diff.
\r
393 ADC_SingleInput_TypeDef input;
\r
395 /** Select if single ended or differential input. */
\r
398 /** Peripheral reflex system trigger enable. */
\r
401 /** Select if left adjustment should be done. */
\r
404 /** Select if continuous conversion until explicit stop. */
\r
406 } ADC_InitSingle_TypeDef;
\r
408 /** Default config for ADC single conversion init structure. */
\r
409 #define ADC_INITSINGLE_DEFAULT \
\r
410 { adcPRSSELCh0, /* PRS ch0 (if enabled). */ \
\r
411 adcAcqTime1, /* 1 ADC_CLK cycle acquisition time. */ \
\r
412 adcRef1V25, /* 1.25V internal reference. */ \
\r
413 adcRes12Bit, /* 12 bit resolution. */ \
\r
414 adcSingleInpCh0, /* CH0 input selected. */ \
\r
415 false, /* Single ended input. */ \
\r
416 false, /* PRS disabled. */ \
\r
417 false, /* Right adjust. */ \
\r
418 false /* Deactivate conversion after one scan sequence. */ \
\r
422 /*******************************************************************************
\r
423 ***************************** PROTOTYPES **********************************
\r
424 ******************************************************************************/
\r
426 /***************************************************************************//**
\r
428 * Get single conversion result.
\r
431 * Do only use if single conversion data valid.
\r
434 * Pointer to ADC peripheral register block.
\r
438 ******************************************************************************/
\r
439 __STATIC_INLINE uint32_t ADC_DataSingleGet(ADC_TypeDef *adc)
\r
441 return(adc->SINGLEDATA);
\r
445 /***************************************************************************//**
\r
450 * Do only use if scan data valid.
\r
453 * Pointer to ADC peripheral register block.
\r
454 ******************************************************************************/
\r
455 __STATIC_INLINE uint32_t ADC_DataScanGet(ADC_TypeDef *adc)
\r
457 return(adc->SCANDATA);
\r
461 void ADC_Init(ADC_TypeDef *adc, const ADC_Init_TypeDef *init);
\r
462 void ADC_InitScan(ADC_TypeDef *adc, const ADC_InitScan_TypeDef *init);
\r
463 void ADC_InitSingle(ADC_TypeDef *adc, const ADC_InitSingle_TypeDef *init);
\r
465 /***************************************************************************//**
\r
467 * Clear one or more pending ADC interrupts.
\r
470 * Pointer to ADC peripheral register block.
\r
473 * Pending ADC interrupt source to clear. Use a bitwise logic OR combination
\r
474 * of valid interrupt flags for the ADC module (ADC_IF_nnn).
\r
475 ******************************************************************************/
\r
476 __STATIC_INLINE void ADC_IntClear(ADC_TypeDef *adc, uint32_t flags)
\r
482 /***************************************************************************//**
\r
484 * Disable one or more ADC interrupts.
\r
487 * Pointer to ADC peripheral register block.
\r
490 * ADC interrupt sources to disable. Use a bitwise logic OR combination of
\r
491 * valid interrupt flags for the ADC module (ADC_IF_nnn).
\r
492 ******************************************************************************/
\r
493 __STATIC_INLINE void ADC_IntDisable(ADC_TypeDef *adc, uint32_t flags)
\r
495 adc->IEN &= ~(flags);
\r
499 /***************************************************************************//**
\r
501 * Enable one or more ADC interrupts.
\r
504 * Depending on the use, a pending interrupt may already be set prior to
\r
505 * enabling the interrupt. Consider using ADC_IntClear() prior to enabling
\r
506 * if such a pending interrupt should be ignored.
\r
509 * Pointer to ADC peripheral register block.
\r
512 * ADC interrupt sources to enable. Use a bitwise logic OR combination of
\r
513 * valid interrupt flags for the ADC module (ADC_IF_nnn).
\r
514 ******************************************************************************/
\r
515 __STATIC_INLINE void ADC_IntEnable(ADC_TypeDef *adc, uint32_t flags)
\r
521 /***************************************************************************//**
\r
523 * Get pending ADC interrupt flags.
\r
526 * The event bits are not cleared by the use of this function.
\r
529 * Pointer to ADC peripheral register block.
\r
532 * ADC interrupt sources pending. A bitwise logic OR combination of valid
\r
533 * interrupt flags for the ADC module (ADC_IF_nnn).
\r
534 ******************************************************************************/
\r
535 __STATIC_INLINE uint32_t ADC_IntGet(ADC_TypeDef *adc)
\r
541 /***************************************************************************//**
\r
543 * Set one or more pending ADC interrupts from SW.
\r
546 * Pointer to ADC peripheral register block.
\r
549 * ADC interrupt sources to set to pending. Use a bitwise logic OR combination
\r
550 * of valid interrupt flags for the ADC module (ADC_IF_nnn).
\r
551 ******************************************************************************/
\r
552 __STATIC_INLINE void ADC_IntSet(ADC_TypeDef *adc, uint32_t flags)
\r
557 uint8_t ADC_PrescaleCalc(uint32_t adcFreq, uint32_t hfperFreq);
\r
560 /***************************************************************************//**
\r
562 * Start scan sequence and/or single conversion.
\r
565 * Pointer to ADC peripheral register block.
\r
568 * Command indicating which type of sampling to start.
\r
569 ******************************************************************************/
\r
570 __STATIC_INLINE void ADC_Start(ADC_TypeDef *adc, ADC_Start_TypeDef cmd)
\r
572 adc->CMD = (uint32_t)cmd;
\r
575 void ADC_Reset(ADC_TypeDef *adc);
\r
576 uint8_t ADC_TimebaseCalc(uint32_t hfperFreq);
\r
578 /** @} (end addtogroup ADC) */
\r
579 /** @} (end addtogroup EM_Library) */
\r
585 #endif /* defined(ADC_COUNT) && (ADC_COUNT > 0) */
\r
586 #endif /* __SILICON_LABS_EM_ADC_H_ */
\r