EZR32 Wonder Gecko Software Documentation  ezr32wg-doc-4.2.1
em_adc.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_adc.h"
34 #if defined( ADC_COUNT ) && ( ADC_COUNT > 0 )
35 
36 #include "em_cmu.h"
37 #include "em_assert.h"
38 #include <stddef.h>
39 
40 /***************************************************************************/
45 /***************************************************************************/
51 /*******************************************************************************
52  ******************************* DEFINES ***********************************
53  ******************************************************************************/
54 
58 #define ADC_REF_VALID(ref) ((ref) == ADC0)
59 
61 #if defined( _SILICON_LABS_32B_PLATFORM_1 )
62 #define ADC_MAX_CLOCK 13000000
63 #else
64 #define ADC_MAX_CLOCK 16000000
65 #endif
66 
68 #define ADC_MIN_CLOCK 32000
69 
71 #if defined( _DEVINFO_ADC0CAL0_1V25_GAIN_MASK )
72 #define DEVINFO_ADC0_GAIN1V25_MASK _DEVINFO_ADC0CAL0_1V25_GAIN_MASK
73 #elif defined( _DEVINFO_ADC0CAL0_GAIN1V25_MASK )
74 #define DEVINFO_ADC0_GAIN1V25_MASK _DEVINFO_ADC0CAL0_GAIN1V25_MASK
75 #endif
76 
77 #if defined( _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT )
78 #define DEVINFO_ADC0_GAIN1V25_SHIFT _DEVINFO_ADC0CAL0_1V25_GAIN_SHIFT
79 #elif defined( _DEVINFO_ADC0CAL0_GAIN1V25_SHIFT )
80 #define DEVINFO_ADC0_GAIN1V25_SHIFT _DEVINFO_ADC0CAL0_GAIN1V25_SHIFT
81 #endif
82 
83 #if defined( _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK )
84 #define DEVINFO_ADC0_OFFSET1V25_MASK _DEVINFO_ADC0CAL0_1V25_OFFSET_MASK
85 #elif defined( _DEVINFO_ADC0CAL0_OFFSET1V25_MASK )
86 #define DEVINFO_ADC0_OFFSET1V25_MASK _DEVINFO_ADC0CAL0_OFFSET1V25_MASK
87 #endif
88 
89 #if defined( _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT )
90 #define DEVINFO_ADC0_OFFSET1V25_SHIFT _DEVINFO_ADC0CAL0_1V25_OFFSET_SHIFT
91 #elif defined( _DEVINFO_ADC0CAL0_OFFSET1V25_SHIFT )
92 #define DEVINFO_ADC0_OFFSET1V25_SHIFT _DEVINFO_ADC0CAL0_OFFSET1V25_SHIFT
93 #endif
94 
95 #if defined( _DEVINFO_ADC0CAL0_2V5_GAIN_MASK )
96 #define DEVINFO_ADC0_GAIN2V5_MASK _DEVINFO_ADC0CAL0_2V5_GAIN_MASK
97 #elif defined( _DEVINFO_ADC0CAL0_GAIN2V5_MASK )
98 #define DEVINFO_ADC0_GAIN2V5_MASK _DEVINFO_ADC0CAL0_GAIN2V5_MASK
99 #endif
100 
101 #if defined( _DEVINFO_ADC0CAL0_2V5_GAIN_SHIFT )
102 #define DEVINFO_ADC0_GAIN2V5_SHIFT _DEVINFO_ADC0CAL0_2V5_GAIN_SHIFT
103 #elif defined( _DEVINFO_ADC0CAL0_GAIN2V5_SHIFT )
104 #define DEVINFO_ADC0_GAIN2V5_SHIFT _DEVINFO_ADC0CAL0_GAIN2V5_SHIFT
105 #endif
106 
107 #if defined( _DEVINFO_ADC0CAL0_2V5_OFFSET_MASK )
108 #define DEVINFO_ADC0_OFFSET2V5_MASK _DEVINFO_ADC0CAL0_2V5_OFFSET_MASK
109 #elif defined( _DEVINFO_ADC0CAL0_OFFSET2V5_MASK )
110 #define DEVINFO_ADC0_OFFSET2V5_MASK _DEVINFO_ADC0CAL0_OFFSET2V5_MASK
111 #endif
112 
113 #if defined( _DEVINFO_ADC0CAL0_2V5_OFFSET_SHIFT )
114 #define DEVINFO_ADC0_OFFSET2V5_SHIFT _DEVINFO_ADC0CAL0_2V5_OFFSET_SHIFT
115 #elif defined( _DEVINFO_ADC0CAL0_OFFSET2V5_SHIFT )
116 #define DEVINFO_ADC0_OFFSET2V5_SHIFT _DEVINFO_ADC0CAL0_OFFSET2V5_SHIFT
117 #endif
118 
119 #if defined( _DEVINFO_ADC0CAL1_VDD_GAIN_MASK )
120 #define DEVINFO_ADC0_GAINVDD_MASK _DEVINFO_ADC0CAL1_VDD_GAIN_MASK
121 #elif defined( _DEVINFO_ADC0CAL1_GAINVDD_MASK )
122 #define DEVINFO_ADC0_GAINVDD_MASK _DEVINFO_ADC0CAL1_GAINVDD_MASK
123 #endif
124 
125 #if defined( _DEVINFO_ADC0CAL1_VDD_GAIN_SHIFT )
126 #define DEVINFO_ADC0_GAINVDD_SHIFT _DEVINFO_ADC0CAL1_VDD_GAIN_SHIFT
127 #elif defined( _DEVINFO_ADC0CAL1_GAINVDD_SHIFT )
128 #define DEVINFO_ADC0_GAINVDD_SHIFT _DEVINFO_ADC0CAL1_GAINVDD_SHIFT
129 #endif
130 
131 #if defined( _DEVINFO_ADC0CAL1_VDD_OFFSET_MASK )
132 #define DEVINFO_ADC0_OFFSETVDD_MASK _DEVINFO_ADC0CAL1_VDD_OFFSET_MASK
133 #elif defined( _DEVINFO_ADC0CAL1_OFFSETVDD_MASK )
134 #define DEVINFO_ADC0_OFFSETVDD_MASK _DEVINFO_ADC0CAL1_OFFSETVDD_MASK
135 #endif
136 
137 #if defined( _DEVINFO_ADC0CAL1_VDD_OFFSET_SHIFT )
138 #define DEVINFO_ADC0_OFFSETVDD_SHIFT _DEVINFO_ADC0CAL1_VDD_OFFSET_SHIFT
139 #elif defined( _DEVINFO_ADC0CAL1_OFFSETVDD_SHIFT )
140 #define DEVINFO_ADC0_OFFSETVDD_SHIFT _DEVINFO_ADC0CAL1_OFFSETVDD_SHIFT
141 #endif
142 
143 #if defined( _DEVINFO_ADC0CAL1_5VDIFF_GAIN_MASK )
144 #define DEVINFO_ADC0_GAIN5VDIFF_MASK _DEVINFO_ADC0CAL1_5VDIFF_GAIN_MASK
145 #elif defined( _DEVINFO_ADC0CAL1_GAIN5VDIFF_MASK )
146 #define DEVINFO_ADC0_GAIN5VDIFF_MASK _DEVINFO_ADC0CAL1_GAIN5VDIFF_MASK
147 #endif
148 
149 #if defined( _DEVINFO_ADC0CAL1_5VDIFF_GAIN_SHIFT )
150 #define DEVINFO_ADC0_GAIN5VDIFF_SHIFT _DEVINFO_ADC0CAL1_5VDIFF_GAIN_SHIFT
151 #elif defined( _DEVINFO_ADC0CAL1_GAIN5VDIFF_SHIFT )
152 #define DEVINFO_ADC0_GAIN5VDIFF_SHIFT _DEVINFO_ADC0CAL1_GAIN5VDIFF_SHIFT
153 #endif
154 
155 #if defined( _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_MASK )
156 #define DEVINFO_ADC0_OFFSET5VDIFF_MASK _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_MASK
157 #elif defined( _DEVINFO_ADC0CAL1_OFFSET5VDIFF_MASK )
158 #define DEVINFO_ADC0_OFFSET5VDIFF_MASK _DEVINFO_ADC0CAL1_OFFSET5VDIFF_MASK
159 #endif
160 
161 #if defined( _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_SHIFT )
162 #define DEVINFO_ADC0_OFFSET5VDIFF_SHIFT _DEVINFO_ADC0CAL1_5VDIFF_OFFSET_SHIFT
163 #elif defined( _DEVINFO_ADC0CAL1_OFFSET5VDIFF_SHIFT )
164 #define DEVINFO_ADC0_OFFSET5VDIFF_SHIFT _DEVINFO_ADC0CAL1_OFFSET5VDIFF_SHIFT
165 #endif
166 
167 #if defined( _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_MASK )
168 #define DEVINFO_ADC0_OFFSET2XVDD_MASK _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_MASK
169 #elif defined( _DEVINFO_ADC0CAL2_OFFSET2XVDD_MASK )
170 #define DEVINFO_ADC0_OFFSET2XVDD_MASK _DEVINFO_ADC0CAL2_OFFSET2XVDD_MASK
171 #endif
172 
173 #if defined( _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_SHIFT )
174 #define DEVINFO_ADC0_OFFSET2XVDD_SHIFT _DEVINFO_ADC0CAL2_2XVDDVSS_OFFSET_SHIFT
175 #elif defined( _DEVINFO_ADC0CAL2_OFFSET2XVDD_SHIFT )
176 #define DEVINFO_ADC0_OFFSET2XVDD_SHIFT _DEVINFO_ADC0CAL2_OFFSET2XVDD_SHIFT
177 #endif
178 
182 /*******************************************************************************
183  *************************** LOCAL FUNCTIONS *******************************
184  ******************************************************************************/
185 
188 /***************************************************************************/
208 static void ADC_LoadDevinfoCal(ADC_TypeDef *adc,
209  ADC_Ref_TypeDef ref,
210  bool setScanCal)
211 {
212  uint32_t calReg;
213  uint32_t newCal;
214  uint32_t mask;
215  uint32_t shift;
216 
217  if (setScanCal)
218  {
220  mask = ~(_ADC_CAL_SCANOFFSET_MASK
221 #if defined( _ADC_CAL_SCANOFFSETINV_MASK )
222  | _ADC_CAL_SCANOFFSETINV_MASK
223 #endif
225  }
226  else
227  {
230 #if defined( _ADC_CAL_SINGLEOFFSETINV_MASK )
231  | _ADC_CAL_SINGLEOFFSETINV_MASK
232 #endif
234  }
235 
236  calReg = adc->CAL & mask;
237  newCal = 0;
238 
239  switch (ref)
240  {
241  case adcRef1V25:
242  newCal |= ((DEVINFO->ADC0CAL0 & DEVINFO_ADC0_GAIN1V25_MASK)
243  >> DEVINFO_ADC0_GAIN1V25_SHIFT)
245  newCal |= ((DEVINFO->ADC0CAL0 & DEVINFO_ADC0_OFFSET1V25_MASK)
246  >> DEVINFO_ADC0_OFFSET1V25_SHIFT)
248 #if defined( _ADC_CAL_SINGLEOFFSETINV_MASK )
249  newCal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_NEGSEOFFSET1V25_MASK)
250  >> _DEVINFO_ADC0CAL0_NEGSEOFFSET1V25_SHIFT)
251  << _ADC_CAL_SINGLEOFFSETINV_SHIFT;
252 #endif
253  break;
254 
255  case adcRef2V5:
256  newCal |= ((DEVINFO->ADC0CAL0 & DEVINFO_ADC0_GAIN2V5_MASK)
257  >> DEVINFO_ADC0_GAIN2V5_SHIFT)
259  newCal |= ((DEVINFO->ADC0CAL0 & DEVINFO_ADC0_OFFSET2V5_MASK)
260  >> DEVINFO_ADC0_OFFSET2V5_SHIFT)
262 #if defined( _ADC_CAL_SINGLEOFFSETINV_MASK )
263  newCal |= ((DEVINFO->ADC0CAL0 & _DEVINFO_ADC0CAL0_NEGSEOFFSET2V5_MASK)
264  >> _DEVINFO_ADC0CAL0_NEGSEOFFSET2V5_SHIFT)
265  << _ADC_CAL_SINGLEOFFSETINV_SHIFT;
266 #endif
267  break;
268 
269  case adcRefVDD:
270  newCal |= ((DEVINFO->ADC0CAL1 & DEVINFO_ADC0_GAINVDD_MASK)
271  >> DEVINFO_ADC0_GAINVDD_SHIFT)
273  newCal |= ((DEVINFO->ADC0CAL1 & DEVINFO_ADC0_OFFSETVDD_MASK)
274  >> DEVINFO_ADC0_OFFSETVDD_SHIFT)
276 #if defined( _ADC_CAL_SINGLEOFFSETINV_MASK )
277  newCal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_NEGSEOFFSETVDD_MASK)
278  >> _DEVINFO_ADC0CAL1_NEGSEOFFSETVDD_SHIFT)
279  << _ADC_CAL_SINGLEOFFSETINV_SHIFT;
280 #endif
281  break;
282 
283  case adcRef5VDIFF:
284  newCal |= ((DEVINFO->ADC0CAL1 & DEVINFO_ADC0_GAIN5VDIFF_MASK)
285  >> DEVINFO_ADC0_GAIN5VDIFF_SHIFT)
287  newCal |= ((DEVINFO->ADC0CAL1 & DEVINFO_ADC0_OFFSET5VDIFF_MASK)
288  >> DEVINFO_ADC0_OFFSET5VDIFF_SHIFT)
290 #if defined( _ADC_CAL_SINGLEOFFSETINV_MASK )
291  newCal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_NEGSEOFFSET5VDIFF_MASK)
292  >> _DEVINFO_ADC0CAL1_NEGSEOFFSET5VDIFF_SHIFT)
293  << _ADC_CAL_SINGLEOFFSETINV_SHIFT;
294 #endif
295  break;
296 
297  case adcRef2xVDD:
298  /* There is no gain calibration for this reference */
299  newCal |= ((DEVINFO->ADC0CAL2 & DEVINFO_ADC0_OFFSET2XVDD_MASK)
300  >> DEVINFO_ADC0_OFFSET2XVDD_SHIFT)
302 #if defined( _ADC_CAL_SINGLEOFFSETINV_MASK )
303  newCal |= ((DEVINFO->ADC0CAL2 & _DEVINFO_ADC0CAL2_NEGSEOFFSET2XVDD_MASK)
304  >> _DEVINFO_ADC0CAL2_NEGSEOFFSET2XVDD_SHIFT)
305  << _ADC_CAL_SINGLEOFFSETINV_SHIFT;
306 #endif
307  break;
308 
309 #if defined( _ADC_SINGLECTRLX_VREFSEL_VDDXWATT )
310  case adcRefVddxAtt:
311  newCal |= ((DEVINFO->ADC0CAL1 & DEVINFO_ADC0_GAINVDD_MASK)
312  >> DEVINFO_ADC0_GAINVDD_SHIFT)
314  newCal |= ((DEVINFO->ADC0CAL1 & DEVINFO_ADC0_OFFSETVDD_MASK)
315  >> DEVINFO_ADC0_OFFSETVDD_SHIFT)
317  newCal |= ((DEVINFO->ADC0CAL1 & _DEVINFO_ADC0CAL1_NEGSEOFFSETVDD_MASK)
318  >> _DEVINFO_ADC0CAL1_NEGSEOFFSETVDD_SHIFT)
319  << _ADC_CAL_SINGLEOFFSETINV_SHIFT;
320  break;
321 #endif
322 
323  /* For external references, the calibration must be determined for the
324  specific application and set by the user. Calibration data is also not
325  available for the internal references adcRefVBGR, adcRefVEntropy and
326  adcRefVBGRlow. */
327  default:
328  newCal = 0;
329  break;
330  }
331 
332  adc->CAL = calReg | (newCal << shift);
333 }
334 
337 /*******************************************************************************
338  ************************** GLOBAL FUNCTIONS *******************************
339  ******************************************************************************/
340 
341 /***************************************************************************/
363 void ADC_Init(ADC_TypeDef *adc, const ADC_Init_TypeDef *init)
364 {
365  uint32_t tmp;
366 
367  EFM_ASSERT(ADC_REF_VALID(adc));
368 
369  /* Make sure conversion is not in progress */
371 
372  tmp = ((uint32_t)(init->ovsRateSel) << _ADC_CTRL_OVSRSEL_SHIFT)
373  | (((uint32_t)(init->timebase) << _ADC_CTRL_TIMEBASE_SHIFT)
375  | (((uint32_t)(init->prescale) << _ADC_CTRL_PRESC_SHIFT)
377 #if defined ( _ADC_CTRL_LPFMODE_MASK )
378  | ((uint32_t)(init->lpfMode) << _ADC_CTRL_LPFMODE_SHIFT)
379 #endif
380  | ((uint32_t)(init->warmUpMode) << _ADC_CTRL_WARMUPMODE_SHIFT);
381 
382  if (init->tailgate)
383  {
384  tmp |= ADC_CTRL_TAILGATE;
385  }
386  adc->CTRL = tmp;
387 
388  /* Set ADC EM2 clock configuration */
389 #if defined( _ADC_CTRL_ADCCLKMODE_MASK )
390  BUS_RegMaskedWrite(&ADC0->CTRL,
391  _ADC_CTRL_ADCCLKMODE_MASK | _ADC_CTRL_ASYNCCLKEN_MASK,
392  init->em2ClockConfig << _ADC_CTRL_ASYNCCLKEN_SHIFT);
393 #endif
394 
395 #if defined( _SILICON_LABS_32B_PLATFORM_2 )
396  /* Fix for errata ADC_EXXX */
397  ADC_IntClear(adc, ADC_IFC_SCANUF);
398 #endif
399 }
400 
401 
402 #if defined( _ADC_SCANINPUTSEL_MASK )
403 /***************************************************************************/
410 void ADC_ScanInputClear(ADC_InitScan_TypeDef *scanInit)
411 {
412  /* Clear input configuration */
413 
414  /* Select none */
415  scanInit->scanInputConfig.scanInputSel = 0xFFFFFFFF;
416  scanInit->scanInputConfig.scanInputEn = 0;
417 
418  /* Default alternative negative inputs */
419  scanInit->scanInputConfig.scanNegSel = _ADC_SCANNEGSEL_RESETVALUE;
420 }
421 
422 
423 /***************************************************************************/
445 uint32_t ADC_ScanSingleEndedInputAdd(ADC_InitScan_TypeDef *scanInit,
446  ADC_ScanInputGroup_TypeDef inputGroup,
447  ADC_PosSel_TypeDef singleEndedSel)
448 {
449  uint32_t currentSel;
450  uint32_t newSel;
451  uint32_t scanId;
452 
453  scanInit->diff = false;
454 
455  /* Check for unsupported APORTs */
456  EFM_ASSERT((singleEndedSel <= adcPosSelAPORT0YCH0) || (singleEndedSel >= adcPosSelAPORT0YCH15));
457 
458  /* Decode the input group select by shifting right by 3 */
459  newSel = singleEndedSel >> 3;
460 
461  currentSel = (scanInit->scanInputConfig.scanInputSel >> (inputGroup * 8)) & 0xFF;
462 
463  /* If none selected */
464  if (currentSel == 0xFF)
465  {
466  scanInit->scanInputConfig.scanInputSel &= ~(0xFF << (inputGroup * 8));
467  scanInit->scanInputConfig.scanInputSel |= (newSel << (inputGroup * 8));
468  }
469  else if (currentSel == newSel)
470  {
471  /* Ok, but do nothing. */
472  }
473  else
474  {
475  /* Invalid channel range. A range is already selected for this group. */
476  EFM_ASSERT(false);
477  }
478 
479  /* Update and return scan input enable mask (SCANMASK) */
480  scanId = (inputGroup * 8) + (singleEndedSel & 0x7);
481  EFM_ASSERT(scanId < 32);
482  scanInit->scanInputConfig.scanInputEn |= 0x1 << scanId;
483  return scanId;
484 }
485 
486 
487 /***************************************************************************/
517 uint32_t ADC_ScanDifferentialInputAdd(ADC_InitScan_TypeDef *scanInit,
518  ADC_ScanInputGroup_TypeDef inputGroup,
519  ADC_PosSel_TypeDef posSel,
520  ADC_ScanNegInput_TypeDef negInput)
521 {
522  uint32_t negInputRegMask = 0;
523  uint32_t negInputRegShift = 0;
524  uint32_t negInputRegVal = 0;
525  uint32_t scanId = 0;
526 
527  /* Do a single ended init, then update for differential scan. */
528  scanId = ADC_ScanSingleEndedInputAdd(scanInit, inputGroup, posSel);
529 
530  /* Reset to differential mode */
531  scanInit->diff = true;
532 
533  /* Set negative ADC input, unless the default is selected. */
534  if (negInput != adcScanNegInputDefault)
535  {
536  if (scanId == 0)
537  {
538  negInputRegMask = _ADC_SCANNEGSEL_INPUT0NEGSEL_MASK;
539  negInputRegShift = _ADC_SCANNEGSEL_INPUT0NEGSEL_SHIFT;
540  EFM_ASSERT(inputGroup == 0);
541  }
542  else if (scanId == 2)
543  {
544  negInputRegMask = _ADC_SCANNEGSEL_INPUT2NEGSEL_MASK;
545  negInputRegShift = _ADC_SCANNEGSEL_INPUT2NEGSEL_SHIFT;
546  EFM_ASSERT(inputGroup == 0);
547  }
548  else if (scanId == 4)
549  {
550  negInputRegMask = _ADC_SCANNEGSEL_INPUT4NEGSEL_MASK;
551  negInputRegShift = _ADC_SCANNEGSEL_INPUT4NEGSEL_SHIFT;
552  EFM_ASSERT(inputGroup == 0);
553  }
554  else if (scanId == 6)
555  {
556  negInputRegMask = _ADC_SCANNEGSEL_INPUT6NEGSEL_MASK;
557  negInputRegShift = _ADC_SCANNEGSEL_INPUT6NEGSEL_SHIFT;
558  EFM_ASSERT(inputGroup == 0);
559  }
560  else if (scanId == 9)
561  {
562  negInputRegMask = _ADC_SCANNEGSEL_INPUT9NEGSEL_MASK;
563  negInputRegShift = _ADC_SCANNEGSEL_INPUT9NEGSEL_SHIFT;
564  EFM_ASSERT(inputGroup == 1);
565  }
566  else if (scanId == 11)
567  {
568  negInputRegMask = _ADC_SCANNEGSEL_INPUT11NEGSEL_MASK;
569  negInputRegShift = _ADC_SCANNEGSEL_INPUT11NEGSEL_SHIFT;
570  EFM_ASSERT(inputGroup == 1);
571  }
572  else if (scanId == 13)
573  {
574  negInputRegMask = _ADC_SCANNEGSEL_INPUT13NEGSEL_MASK;
575  negInputRegShift = _ADC_SCANNEGSEL_INPUT13NEGSEL_SHIFT;
576  EFM_ASSERT(inputGroup == 1);
577  }
578  else if (scanId == 15)
579  {
580  negInputRegMask = _ADC_SCANNEGSEL_INPUT15NEGSEL_MASK;
581  negInputRegShift = _ADC_SCANNEGSEL_INPUT15NEGSEL_SHIFT;
582  EFM_ASSERT(inputGroup == 1);
583  }
584  else
585  {
586  /* There is not negative input option for this positive input (negInput is posInput + 1). */
587  EFM_ASSERT(false);
588  }
589 
590  /* Find ADC_SCANNEGSEL_CHxNSEL value for positive input 0, 2, 4 and 6 */
591  if (inputGroup == 0)
592  {
593  switch (negInput)
594  {
595  case adcScanNegInput1:
596  negInputRegVal = _ADC_SCANNEGSEL_INPUT0NEGSEL_INPUT1;
597  break;
598 
599  case adcScanNegInput3:
600  negInputRegVal = _ADC_SCANNEGSEL_INPUT0NEGSEL_INPUT3;
601  break;
602 
603  case adcScanNegInput5:
604  negInputRegVal = _ADC_SCANNEGSEL_INPUT0NEGSEL_INPUT5;
605  break;
606 
607  case adcScanNegInput7:
608  negInputRegVal = _ADC_SCANNEGSEL_INPUT0NEGSEL_INPUT7;
609  break;
610 
611  default:
612  /* Invalid selection. Options are input 1, 3, 5 and 7. */
613  EFM_ASSERT(false);
614  break;
615  }
616  }
617  else if (inputGroup == 1)
618  {
619  /* Find ADC_SCANNEGSEL_CHxNSEL value for positive input 9, 11, 13 and 15 */
620  switch (negInput)
621  {
622  case adcScanNegInput8:
623  negInputRegVal = _ADC_SCANNEGSEL_INPUT9NEGSEL_INPUT8;
624  break;
625 
626  case adcScanNegInput10:
627  negInputRegVal = _ADC_SCANNEGSEL_INPUT9NEGSEL_INPUT10;
628  break;
629 
630  case adcScanNegInput12:
631  negInputRegVal = _ADC_SCANNEGSEL_INPUT9NEGSEL_INPUT12;
632  break;
633 
634  case adcScanNegInput14:
635  negInputRegVal = _ADC_SCANNEGSEL_INPUT9NEGSEL_INPUT14;
636  break;
637 
638  default:
639  /* Invalid selection. Options are input 8, 10, 12 and 14. */
640  EFM_ASSERT(false);
641  break;
642  }
643  }
644  else
645  {
646  /* No alternative negative input for input group > 1 */
647  EFM_ASSERT(false);
648  }
649 
650  /* Update config */
651  scanInit->scanInputConfig.scanNegSel &= ~negInputRegMask;
652  scanInit->scanInputConfig.scanNegSel |= negInputRegVal << negInputRegShift;
653  }
654  return scanId;
655 }
656 #endif
657 
658 
659 /***************************************************************************/
680 {
681  uint32_t tmp;
682 
683  EFM_ASSERT(ADC_REF_VALID(adc));
684 
685  /* Make sure scan sequence is not in progress */
686  adc->CMD = ADC_CMD_SCANSTOP;
687 
688  /* Load calibration data for selected reference */
689  ADC_LoadDevinfoCal(adc, init->reference, true);
690 
691  tmp = 0
692 #if defined ( _ADC_SCANCTRL_PRSSEL_MASK )
694 #endif
695  | (init->acqTime << _ADC_SCANCTRL_AT_SHIFT)
696 #if defined ( _ADC_SCANCTRL_INPUTMASK_MASK )
697  | init->input
698 #endif
699  | (init->resolution << _ADC_SCANCTRL_RES_SHIFT);
700 
701  if (init->prsEnable)
702  {
703  tmp |= ADC_SCANCTRL_PRSEN;
704  }
705 
706  if (init->leftAdjust)
707  {
708  tmp |= ADC_SCANCTRL_ADJ_LEFT;
709  }
710 
711 #if defined( _ADC_SCANCTRL_INPUTMASK_MASK )
712  if (init->diff)
713 #elif defined( _ADC_SCANINPUTSEL_MASK )
714  if (init->diff)
715 #endif
716  {
717  tmp |= ADC_SCANCTRL_DIFF;
718  }
719 
720  if (init->rep)
721  {
722 #if defined( _SILICON_LABS_32B_PLATFORM_2 )
723  /* Scan repeat mode does not work on platform 2 as described in errata ADC_EXXX. */
724  EFM_ASSERT(false);
725 #endif
726  tmp |= ADC_SCANCTRL_REP;
727  }
728 
729  /* Set scan reference. Check if reference configuraion is extended to SCANCTRLX. */
730 #if defined ( _ADC_SCANCTRLX_VREFSEL_MASK )
731  if (init->reference & ADC_CTRLX_VREFSEL_REG)
732  {
733  /* Select extension register */
734  tmp |= ADC_SCANCTRL_REF_CONF;
735  }
736  else
737  {
738  tmp |= init->reference << _ADC_SCANCTRL_REF_SHIFT;
739  }
740 #else
741  tmp |= init->reference << _ADC_SCANCTRL_REF_SHIFT;
742 #endif
743 
744 #if defined( _ADC_SCANCTRL_INPUTMASK_MASK )
745  tmp |= init->input;
746 #endif
747 
748  adc->SCANCTRL = tmp;
749 
750  /* Update SINGLECTRLX for reference select and PRS select */
751 #if defined ( _ADC_SCANCTRLX_MASK )
752  tmp = adc->SCANCTRLX & ~(_ADC_SCANCTRLX_VREFSEL_MASK
753  | _ADC_SCANCTRLX_PRSSEL_MASK
754  | _ADC_SCANCTRLX_FIFOOFACT_MASK);
755  if (init->reference & ADC_CTRLX_VREFSEL_REG)
756  {
757  tmp |= (init->reference & ~ADC_CTRLX_VREFSEL_REG) << _ADC_SCANCTRLX_VREFSEL_SHIFT;
758  }
759 
760  tmp |= init->prsSel << _ADC_SCANCTRLX_PRSSEL_SHIFT;
761 
762  if (init->fifoOverwrite)
763  {
764  tmp |= ADC_SCANCTRLX_FIFOOFACT_OVERWRITE;
765  }
766 
767  adc->SCANCTRLX = tmp;
768 #endif
769 
770 #if defined( _ADC_CTRL_SCANDMAWU_MASK )
771  BUS_RegBitWrite(&adc->CTRL, _ADC_CTRL_SCANDMAWU_SHIFT, init->scanDmaEm2Wu);
772 #endif
773 
774  /* Write scan input configuration */
775 #if defined( _ADC_SCANINPUTSEL_MASK )
776  adc->SCANINPUTSEL = init->scanInputConfig.scanInputSel;
777  adc->SCANMASK = init->scanInputConfig.scanInputEn;
778  adc->SCANNEGSEL = init->scanInputConfig.scanNegSel;
779 #endif
780 
781  /* Assert for any APORT bus conflicts programming errors */
782 #if defined( _ADC_BUSCONFLICT_MASK )
783  tmp = adc->BUSREQ;
784  EFM_ASSERT(!(tmp & adc->BUSCONFLICT));
785  EFM_ASSERT(!(adc->STATUS & _ADC_STATUS_PROGERR_MASK));
786 #endif
787 }
788 
789 
790 /***************************************************************************/
811 {
812  uint32_t tmp;
813 
814  EFM_ASSERT(ADC_REF_VALID(adc));
815 
816  /* Make sure single conversion is not in progress */
817  adc->CMD = ADC_CMD_SINGLESTOP;
818 
819  /* Load calibration data for selected reference */
820  ADC_LoadDevinfoCal(adc, init->reference, false);
821 
822  tmp = 0
823 #if defined( _ADC_SINGLECTRL_PRSSEL_MASK )
825 #endif
826  | (init->acqTime << _ADC_SINGLECTRL_AT_SHIFT)
827 #if defined( _ADC_SINGLECTRL_INPUTSEL_MASK )
829 #endif
830 #if defined( _ADC_SINGLECTRL_POSSEL_MASK )
831  | (init->posSel << _ADC_SINGLECTRL_POSSEL_SHIFT)
832 #endif
833 #if defined( _ADC_SINGLECTRL_NEGSEL_MASK )
834  | (init->negSel << _ADC_SINGLECTRL_NEGSEL_SHIFT)
835 #endif
836  | ((uint32_t)(init->resolution) << _ADC_SINGLECTRL_RES_SHIFT);
837 
838  if (init->prsEnable)
839  {
840  tmp |= ADC_SINGLECTRL_PRSEN;
841  }
842 
843  if (init->leftAdjust)
844  {
846  }
847 
848  if (init->diff)
849  {
850  tmp |= ADC_SINGLECTRL_DIFF;
851  }
852 
853  if (init->rep)
854  {
855  tmp |= ADC_SINGLECTRL_REP;
856  }
857 
858  /* Set single reference. Check if reference configuraion is extended to SINGLECTRLX. */
859 #if defined ( _ADC_SINGLECTRLX_MASK )
860  if (init->reference & ADC_CTRLX_VREFSEL_REG)
861  {
862  /* Select extension register */
863  tmp |= ADC_SINGLECTRL_REF_CONF;
864  }
865  else
866  {
867  tmp |= (init->reference << _ADC_SINGLECTRL_REF_SHIFT);
868  }
869 #else
870  tmp |= (init->reference << _ADC_SINGLECTRL_REF_SHIFT);
871 #endif
872  adc->SINGLECTRL = tmp;
873 
874  /* Update SINGLECTRLX for reference select and PRS select */
875 #if defined ( _ADC_SINGLECTRLX_VREFSEL_MASK )
876  tmp = adc->SINGLECTRLX & (_ADC_SINGLECTRLX_VREFSEL_MASK
877  | _ADC_SINGLECTRLX_PRSSEL_MASK
878  | _ADC_SINGLECTRLX_FIFOOFACT_MASK);
879  if (init->reference & ADC_CTRLX_VREFSEL_REG)
880  {
881  tmp |= ((init->reference & ~ADC_CTRLX_VREFSEL_REG) << _ADC_SINGLECTRLX_VREFSEL_SHIFT);
882  }
883 
884  tmp |= ((init->prsSel << _ADC_SINGLECTRLX_PRSSEL_SHIFT));
885 
886  if (init->fifoOverwrite)
887  {
888  tmp |= ADC_SINGLECTRLX_FIFOOFACT_OVERWRITE;
889  }
890 
891  adc->SINGLECTRLX = tmp;
892 #endif
893 
894  /* Set DMA availability in EM2 */
895 #if defined( _ADC_CTRL_SINGLEDMAWU_MASK )
896  BUS_RegBitWrite(&ADC0->CTRL, _ADC_CTRL_SINGLEDMAWU_SHIFT, init->singleDmaEm2Wu);
897 #endif
898 
899  /* Assert for any APORT bus conflicts programming errors */
900 #if defined( _ADC_BUSCONFLICT_MASK )
901  tmp = adc->BUSREQ;
902  EFM_ASSERT(!(tmp & adc->BUSCONFLICT));
903  EFM_ASSERT(!(adc->STATUS & _ADC_STATUS_PROGERR_MASK));
904 #endif
905 }
906 
907 
908 #if defined( _ADC_SCANDATAX_MASK )
909 /***************************************************************************/
926 uint32_t ADC_DataIdScanGet(ADC_TypeDef *adc, uint32_t *scanId)
927 {
928  uint32_t scanData;
929 
930  /* Pop data FIFO with scan ID */
931  scanData = adc->SCANDATAX;
932  *scanId = (scanData & _ADC_SCANDATAX_SCANINPUTID_MASK) >> _ADC_SCANDATAX_SCANINPUTID_SHIFT;
933  return (scanData & _ADC_SCANDATAX_DATA_MASK) >> _ADC_SCANDATAX_DATA_SHIFT;
934 }
935 #endif
936 
937 
938 /***************************************************************************/
955 uint8_t ADC_PrescaleCalc(uint32_t adcFreq, uint32_t hfperFreq)
956 {
957  uint32_t ret;
958 
959  /* Make sure selected ADC clock is within valid range */
960  if (adcFreq > ADC_MAX_CLOCK)
961  {
962  adcFreq = ADC_MAX_CLOCK;
963  }
964  else if (adcFreq < ADC_MIN_CLOCK)
965  {
966  adcFreq = ADC_MIN_CLOCK;
967  }
968 
969  /* Use current HFPER frequency? */
970  if (!hfperFreq)
971  {
972  hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
973  }
974 
975  ret = (hfperFreq + adcFreq - 1) / adcFreq;
976  if (ret)
977  {
978  ret--;
979  }
980 
981  return (uint8_t)ret;
982 }
983 
984 
985 /***************************************************************************/
997 {
998  /* Stop conversions, before resetting other registers. */
1001 #if defined( _ADC_SINGLECTRLX_MASK )
1002  adc->SINGLECTRLX = _ADC_SINGLECTRLX_RESETVALUE;
1003 #endif
1005 #if defined( _ADC_SCANCTRLX_MASK )
1006  adc->SCANCTRLX = _ADC_SCANCTRLX_RESETVALUE;
1007 #endif
1008  adc->CTRL = _ADC_CTRL_RESETVALUE;
1009  adc->IEN = _ADC_IEN_RESETVALUE;
1010  adc->IFC = _ADC_IFC_MASK;
1012 #if defined( _ADC_SCANMASK_MASK )
1013  adc->SCANMASK = _ADC_SCANMASK_RESETVALUE;
1014 #endif
1015 #if defined( _ADC_SCANINPUTSEL_MASK )
1016  adc->SCANINPUTSEL = _ADC_SCANINPUTSEL_RESETVALUE;
1017 #endif
1018 #if defined( _ADC_SCANNEGSEL_MASK )
1019  adc->SCANNEGSEL = _ADC_SCANNEGSEL_RESETVALUE;
1020 #endif
1021 
1022  /* Clear data FIFOs */
1023 #if defined( _ADC_SINGLEFIFOCLEAR_MASK )
1024  adc->SINGLEFIFOCLEAR |= ADC_SINGLEFIFOCLEAR_SINGLEFIFOCLEAR;
1025  adc->SCANFIFOCLEAR |= ADC_SCANFIFOCLEAR_SCANFIFOCLEAR;
1026 #endif
1027 
1028  /* Load calibration values for the 1V25 internal reference. */
1029  ADC_LoadDevinfoCal(adc, adcRef1V25, false);
1030  ADC_LoadDevinfoCal(adc, adcRef1V25, true);
1031 
1032 #if defined( _ADC_SCANINPUTSEL_MASK )
1033  /* Do not reset route register, setting should be done independently */
1034 #endif
1035 }
1036 
1037 
1038 /***************************************************************************/
1048 uint8_t ADC_TimebaseCalc(uint32_t hfperFreq)
1049 {
1050  if (!hfperFreq)
1051  {
1052  hfperFreq = CMU_ClockFreqGet(cmuClock_HFPER);
1053 
1054  /* Just in case, make sure we get non-zero freq for below calculation */
1055  if (!hfperFreq)
1056  {
1057  hfperFreq = 1;
1058  }
1059  }
1060 #if defined( _EFM32_GIANT_FAMILY ) || defined( _EFM32_WONDER_FAMILY )
1061  /* Handle errata on Giant Gecko, max TIMEBASE is 5 bits wide or max 0x1F */
1062  /* cycles. This will give a warmp up time of e.g. 0.645us, not the */
1063  /* required 1us when operating at 48MHz. One must also increase acqTime */
1064  /* to compensate for the missing clock cycles, adding up to 1us in total.*/
1065  /* See reference manual for details. */
1066  if ( hfperFreq > 32000000 )
1067  {
1068  hfperFreq = 32000000;
1069  }
1070 #endif
1071  /* Determine number of HFPERCLK cycle >= 1us */
1072  hfperFreq += 999999;
1073  hfperFreq /= 1000000;
1074 
1075  /* Return timebase value (N+1 format) */
1076  return (uint8_t)(hfperFreq - 1);
1077 }
1078 
1079 
1082 #endif /* defined(ADC_COUNT) && (ADC_COUNT > 0) */
#define _ADC_SINGLECTRL_REF_SHIFT
Definition: ezr32wg_adc.h:297
Clock management unit (CMU) API.
#define _ADC_IFC_MASK
Definition: ezr32wg_adc.h:581
#define _ADC_CTRL_PRESC_SHIFT
Definition: ezr32wg_adc.h:97
#define ADC0
#define _ADC_CTRL_RESETVALUE
Definition: ezr32wg_adc.h:68
#define _ADC_CAL_SCANOFFSET_MASK
Definition: ezr32wg_adc.h:647
Emlib peripheral API "assert" implementation.
#define _ADC_SCANCTRL_RESETVALUE
Definition: ezr32wg_adc.h:372
uint32_t input
Definition: em_adc.h:884
#define ADC_CTRL_TAILGATE
Definition: ezr32wg_adc.h:82
#define _ADC_SINGLECTRL_RESETVALUE
Definition: ezr32wg_adc.h:220
void ADC_Reset(ADC_TypeDef *adc)
Reset ADC to same state as after a HW reset.
Definition: em_adc.c:996
uint8_t timebase
Definition: em_adc.h:794
__IO uint32_t BIASPROG
Definition: ezr32wg_adc.h:59
#define _ADC_CTRL_LPFMODE_MASK
Definition: ezr32wg_adc.h:88
ADC_AcqTime_TypeDef acqTime
Definition: em_adc.h:965
__STATIC_INLINE void ADC_IntClear(ADC_TypeDef *adc, uint32_t flags)
Clear one or more pending ADC interrupts.
Definition: em_adc.h:1166
__IO uint32_t SINGLECTRL
Definition: ezr32wg_adc.h:46
#define _ADC_CTRL_TIMEBASE_MASK
Definition: ezr32wg_adc.h:104
#define _ADC_CAL_SINGLEOFFSET_MASK
Definition: ezr32wg_adc.h:639
#define ADC_SINGLECTRL_DIFF
Definition: ezr32wg_adc.h:227
ADC_SingleInput_TypeDef input
Definition: em_adc.h:981
#define _ADC_CAL_SINGLEGAIN_SHIFT
Definition: ezr32wg_adc.h:642
ADC_PRSSEL_TypeDef prsSel
Definition: em_adc.h:962
#define _ADC_CTRL_PRESC_MASK
Definition: ezr32wg_adc.h:98
#define DEVINFO
#define ADC_SCANCTRL_ADJ_LEFT
Definition: ezr32wg_adc.h:392
__IO uint32_t CMD
Definition: ezr32wg_adc.h:44
#define _ADC_CAL_SINGLEOFFSET_SHIFT
Definition: ezr32wg_adc.h:638
#define ADC_SCANCTRL_DIFF
Definition: ezr32wg_adc.h:379
#define ADC_CMD_SINGLESTOP
Definition: ezr32wg_adc.h:144
void ADC_Init(ADC_TypeDef *adc, const ADC_Init_TypeDef *init)
Initialize ADC.
Definition: em_adc.c:363
#define ADC_SCANCTRL_REP
Definition: ezr32wg_adc.h:374
ADC_PRSSEL_TypeDef prsSel
Definition: em_adc.h:863
__IO uint32_t SCANCTRL
Definition: ezr32wg_adc.h:47
#define _ADC_SINGLECTRL_RES_SHIFT
Definition: ezr32wg_adc.h:241
#define _ADC_SINGLECTRL_INPUTSEL_SHIFT
Definition: ezr32wg_adc.h:253
#define _ADC_SINGLECTRL_AT_SHIFT
Definition: ezr32wg_adc.h:315
#define ADC_SCANCTRL_PRSEN
Definition: ezr32wg_adc.h:473
#define _ADC_SCANCTRL_RES_SHIFT
Definition: ezr32wg_adc.h:393
#define _ADC_CAL_SCANOFFSET_SHIFT
Definition: ezr32wg_adc.h:646
uint8_t ADC_TimebaseCalc(uint32_t hfperFreq)
Calculate timebase value in order to get a timebase providing at least 1us.
Definition: em_adc.c:1048
#define _ADC_SCANCTRL_PRSSEL_SHIFT
Definition: ezr32wg_adc.h:478
#define ADC_SINGLECTRL_PRSEN
Definition: ezr32wg_adc.h:337
ADC_Res_TypeDef resolution
Definition: em_adc.h:974
uint8_t prescale
Definition: em_adc.h:797
void ADC_InitSingle(ADC_TypeDef *adc, const ADC_InitSingle_TypeDef *init)
Initialize single ADC sample conversion.
Definition: em_adc.c:810
__I uint32_t STATUS
Definition: ezr32wg_adc.h:45
__IO uint32_t IFC
Definition: ezr32wg_adc.h:51
#define ADC_SINGLECTRL_REP
Definition: ezr32wg_adc.h:222
#define _ADC_CAL_SINGLEGAIN_MASK
Definition: ezr32wg_adc.h:643
__IO uint32_t IEN
Definition: ezr32wg_adc.h:48
#define _ADC_CTRL_TIMEBASE_SHIFT
Definition: ezr32wg_adc.h:103
#define ADC_CMD_SCANSTOP
Definition: ezr32wg_adc.h:154
__STATIC_INLINE void BUS_RegMaskedWrite(volatile uint32_t *addr, uint32_t mask, uint32_t val)
Perform peripheral register masked clear and value write.
Definition: em_bus.h:283
#define _ADC_SCANCTRL_AT_SHIFT
Definition: ezr32wg_adc.h:451
uint8_t ADC_PrescaleCalc(uint32_t adcFreq, uint32_t hfperFreq)
Calculate prescaler value used to determine ADC clock.
Definition: em_adc.c:955
ADC_LPFilter_TypeDef lpfMode
Definition: em_adc.h:781
void ADC_InitScan(ADC_TypeDef *adc, const ADC_InitScan_TypeDef *init)
Initialize ADC scan sequence.
Definition: em_adc.c:679
Analog to Digital Converter (ADC) peripheral API.
__IO uint32_t CTRL
Definition: ezr32wg_adc.h:43
__STATIC_INLINE void BUS_RegBitWrite(volatile uint32_t *addr, unsigned int bit, unsigned int val)
Perform a single-bit write operation on a peripheral register.
Definition: em_bus.h:146
ADC_Ref_TypeDef reference
Definition: em_adc.h:971
ADC_OvsRateSel_TypeDef ovsRateSel
Definition: em_adc.h:777
#define _ADC_IEN_RESETVALUE
Definition: ezr32wg_adc.h:508
uint32_t CMU_ClockFreqGet(CMU_Clock_TypeDef clock)
Get clock frequency for a clock point.
Definition: em_cmu.c:1482
__IO uint32_t CAL
Definition: ezr32wg_adc.h:56
ADC_Ref_TypeDef reference
Definition: em_adc.h:872
#define _ADC_CTRL_WARMUPMODE_SHIFT
Definition: ezr32wg_adc.h:70
#define _ADC_SINGLECTRL_PRSSEL_SHIFT
Definition: ezr32wg_adc.h:342
#define _ADC_CTRL_LPFMODE_SHIFT
Definition: ezr32wg_adc.h:87
ADC_Res_TypeDef resolution
Definition: em_adc.h:875
ADC_Ref_TypeDef
Definition: em_adc.h:189
ADC_AcqTime_TypeDef acqTime
Definition: em_adc.h:866
ADC_Warmup_TypeDef warmUpMode
Definition: em_adc.h:785
#define _ADC_SCANCTRL_REF_SHIFT
Definition: ezr32wg_adc.h:433
#define ADC_SINGLECTRL_ADJ_LEFT
Definition: ezr32wg_adc.h:240
#define _ADC_CAL_SCANGAIN_MASK
Definition: ezr32wg_adc.h:651
#define _ADC_CTRL_OVSRSEL_SHIFT
Definition: ezr32wg_adc.h:107
#define _ADC_BIASPROG_RESETVALUE
Definition: ezr32wg_adc.h:656