EFM32 Zero Gecko Software Documentation  efm32zg-doc-4.2.1
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 /***************************************************************************/
51 /* Fix for errata IDAC_E101 - IDAC output current degradation */
52 #if defined(_EFM32_ZERO_FAMILY) || defined(_EFM32_HAPPY_FAMILY)
53 #define ERRATA_FIX_IDAC_E101_EN
54 #endif
55 
57 /*******************************************************************************
58  ************************** GLOBAL FUNCTIONS *******************************
59  ******************************************************************************/
60 /***************************************************************************/
77 void IDAC_Init(IDAC_TypeDef *idac, const IDAC_Init_TypeDef *init)
78 {
79  uint32_t tmp;
80 
81  EFM_ASSERT(IDAC_REF_VALID(idac));
82 
83  tmp = (uint32_t)(init->prsSel);
84 
85  tmp |= init->outMode;
86 
87  if (init->enable)
88  {
89  tmp |= IDAC_CTRL_EN;
90  }
91  if (init->prsEnable)
92  {
93  tmp |= IDAC_CTRL_OUTENPRS;
94  }
95  if (init->sinkEnable)
96  {
97  tmp |= IDAC_CTRL_CURSINK;
98  }
99 
100  idac->CTRL = tmp;
101 }
102 
103 
104 /***************************************************************************/
114 void IDAC_Enable(IDAC_TypeDef *idac, bool enable)
115 {
116  volatile uint32_t *reg;
117 
118  EFM_ASSERT(IDAC_REF_VALID(idac));
119 
120  reg = &(idac->CTRL);
121 
122  BUS_RegBitWrite(reg, _IDAC_CTRL_EN_SHIFT, enable);
123 }
124 
125 
126 /***************************************************************************/
134 {
135  EFM_ASSERT(IDAC_REF_VALID(idac));
136 
137 #if defined(ERRATA_FIX_IDAC_E101_EN)
138  /* Fix for errata IDAC_E101 - IDAC output current degradation:
139  Instead of disabling it we will put it in it's lowest power state (50 nA)
140  to avoid degradation over time */
141 
142  /* Make sure IDAC is enabled with disabled output */
144 
145  /* Set lowest current (50 nA) */
148 
149  /* Enable duty-cycling for all energy modes */
151 #else
152  idac->CTRL = _IDAC_CTRL_RESETVALUE;
155 #endif
156 #if defined ( _IDAC_CAL_MASK )
157  idac->CAL = _IDAC_CAL_RESETVALUE;
158 #endif
159 }
160 
161 
162 /***************************************************************************/
173 {
174  volatile uint32_t *reg;
175 
176  EFM_ASSERT(IDAC_REF_VALID(idac));
177 
178  reg = &(idac->CTRL);
179 
181 }
182 
183 
184 /***************************************************************************/
201 {
202  uint32_t tmp;
203 #if defined( _IDAC_CURPROG_TUNING_MASK )
204  uint32_t diCal0;
205  uint32_t diCal1;
206 #endif
207 
208  EFM_ASSERT(IDAC_REF_VALID(idac));
209  EFM_ASSERT(((uint32_t)range >> _IDAC_CURPROG_RANGESEL_SHIFT)
211 
212 #if defined ( _IDAC_CAL_MASK )
213 
214  /* Load proper calibration data depending on selected range */
215  switch ((IDAC_Range_TypeDef)range)
216  {
217  case idacCurrentRange0:
218  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE0_MASK)
220  break;
221  case idacCurrentRange1:
222  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE1_MASK)
224  break;
225  case idacCurrentRange2:
226  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE2_MASK)
228  break;
229  case idacCurrentRange3:
230  idac->CAL = (DEVINFO->IDAC0CAL0 & _DEVINFO_IDAC0CAL0_RANGE3_MASK)
232  break;
233  }
234 
235  tmp = idac->CURPROG & ~_IDAC_CURPROG_RANGESEL_MASK;
236  tmp |= (uint32_t)range;
237 
238 #elif defined( _IDAC_CURPROG_TUNING_MASK )
239 
240  /* Load calibration data depending on selected range and sink/source mode */
241  /* TUNING (calibration) field in CURPROG register. */
242  if (idac == IDAC0)
243  {
244  diCal0 = DEVINFO->IDAC0CAL0;
245  diCal1 = DEVINFO->IDAC0CAL1;
246  }
247  else
248  {
249  EFM_ASSERT(false);
250  }
251 
252  tmp = idac->CURPROG & ~(_IDAC_CURPROG_TUNING_MASK
254  if (idac->CTRL & IDAC_CTRL_CURSINK)
255  {
256  switch (range)
257  {
258  case idacCurrentRange0:
259  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE0TUNING_MASK)
260  >> _DEVINFO_IDAC0CAL1_SINKRANGE0TUNING_SHIFT)
261  << _IDAC_CURPROG_TUNING_SHIFT;
262  break;
263 
264  case idacCurrentRange1:
265  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE1TUNING_MASK)
266  >> _DEVINFO_IDAC0CAL1_SINKRANGE1TUNING_SHIFT)
267  << _IDAC_CURPROG_TUNING_SHIFT;
268  break;
269 
270  case idacCurrentRange2:
271  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE2TUNING_MASK)
272  >> _DEVINFO_IDAC0CAL1_SINKRANGE2TUNING_SHIFT)
273  << _IDAC_CURPROG_TUNING_SHIFT;
274  break;
275 
276  case idacCurrentRange3:
277  tmp |= ((diCal1 & _DEVINFO_IDAC0CAL1_SINKRANGE3TUNING_MASK)
278  >> _DEVINFO_IDAC0CAL1_SINKRANGE3TUNING_SHIFT)
279  << _IDAC_CURPROG_TUNING_SHIFT;
280  break;
281  }
282  }
283  else
284  {
285  switch (range)
286  {
287  case idacCurrentRange0:
288  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE0TUNING_MASK)
289  >> _DEVINFO_IDAC0CAL0_SOURCERANGE0TUNING_SHIFT)
290  << _IDAC_CURPROG_TUNING_SHIFT;
291  break;
292 
293  case idacCurrentRange1:
294  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE1TUNING_MASK)
295  >> _DEVINFO_IDAC0CAL0_SOURCERANGE1TUNING_SHIFT)
296  << _IDAC_CURPROG_TUNING_SHIFT;
297  break;
298 
299  case idacCurrentRange2:
300  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE2TUNING_MASK)
301  >> _DEVINFO_IDAC0CAL0_SOURCERANGE2TUNING_SHIFT)
302  << _IDAC_CURPROG_TUNING_SHIFT;
303  break;
304 
305  case idacCurrentRange3:
306  tmp |= ((diCal0 & _DEVINFO_IDAC0CAL0_SOURCERANGE3TUNING_MASK)
307  >> _DEVINFO_IDAC0CAL0_SOURCERANGE3TUNING_SHIFT)
308  << _IDAC_CURPROG_TUNING_SHIFT;
309  break;
310  }
311  }
312 
313  tmp |= (uint32_t)range;
314 
315 #else
316 #warning "IDAC calibration register definition unknown."
317 #endif
318 
319  idac->CURPROG = tmp;
320 }
321 
322 
323 /***************************************************************************/
333 void IDAC_StepSet(IDAC_TypeDef *idac, const uint32_t step)
334 {
335  uint32_t tmp;
336 
337  EFM_ASSERT(IDAC_REF_VALID(idac));
339 
340  tmp = idac->CURPROG & ~_IDAC_CURPROG_STEPSEL_MASK;
341  tmp |= step << _IDAC_CURPROG_STEPSEL_SHIFT;
342 
343  idac->CURPROG = tmp;
344 }
345 
346 
347 /***************************************************************************/
357 void IDAC_OutEnable(IDAC_TypeDef *idac, bool enable)
358 {
359  volatile uint32_t *reg;
360 
361  EFM_ASSERT(IDAC_REF_VALID(idac));
362 
363  reg = &(idac->CTRL);
364 
366 }
367 
368 
372 #endif /* defined(IDAC_COUNT) && (IDAC_COUNT > 0) */
#define _DEVINFO_IDAC0CAL0_RANGE2_SHIFT
Clock management unit (CMU) API.
__IO uint32_t DUTYCONFIG
Definition: efm32zg_idac.h:46
#define _DEVINFO_IDAC0CAL0_RANGE0_SHIFT
#define IDAC_CTRL_CURSINK
Definition: efm32zg_idac.h:62
#define IDAC_CURPROG_RANGESEL_RANGE0
Definition: efm32zg_idac.h:115
IDAC_PRSSEL_TypeDef prsSel
Definition: em_idac.h:165
Emlib peripheral API "assert" implementation.
#define _IDAC_CURPROG_RANGESEL_MASK
Definition: efm32zg_idac.h:108
#define _IDAC_CURPROG_STEPSEL_MASK
Definition: efm32zg_idac.h:120
RAM and peripheral bit-field set and clear API.
#define _DEVINFO_IDAC0CAL0_RANGE2_MASK
Current Digital to Analog Converter (IDAC) peripheral API.
#define IDAC_CTRL_OUTENPRS
Definition: efm32zg_idac.h:86
#define _DEVINFO_IDAC0CAL0_RANGE0_MASK
#define _DEVINFO_IDAC0CAL0_RANGE1_SHIFT
#define IDAC0
void IDAC_Enable(IDAC_TypeDef *idac, bool enable)
Enable/disable IDAC.
Definition: em_idac.c:114
#define _IDAC_CURPROG_RANGESEL_SHIFT
Definition: efm32zg_idac.h:107
void IDAC_MinimalOutputTransitionMode(IDAC_TypeDef *idac, bool enable)
Enable/disable Minimal Output Transition mode.
Definition: em_idac.c:172
#define _IDAC_CTRL_MINOUTTRANS_SHIFT
Definition: efm32zg_idac.h:68
__IO uint32_t CAL
Definition: efm32zg_idac.h:45
#define _IDAC_DUTYCONFIG_RESETVALUE
Definition: efm32zg_idac.h:133
#define _DEVINFO_IDAC0CAL0_RANGE3_SHIFT
__IO uint32_t CURPROG
Definition: efm32zg_idac.h:44
void IDAC_RangeSet(IDAC_TypeDef *idac, const IDAC_Range_TypeDef range)
Set the current range of the IDAC output.
Definition: em_idac.c:200
#define _IDAC_CAL_RESETVALUE
Definition: efm32zg_idac.h:125
#define _IDAC_CTRL_OUTEN_SHIFT
Definition: efm32zg_idac.h:73
void IDAC_Init(IDAC_TypeDef *idac, const IDAC_Init_TypeDef *init)
Initialize IDAC.
Definition: em_idac.c:77
__IO uint32_t CTRL
Definition: efm32zg_idac.h:43
#define _DEVINFO_IDAC0CAL0_RANGE1_MASK
#define _IDAC_CURPROG_STEPSEL_SHIFT
Definition: efm32zg_idac.h:119
IDAC_OutMode_TypeDef outMode
Definition: em_idac.h:152
void IDAC_StepSet(IDAC_TypeDef *idac, const uint32_t step)
Set the current step of the IDAC output.
Definition: em_idac.c:333
#define DEVINFO
#define _IDAC_CTRL_EN_SHIFT
Definition: efm32zg_idac.h:58
#define _IDAC_CTRL_RESETVALUE
Definition: efm32zg_idac.h:55
#define IDAC_DUTYCONFIG_DUTYCYCLEEN
Definition: efm32zg_idac.h:135
void IDAC_Reset(IDAC_TypeDef *idac)
Reset IDAC to same state as after a HW reset.
Definition: em_idac.c:133
#define IDAC_CTRL_EN
Definition: efm32zg_idac.h:57
#define _IDAC_CURPROG_RESETVALUE
Definition: efm32zg_idac.h:105
#define _DEVINFO_IDAC0CAL0_RANGE3_MASK
void IDAC_OutEnable(IDAC_TypeDef *idac, bool enable)
Enable/disable the IDAC OUT pin.
Definition: em_idac.c:357
__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
IDAC_Range_TypeDef
Definition: em_idac.h:133