EFM32 Happy Gecko Software Documentation  efm32hg-doc-5.1.2
em_idac.c
Go to the documentation of this file.
1 /***************************************************************************/
33 #include "em_idac.h"
34 #if defined(IDAC_COUNT) && (IDAC_COUNT > 0)
35 #include "em_cmu.h"
36 #include "em_assert.h"
37 #include "em_bus.h"
38 
39 /***************************************************************************/
44 /***************************************************************************/
50 /* Fix for errata IDAC_E101 - IDAC output current degradation */
51 #if defined(_SILICON_LABS_32B_SERIES_0) \
52  && (defined(_EFM32_ZERO_FAMILY) || defined(_EFM32_HAPPY_FAMILY))
53 #define ERRATA_FIX_IDAC_E101_EN
54 #endif
55 
57 /*******************************************************************************
58  ************************** GLOBAL FUNCTIONS *******************************
59  ******************************************************************************/
60 
61 
62 /***************************************************************************/
79 void IDAC_Init(IDAC_TypeDef *idac, const IDAC_Init_TypeDef *init)
80 {
81  uint32_t tmp;
82 
83  EFM_ASSERT(IDAC_REF_VALID(idac));
84 
85  tmp = (uint32_t)(init->prsSel);
86 
87  tmp |= init->outMode;
88 
89  if (init->enable)
90  {
91  tmp |= IDAC_CTRL_EN;
92  }
93  if (init->prsEnable)
94  {
95 #if defined(_IDAC_CTRL_OUTENPRS_MASK)
96  tmp |= IDAC_CTRL_OUTENPRS;
97 #else
98  tmp |= IDAC_CTRL_APORTOUTENPRS;
99 #endif
100  }
101  if (init->sinkEnable)
102  {
103  tmp |= IDAC_CTRL_CURSINK;
104  }
105 
106  idac->CTRL = tmp;
107 }
108 
109 
110 /***************************************************************************/
120 void IDAC_Enable(IDAC_TypeDef *idac, bool enable)
121 {
122  EFM_ASSERT(IDAC_REF_VALID(idac));
123  BUS_RegBitWrite(&idac->CTRL, _IDAC_CTRL_EN_SHIFT, enable);
124 }
125 
126 
127 /***************************************************************************/
135 {
136  EFM_ASSERT(IDAC_REF_VALID(idac));
137 
138 #if defined(ERRATA_FIX_IDAC_E101_EN)
139  /* Fix for errata IDAC_E101 - IDAC output current degradation:
140  Instead of disabling it we will put it in it's lowest power state (50 nA)
141  to avoid degradation over time */
142 
143  /* Make sure IDAC is enabled with disabled output */
145 
146  /* Set lowest current (50 nA) */
149 
150  /* Enable duty-cycling for all energy modes */
152 #else
153  idac->CTRL = _IDAC_CTRL_RESETVALUE;
156 #endif
157 #if defined ( _IDAC_CAL_MASK )
158  idac->CAL = _IDAC_CAL_RESETVALUE;
159 #endif
160 }
161 
162 
163 /***************************************************************************/
174 {
175  EFM_ASSERT(IDAC_REF_VALID(idac));
177 }
178 
179 
180 /***************************************************************************/
197 {
198  uint32_t tmp;
199 #if defined( _IDAC_CURPROG_TUNING_MASK )
200  uint32_t diCal0;
201  uint32_t diCal1;
202 #endif
203 
204  EFM_ASSERT(IDAC_REF_VALID(idac));
205  EFM_ASSERT(((uint32_t)range >> _IDAC_CURPROG_RANGESEL_SHIFT)
207 
208 #if defined ( _IDAC_CAL_MASK )
209 
210  /* Load proper calibration data depending on selected range */
211  switch ((IDAC_Range_TypeDef)range)
212  {
213  case idacCurrentRange0:
214  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE0_MASK)
216  break;
217  case idacCurrentRange1:
218  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE1_MASK)
220  break;
221  case idacCurrentRange2:
222  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE2_MASK)
224  break;
225  case idacCurrentRange3:
226  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE3_MASK)
228  break;
229  }
230 
231  tmp = idac->CURPROG & ~_IDAC_CURPROG_RANGESEL_MASK;
232  tmp |= (uint32_t)range;
233 
234 #elif defined( _IDAC_CURPROG_TUNING_MASK )
235 
236  /* Load calibration data depending on selected range and sink/source mode */
237  /* TUNING (calibration) field in CURPROG register. */
238  EFM_ASSERT(idac == IDAC0);
239  diCal0 = DEVINFO->IDAC0CAL0;
240  diCal1 = DEVINFO->IDAC0CAL1;
241 
242  tmp = idac->CURPROG & ~(_IDAC_CURPROG_TUNING_MASK
244  if (idac->CTRL & IDAC_CTRL_CURSINK)
245  {
246  switch (range)
247  {
248  case idacCurrentRange0:
249  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE0TUNING_MASK)
250  >> _DEVINFO_IDAC0CAL1_SINKRANGE0TUNING_SHIFT)
251  << _IDAC_CURPROG_TUNING_SHIFT;
252  break;
253 
254  case idacCurrentRange1:
255  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE1TUNING_MASK)
256  >> _DEVINFO_IDAC0CAL1_SINKRANGE1TUNING_SHIFT)
257  << _IDAC_CURPROG_TUNING_SHIFT;
258  break;
259 
260  case idacCurrentRange2:
261  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE2TUNING_MASK)
262  >> _DEVINFO_IDAC0CAL1_SINKRANGE2TUNING_SHIFT)
263  << _IDAC_CURPROG_TUNING_SHIFT;
264  break;
265 
266  case idacCurrentRange3:
267  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE3TUNING_MASK)
268  >> _DEVINFO_IDAC0CAL1_SINKRANGE3TUNING_SHIFT)
269  << _IDAC_CURPROG_TUNING_SHIFT;
270  break;
271  }
272  }
273  else
274  {
275  switch (range)
276  {
277  case idacCurrentRange0:
278  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE0TUNING_MASK)
279  >> _DEVINFO_IDAC0CAL0_SOURCERANGE0TUNING_SHIFT)
280  << _IDAC_CURPROG_TUNING_SHIFT;
281  break;
282 
283  case idacCurrentRange1:
284  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE1TUNING_MASK)
285  >> _DEVINFO_IDAC0CAL0_SOURCERANGE1TUNING_SHIFT)
286  << _IDAC_CURPROG_TUNING_SHIFT;
287  break;
288 
289  case idacCurrentRange2:
290  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE2TUNING_MASK)
291  >> _DEVINFO_IDAC0CAL0_SOURCERANGE2TUNING_SHIFT)
292  << _IDAC_CURPROG_TUNING_SHIFT;
293  break;
294 
295  case idacCurrentRange3:
296  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE3TUNING_MASK)
297  >> _DEVINFO_IDAC0CAL0_SOURCERANGE3TUNING_SHIFT)
298  << _IDAC_CURPROG_TUNING_SHIFT;
299  break;
300  }
301  }
302 
303  tmp |= (uint32_t)range;
304 
305 #else
306 #warning "IDAC calibration register definition unknown."
307 #endif
308 
309  idac->CURPROG = tmp;
310 }
311 
312 
313 /***************************************************************************/
323 void IDAC_StepSet(IDAC_TypeDef *idac, const uint32_t step)
324 {
325  uint32_t tmp;
326 
327  EFM_ASSERT(IDAC_REF_VALID(idac));
329 
330  tmp = idac->CURPROG & ~_IDAC_CURPROG_STEPSEL_MASK;
331  tmp |= step << _IDAC_CURPROG_STEPSEL_SHIFT;
332 
333  idac->CURPROG = tmp;
334 }
335 
336 
337 /***************************************************************************/
347 void IDAC_OutEnable(IDAC_TypeDef *idac, bool enable)
348 {
349  EFM_ASSERT(IDAC_REF_VALID(idac));
350 #if defined(_IDAC_CTRL_OUTEN_MASK)
352 #else
353  BUS_RegBitWrite(&idac->CTRL, _IDAC_CTRL_APORTOUTEN_SHIFT, enable);
354 #endif
355 }
356 
357 
361 #endif /* defined(IDAC_COUNT) && (IDAC_COUNT > 0) */
Clock management unit (CMU) API.
#define IDAC0
#define IDAC_CTRL_EN
Definition: efm32hg_idac.h:57
__IOM uint32_t CAL
Definition: efm32hg_idac.h:45
IDAC_PRSSEL_TypeDef prsSel
Definition: em_idac.h:191
#define _DEVINFO_IDAC0CAL0_RANGE2_SHIFT
Emlib peripheral API "assert" implementation.
#define _DEVINFO_IDAC0CAL0_RANGE1_SHIFT
#define _DEVINFO_IDAC0CAL0_RANGE2_MASK
RAM and peripheral bit-field set and clear API.
#define _DEVINFO_IDAC0CAL0_RANGE0_MASK
Current Digital to Analog Converter (IDAC) peripheral API.
__IOM uint32_t CTRL
Definition: efm32hg_idac.h:43
#define _DEVINFO_IDAC0CAL0_RANGE0_SHIFT
#define IDAC_CTRL_CURSINK
Definition: efm32hg_idac.h:62
#define _IDAC_CTRL_RESETVALUE
Definition: efm32hg_idac.h:55
__IOM uint32_t CURPROG
Definition: efm32hg_idac.h:44
#define _IDAC_DUTYCONFIG_RESETVALUE
Definition: efm32hg_idac.h:137
void IDAC_Enable(IDAC_TypeDef *idac, bool enable)
Enable/disable IDAC.
Definition: em_idac.c:120
#define DEVINFO
__IOM uint32_t DUTYCONFIG
Definition: efm32hg_idac.h:46
void IDAC_MinimalOutputTransitionMode(IDAC_TypeDef *idac, bool enable)
Enable/disable Minimal Output Transition mode.
Definition: em_idac.c:173
#define _IDAC_CAL_RESETVALUE
Definition: efm32hg_idac.h:129
#define _IDAC_CTRL_OUTEN_SHIFT
Definition: efm32hg_idac.h:73
#define _IDAC_CTRL_MINOUTTRANS_SHIFT
Definition: efm32hg_idac.h:68
void IDAC_RangeSet(IDAC_TypeDef *idac, const IDAC_Range_TypeDef range)
Set the current range of the IDAC output.
Definition: em_idac.c:196
#define _DEVINFO_IDAC0CAL0_RANGE3_SHIFT
#define _IDAC_CURPROG_RANGESEL_MASK
Definition: efm32hg_idac.h:112
void IDAC_Init(IDAC_TypeDef *idac, const IDAC_Init_TypeDef *init)
Initialize IDAC.
Definition: em_idac.c:79
#define _DEVINFO_IDAC0CAL0_RANGE1_MASK
IDAC_OutMode_TypeDef outMode
Definition: em_idac.h:178
void IDAC_StepSet(IDAC_TypeDef *idac, const uint32_t step)
Set the current step of the IDAC output.
Definition: em_idac.c:323
#define _IDAC_CURPROG_RESETVALUE
Definition: efm32hg_idac.h:109
#define _IDAC_CURPROG_STEPSEL_SHIFT
Definition: efm32hg_idac.h:123
#define IDAC_CTRL_OUTENPRS
Definition: efm32hg_idac.h:86
#define _IDAC_CTRL_EN_SHIFT
Definition: efm32hg_idac.h:58
#define IDAC_DUTYCONFIG_DUTYCYCLEEN
Definition: efm32hg_idac.h:139
#define _IDAC_CURPROG_STEPSEL_MASK
Definition: efm32hg_idac.h:124
void IDAC_Reset(IDAC_TypeDef *idac)
Reset IDAC to same state as after a HW reset.
Definition: em_idac.c:134
void IDAC_OutEnable(IDAC_TypeDef *idac, bool enable)
Enable/disable the IDAC OUT pin.
Definition: em_idac.c:347
#define _DEVINFO_IDAC0CAL0_RANGE3_MASK
__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:148
IDAC_Range_TypeDef
Definition: em_idac.h:159
#define _IDAC_CURPROG_RANGESEL_SHIFT
Definition: efm32hg_idac.h:111
#define IDAC_CURPROG_RANGESEL_RANGE0
Definition: efm32hg_idac.h:119