1 /***************************************************************************//**
2  * @file
3  * @brief Digital to Analog Converter (VDAC) peripheral API
4  *******************************************************************************
5  * # License
6  * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7  *******************************************************************************
8  *
9  * SPDX-License-Identifier: Zlib
10  *
11  * The licensor of this software is Silicon Laboratories Inc.
12  *
13  * This software is provided 'as-is', without any express or implied
14  * warranty. In no event will the authors be held liable for any damages
15  * arising from the use of this software.
16  *
17  * Permission is granted to anyone to use this software for any purpose,
18  * including commercial applications, and to alter it and redistribute it
19  * freely, subject to the following restrictions:
20  *
21  * 1. The origin of this software must not be misrepresented; you must not
22  *    claim that you wrote the original software. If you use this software
23  *    in a product, an acknowledgment in the product documentation would be
24  *    appreciated but is not required.
25  * 2. Altered source versions must be plainly marked as such, and must not be
26  *    misrepresented as being the original software.
27  * 3. This notice may not be removed or altered from any source distribution.
28  *
29  ******************************************************************************/
30 
31 #ifndef EM_VDAC_H
32 #define EM_VDAC_H
33 
34 #include "em_device.h"
35 
36 #if defined(VDAC_COUNT) && (VDAC_COUNT > 0)
37 
38 #include "em_assert.h"
39 #include <stdbool.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /***************************************************************************//**
46  * @addtogroup vdac VDAC - Voltage DAC
47  * @brief Digital to Analog Voltage Converter (VDAC) Peripheral API
48  *
49  * @details
50  *  This module contains functions to control the VDAC peripheral of Silicon
51  *  Labs' 32-bit MCUs and SoCs. VDAC converts digital values to analog
52  *  signals at up to 500 ksps with 12-bit accuracy. VDAC is designed for
53  *  low energy consumption, but can also provide very good performance.
54  *
55  *  The following steps are necessary for basic operation:
56  *
57  *  Clock enable:
58  *  @code
59     CMU_ClockEnable(cmuClock_VDAC0, true);@endcode
60  *
61  *  Initialize the VDAC with default settings and modify selected fields:
62  *  @code
63     VDAC_Init_TypeDef vdacInit          = VDAC_INIT_DEFAULT;
64     VDAC_InitChannel_TypeDef vdacChInit = VDAC_INITCHANNEL_DEFAULT;
65 
66     // Set prescaler to get 1 MHz VDAC clock frequency.
67     vdacInit.prescaler = VDAC_PrescaleCalc(1000000, true, 0);
68     VDAC_Init(VDAC0, &vdacInit);
69 
70     vdacChInit.enable = true;
71     VDAC_InitChannel(VDAC0, &vdacChInit, 0);@endcode
72  *
73  *  Perform a conversion:
74  *  @code
75     VDAC_ChannelOutputSet(VDAC0, 0, 250);@endcode
76  *
77  * @note The output stage of a VDAC channel consists of an on-chip operational
78  *   amplifier (OPAMP) in the OPAMP module. This OPAMP is highly configurable;
79  *   and to exploit the VDAC functionality fully, configure the OPAMP using
80  *   the OPAMP API. Using the OPAMP API also loads OPAMP calibration values.
81  *   The default (reset) settings of OPAMP is sufficient for many applications.
82  * @{
83  ******************************************************************************/
84 
85 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
86 
87 /** Validation of VDAC register block pointer reference for assert statements.*/
88 
89 #define VDAC_REF_VALID(ref)   ((ref) == VDAC0)
90 
91 /** @endcond */
92 
93 /*******************************************************************************
94  ********************************   ENUMS   ************************************
95  ******************************************************************************/
96 
97 #if !defined(_SILICON_LABS_32B_SERIES_2)
98 /** Channel refresh period. */
99 typedef enum {
100   vdacRefresh8  = _VDAC_CTRL_REFRESHPERIOD_8CYCLES,  /**< Refresh every 8 clock cycles. */
101   vdacRefresh16 = _VDAC_CTRL_REFRESHPERIOD_16CYCLES, /**< Refresh every 16 clock cycles. */
102   vdacRefresh32 = _VDAC_CTRL_REFRESHPERIOD_32CYCLES, /**< Refresh every 32 clock cycles. */
103   vdacRefresh64 = _VDAC_CTRL_REFRESHPERIOD_64CYCLES, /**< Refresh every 64 clock cycles. */
104 } VDAC_Refresh_TypeDef;
105 
106 /** Reference voltage for VDAC. */
107 typedef enum {
108   vdacRef1V25Ln = _VDAC_CTRL_REFSEL_1V25LN, /**< Internal low noise 1.25 V band gap reference. */
109   vdacRef2V5Ln  = _VDAC_CTRL_REFSEL_2V5LN,  /**< Internal low noise 2.5 V band gap reference. */
110   vdacRef1V25   = _VDAC_CTRL_REFSEL_1V25,   /**< Internal 1.25 V band gap reference. */
111   vdacRef2V5    = _VDAC_CTRL_REFSEL_2V5,    /**< Internal 2.5 V band gap reference. */
112   vdacRefAvdd   = _VDAC_CTRL_REFSEL_VDD,    /**< AVDD reference. */
113   vdacRefExtPin = _VDAC_CTRL_REFSEL_EXT,    /**< External pin reference. */
114 } VDAC_Ref_TypeDef;
115 
116 /** Peripheral Reflex System signal used to trigger VDAC channel conversion. */
117 typedef enum {
118   vdacPrsSelCh0 =  _VDAC_CH0CTRL_PRSSEL_PRSCH0,  /**< PRS ch 0 triggers conversion. */
119   vdacPrsSelCh1 =  _VDAC_CH0CTRL_PRSSEL_PRSCH1,  /**< PRS ch 1 triggers conversion. */
120   vdacPrsSelCh2 =  _VDAC_CH0CTRL_PRSSEL_PRSCH2,  /**< PRS ch 2 triggers conversion. */
121   vdacPrsSelCh3 =  _VDAC_CH0CTRL_PRSSEL_PRSCH3,  /**< PRS ch 3 triggers conversion. */
122   vdacPrsSelCh4 =  _VDAC_CH0CTRL_PRSSEL_PRSCH4,  /**< PRS ch 4 triggers conversion. */
123   vdacPrsSelCh5 =  _VDAC_CH0CTRL_PRSSEL_PRSCH5,  /**< PRS ch 5 triggers conversion. */
124   vdacPrsSelCh6 =  _VDAC_CH0CTRL_PRSSEL_PRSCH6,  /**< PRS ch 6 triggers conversion. */
125   vdacPrsSelCh7 =  _VDAC_CH0CTRL_PRSSEL_PRSCH7,  /**< PRS ch 7 triggers conversion. */
126 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH8)
127   vdacPrsSelCh8 =  _VDAC_CH0CTRL_PRSSEL_PRSCH8,  /**< PRS ch 8 triggers conversion. */
128 #endif
129 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH9)
130   vdacPrsSelCh9 =  _VDAC_CH0CTRL_PRSSEL_PRSCH9,  /**< PRS ch 9 triggers conversion. */
131 #endif
132 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH10)
133   vdacPrsSelCh10 = _VDAC_CH0CTRL_PRSSEL_PRSCH10, /**< PRS ch 10 triggers conversion. */
134 #endif
135 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH11)
136   vdacPrsSelCh11 = _VDAC_CH0CTRL_PRSSEL_PRSCH11, /**< PRS ch 11 triggers conversion. */
137 #endif
138 } VDAC_PrsSel_TypeDef;
139 
140 /** Channel conversion trigger mode. */
141 typedef enum {
142   vdacTrigModeSw        = _VDAC_CH0CTRL_TRIGMODE_SW,        /**< Channel is triggered by CHnDATA or COMBDATA write. */
143   vdacTrigModePrs       = _VDAC_CH0CTRL_TRIGMODE_PRS,       /**< Channel is triggered by PRS input. */
144   vdacTrigModeRefresh   = _VDAC_CH0CTRL_TRIGMODE_REFRESH,   /**< Channel is triggered by Refresh timer. */
145   vdacTrigModeSwPrs     = _VDAC_CH0CTRL_TRIGMODE_SWPRS,     /**< Channel is triggered by CHnDATA/COMBDATA write or PRS input. */
146   vdacTrigModeSwRefresh = _VDAC_CH0CTRL_TRIGMODE_SWREFRESH, /**< Channel is triggered by CHnDATA/COMBDATA write or Refresh timer. */
147   vdacTrigModeLesense   = _VDAC_CH0CTRL_TRIGMODE_LESENSE,   /**< Channel is triggered by LESENSE. */
148 } VDAC_TrigMode_TypeDef;
149 
150 /*******************************************************************************
151  *******************************   STRUCTS   ***********************************
152  ******************************************************************************/
153 
154 /** VDAC initialization structure, common for both channels. */
155 typedef struct {
156   /** Selects between main and alternate output path calibration values. */
157   bool                  mainCalibration;
158 
159   /** Selects clock from asynchronous or synchronous (with respect to
160       peripheral clock) source. */
161   bool                  asyncClockMode;
162 
163   /** Warm-up mode, keep VDAC on (in idle) - or shutdown between conversions.*/
164   bool                  warmupKeepOn;
165 
166   /** Channel refresh period. */
167   VDAC_Refresh_TypeDef  refresh;
168 
169   /** Prescaler for VDAC clock. Clock is source clock divided by prescaler+1. */
170   uint32_t              prescaler;
171 
172   /** Reference voltage to use. */
173   VDAC_Ref_TypeDef      reference;
174 
175   /** Enable/disable reset of prescaler on CH 0 start. */
176   bool                 ch0ResetPre;
177 
178   /** Enable/disable output enable control by CH1 PRS signal. */
179   bool                 outEnablePRS;
180 
181   /** Enable/disable sine mode. */
182   bool                 sineEnable;
183 
184   /** Select if single ended or differential output mode. */
185   bool                 diff;
186 } VDAC_Init_TypeDef;
187 
188 /** Default configuration for VDAC initialization structure. */
189 #define VDAC_INIT_DEFAULT                                                \
190   {                                                                      \
191     true,                 /* Use main output path calibration values. */ \
192     false,                /* Use synchronous clock mode. */              \
193     false,                /* Turn off between sample off conversions.*/  \
194     vdacRefresh8,         /* Refresh every 8th cycle. */                 \
195     0,                    /* No prescaling. */                           \
196     vdacRef1V25Ln,        /* 1.25 V internal low noise reference. */     \
197     false,                /* Do not reset prescaler on CH 0 start. */    \
198     false,                /* VDAC output enable always on. */            \
199     false,                /* Disable sine mode. */                       \
200     false                 /* Single ended mode. */                       \
201   }
202 
203 /** VDAC channel initialization structure. */
204 typedef struct {
205   /** Enable channel. */
206   bool                  enable;
207 
208   /**
209    * Peripheral reflex system trigger selection. Only applicable if @p trigMode
210    * is set to @p vdacTrigModePrs or @p vdacTrigModeSwPrs. */
211   VDAC_PrsSel_TypeDef   prsSel;
212 
213   /** Treat the PRS signal asynchronously. */
214   bool                  prsAsync;
215 
216   /** Channel conversion trigger mode. */
217   VDAC_TrigMode_TypeDef trigMode;
218 
219   /** Set channel conversion mode to sample/shut-off mode. Default is
220    *  continuous.*/
221   bool                  sampleOffMode;
222 } VDAC_InitChannel_TypeDef;
223 
224 /** Default configuration for VDAC channel initialization structure. */
225 #define VDAC_INITCHANNEL_DEFAULT                                                \
226   {                                                                             \
227     false,            /* Leave channel disabled when initialization is done. */ \
228     vdacPrsSelCh0,    /* PRS CH 0 triggers conversion. */                       \
229     false,            /* Treat PRS channel as a synchronous signal. */          \
230     vdacTrigModeSw,   /* Conversion trigged by CH0DATA or COMBDATA write. */    \
231     false,            /* Channel conversion set to continuous. */               \
232   }
233 #else // defined(_SILICON_LABS_32B_SERIES_2)
234 
235 /** Channel refresh period. */
236 typedef enum {
237   vdacRefresh2    = _VDAC_CFG_REFRESHPERIOD_CYCLES2,    /**< Refresh every 2 clock cycles. */
238   vdacRefresh4    = _VDAC_CFG_REFRESHPERIOD_CYCLES4,    /**< Refresh every 4 clock cycles. */
239   vdacRefresh8    = _VDAC_CFG_REFRESHPERIOD_CYCLES8,    /**< Refresh every 8 clock cycles. */
240   vdacRefresh16   = _VDAC_CFG_REFRESHPERIOD_CYCLES16,   /**< Refresh every 16 clock cycles. */
241   vdacRefresh32   = _VDAC_CFG_REFRESHPERIOD_CYCLES32,   /**< Refresh every 32 clock cycles. */
242   vdacRefresh64   = _VDAC_CFG_REFRESHPERIOD_CYCLES64,   /**< Refresh every 64 clock cycles. */
243   vdacRefresh128  = _VDAC_CFG_REFRESHPERIOD_CYCLES128,  /**< Refresh every 128 clock cycles. */
244   vdacRefresh256  = _VDAC_CFG_REFRESHPERIOD_CYCLES256,  /**< Refresh every 256 clock cycles. */
245 } VDAC_Refresh_TypeDef;
246 
247 /** Timer overflow period. */
248 typedef enum {
249   vdacCycles2  = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES2,    /**< Overflows every 2 clock cycles. */
250   vdacCycles4  = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES4,    /**< Overflows every 4 clock cycles. */
251   vdacCycles8  = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES8,    /**< Overflows every 8 clock cycles. */
252   vdacCycles16 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES16,   /**< Overflows every 16 clock cycles. */
253   vdacCycles32 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES32,   /**< Overflows every 32 clock cycles. */
254   vdacCycles64 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES64    /**< Overflows every 64 clock cycles. */
255 } VDAC_TimerOverflow_TypeDef;
256 
257 /** Reference voltage for VDAC. */
258 typedef enum {
259   vdacRef1V25   = _VDAC_CFG_REFRSEL_V125,   /**< Internal 1.25 V band gap reference. */
260   vdacRef2V5    = _VDAC_CFG_REFRSEL_V25,    /**< Internal 2.5 V band gap reference. */
261   vdacRefAvdd   = _VDAC_CFG_REFRSEL_VDD,    /**< AVDD reference. */
262   vdacRefExtPin = _VDAC_CFG_REFRSEL_EXT,    /**< External pin reference. */
263 } VDAC_Ref_TypeDef;
264 
265 typedef enum {
266   vdacRefreshSrcNone          = _VDAC_CH0CFG_REFRESHSOURCE_NONE,        /**< No refresh source. */
267   vdacRefreshSrcRefreshTimer  = _VDAC_CH0CFG_REFRESHSOURCE_REFRESHTIMER,/**< Refresh triggered by refresh timer overflow. */
268   vdacRefreshSrcSyncPrs       = _VDAC_CH0CFG_REFRESHSOURCE_SYNCPRS,     /**< Refresh triggered by sync PRS. */
269   vdacRefreshSrcAsyncPrs      = _VDAC_CH0CFG_REFRESHSOURCE_ASYNCPRS,    /**< Refresh triggered by async PRS. */
270 } VDAC_RefreshSource_TypeDef;
271 
272 /** Channel conversion trigger mode. */
273 typedef enum {
274   vdacTrigModeNone          = _VDAC_CH0CFG_TRIGMODE_NONE,           /**< No conversion trigger source selected. */
275   vdacTrigModeSw            = _VDAC_CH0CFG_TRIGMODE_SW,             /**< Channel is triggered by CHnDATA or COMBDATA write. */
276   vdacTrigModeSyncPrs       = _VDAC_CH0CFG_TRIGMODE_SYNCPRS,        /**< Channel is triggered by Sync PRS input. */
277   vdacTrigModeLesense       = _VDAC_CH0CFG_TRIGMODE_LESENSE,        /**< Channel is triggered by LESENSE. */
278   vdacTrigModeInternalTimer = _VDAC_CH0CFG_TRIGMODE_INTERNALTIMER,  /**< Channel is triggered by Internal Timer. */
279   vdacTrigModeAsyncPrs      = _VDAC_CH0CFG_TRIGMODE_ASYNCPRS        /**< Channel is triggered by Async PRS input. */
280 } VDAC_TrigMode_TypeDef;
281 
282 /** Channel power mode. */
283 typedef enum {
284   vdacPowerModeHighPower    = _VDAC_CH0CFG_POWERMODE_HIGHPOWER,     /**< High power buffer mode. */
285   vdacPowerModeLowPower     = _VDAC_CH0CFG_POWERMODE_LOWPOWER       /**< Low power buffer mode. */
286 } VDAC_PowerMode_TypeDef;
287 
288 /** VDAC channel Abus port selection. */
289 typedef enum {
290   /** NoneSelected  */
291   vdacChPortNone    = _VDAC_OUTCTRL_ABUSPORTSELCH0_NONE,
292   vdacChPortA       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTA,
293   vdacChPortB       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTB,
294   vdacChPortC       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTC,
295   vdacChPortD       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTD,
296 } VDAC_ChPortSel_t;
297 
298 /*******************************************************************************
299  *******************************   STRUCTS   ***********************************
300  ******************************************************************************/
301 
302 /** VDAC initialization structure, common for both channels. */
303 typedef struct {
304   /** Number of prescaled CLK_DAC + 1 for the vdac to warmup. */
305   uint32_t                    warmupTime;
306 
307   /** Halt during debug. */
308   bool                        dbgHalt;
309 
310   /** Always allow clk_dac. */
311   bool                        onDemandClk;
312 
313   /** DMA Wakeup. */
314   bool                        dmaWakeUp;
315 
316   /** Bias keep warm enable. */
317   bool                        biasKeepWarm;
318 
319   /** Channel refresh period. */
320   VDAC_Refresh_TypeDef        refresh;
321 
322   /** Internal timer overflow period. */
323   VDAC_TimerOverflow_TypeDef  timerOverflow;
324 
325   /** Prescaler for VDAC clock. Clock is source clock divided by prescaler+1. */
326   uint32_t                    prescaler;
327 
328   /** Reference voltage to use. */
329   VDAC_Ref_TypeDef            reference;
330 
331   /** Enable/disable reset of prescaler on CH 0 start. */
332   bool                        ch0ResetPre;
333 
334   /** Sine reset mode. */
335   bool                        sineReset;
336 
337   /** Enable/disable sine mode. */
338   bool                        sineEnable;
339 
340   /** Select if single ended or differential output mode. */
341   bool                        diff;
342 } VDAC_Init_TypeDef;
343 
344 /** Default configuration for VDAC initialization structure. */
345 #define VDAC_INIT_DEFAULT                                                                            \
346   {                                                                                                  \
347     _VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */              \
348     false,                        /* Continue while debugging. */                                    \
349     true,                         /* On demand clock. */                                             \
350     false,                        /* DMA wake up. */                                                 \
351     false,                        /* Bias keep warm. */                                              \
352     vdacRefresh8,                 /* Refresh every 8th cycle. */                                     \
353     vdacCycles2,                  /* Internal overflow every 8th cycle. */                           \
354     0,                            /* No prescaling. */                                               \
355     vdacRef1V25,                  /* 1.25 V internal low noise reference. */                         \
356     false,                        /* Do not reset prescaler on CH 0 start. */                        \
357     false,                        /* Sine wave is stopped at the sample its currently outputting. */ \
358     false,                        /* Disable sine mode. */                                           \
359     false                         /* Differential mode. */                                           \
360   }
361 
362 /** VDAC channel initialization structure. */
363 typedef struct {
364   /** Enable channel. */
365   bool                        enable;
366 
367   /** Warm-up mode, keep VDAC on (in idle) - or shutdown between conversions.*/
368   bool                        warmupKeepOn;
369 
370   /** Select high capacitance load mode in conjunction with high power. */
371   bool                        highCapLoadEnable;
372 
373   /** Channel x FIFO Low threshold data valid level. */
374   uint32_t                    fifoLowDataThreshold;
375 
376   /** Channel refresh source. */
377   VDAC_RefreshSource_TypeDef  chRefreshSource;
378 
379   /** Channel conversion trigger mode. */
380   VDAC_TrigMode_TypeDef       trigMode;
381 
382   /** Channel power mode. */
383   VDAC_PowerMode_TypeDef      powerMode;
384 
385   /** Set channel conversion mode to sample/shut-off mode. Default is
386    *  continuous.*/
387   bool                        sampleOffMode;
388 
389   /** Vdac channel output pin. */
390   uint32_t                    pin;
391 
392   /** Vdac channel output port. */
393   VDAC_ChPortSel_t            port;
394 
395   /** Short High power and low power output. */
396   bool                        shortOutput;
397 
398   /**  Alternative output enable. */
399   bool                        auxOutEnable;
400 
401   /**  Main output enable. */
402   bool                        mainOutEnable;
403 
404   /**  Channel output hold time. */
405   uint32_t                    holdOutTime;
406 } VDAC_InitChannel_TypeDef;
407 
408 /** Default configuration for VDAC channel initialization structure. */
409 #define VDAC_INITCHANNEL_DEFAULT                                                      \
410   {                                                                                   \
411     false,                  /* Leave channel disabled when initialization is done. */ \
412     false,                  /* Turn off between sample off conversions.*/             \
413     true,                   /* Enable High cap mode. */                               \
414     0,                      /* Fifo data low watermark at 0. */                       \
415     vdacRefreshSrcNone,     /* Channel refresh source. */                             \
416     vdacTrigModeSw,         /* Conversion trigged by CH0DATA or COMBDATA write. */    \
417     vdacPowerModeHighPower, /* High power mode enabled. */                            \
418     false,                  /* Continuous conversion mode. */                         \
419     0,                      /* ABUS pin selected. */                                  \
420     vdacChPortNone,         /* No Analog bus port selected. */                        \
421     false,                  /* Output not shorted */                                  \
422     false,                  /* Alternative output disabled. */                        \
423     true,                   /* Main output enabled. */                                \
424     0                       /* Hold out time. Previously called settle time */        \
425   }
426 
427 #endif
428 /*******************************************************************************
429  *****************************   PROTOTYPES   **********************************
430  ******************************************************************************/
431 
432 void VDAC_ChannelOutputSet(VDAC_TypeDef *vdac,
433                            unsigned int channel,
434                            uint32_t     value);
435 void VDAC_Enable(VDAC_TypeDef *vdac, unsigned int ch, bool enable);
436 void VDAC_Init(VDAC_TypeDef *vdac, const VDAC_Init_TypeDef *init);
437 void VDAC_InitChannel(VDAC_TypeDef *vdac,
438                       const VDAC_InitChannel_TypeDef *init,
439                       unsigned int ch);
440 
441 #if defined(_SILICON_LABS_32B_SERIES_2)
442 /***************************************************************************//**
443  * @brief
444  *  Sinemode start/stop
445  *
446  * @details
447  *   This function send the sine mode start/stop signal to the DAC.
448  *
449  * @param[in] vdac
450  *   Pointer to VDAC peripheral register block.
451  *
452  * @param[in] start
453  *   True to start the Sine mode, false to stop it.
454  ******************************************************************************/
VDAC_SineModeStart(VDAC_TypeDef * vdac,bool start)455 __STATIC_INLINE void VDAC_SineModeStart(VDAC_TypeDef *vdac, bool start)
456 {
457   EFM_ASSERT(VDAC_REF_VALID(vdac));
458 
459   while (vdac->STATUS & VDAC_STATUS_SYNCBUSY) ;
460 
461   if (start) {
462     vdac->CMD = VDAC_CMD_SINEMODESTART;
463     while ((vdac->STATUS & VDAC_STATUS_SINEACTIVE) == 0) ;
464   } else {
465     vdac->CMD = VDAC_CMD_SINEMODESTOP;
466     while ((vdac->STATUS & VDAC_STATUS_SINEACTIVE) != 0) ;
467   }
468 }
469 #endif
470 
471 /***************************************************************************//**
472  * @brief
473  *   Set the output signal of VDAC channel 0 to a given value.
474  *
475  * @details
476  *   This function sets the output signal of VDAC channel 0 by writing @p value
477  *   to the CH0DATA register.
478  *
479  * @param[in] vdac
480  *   Pointer to VDAC peripheral register block.
481  *
482  * @param[in] value
483  *   Value to write to channel 0 output register CH0DATA.
484  ******************************************************************************/
VDAC_Channel0OutputSet(VDAC_TypeDef * vdac,uint32_t value)485 __STATIC_INLINE void VDAC_Channel0OutputSet(VDAC_TypeDef *vdac,
486                                             uint32_t value)
487 {
488 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
489   EFM_ASSERT(value <= _VDAC_CH0DATA_MASK);
490   vdac->CH0DATA = value;
491 #elif defined(_SILICON_LABS_32B_SERIES_2)
492   EFM_ASSERT(value <= _VDAC_CH0F_MASK);
493   vdac->CH0F = value;
494 #endif
495 }
496 
497 /***************************************************************************//**
498  * @brief
499  *   Set the output signal of VDAC channel 1 to a given value.
500  *
501  * @details
502  *   This function sets the output signal of VDAC channel 1 by writing @p value
503  *   to the CH1DATA register.
504  *
505  * @param[in] vdac
506  *   Pointer to VDAC peripheral register block.
507  *
508  * @param[in] value
509  *   Value to write to channel 1 output register CH1DATA.
510  ******************************************************************************/
VDAC_Channel1OutputSet(VDAC_TypeDef * vdac,uint32_t value)511 __STATIC_INLINE void VDAC_Channel1OutputSet(VDAC_TypeDef *vdac,
512                                             uint32_t value)
513 {
514 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
515   EFM_ASSERT(value <= _VDAC_CH1DATA_MASK);
516   vdac->CH1DATA = value;
517 #elif defined(_SILICON_LABS_32B_SERIES_2)
518   EFM_ASSERT(value <= _VDAC_CH1F_MASK);
519   vdac->CH1F = value;
520 #endif
521 }
522 
523 /***************************************************************************//**
524  * @brief
525  *   Clear one or more pending VDAC interrupts.
526  *
527  * @param[in] vdac
528  *   Pointer to VDAC peripheral register block.
529  *
530  * @param[in] flags
531  *   Pending VDAC interrupt source to clear. Use a bitwise logic OR combination
532  *   of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
533  ******************************************************************************/
VDAC_IntClear(VDAC_TypeDef * vdac,uint32_t flags)534 __STATIC_INLINE void VDAC_IntClear(VDAC_TypeDef *vdac, uint32_t flags)
535 {
536 #if defined(VDAC_HAS_SET_CLEAR)
537   vdac->IF_CLR = flags;
538 #else
539   vdac->IFC = flags;
540 #endif
541 }
542 
543 /***************************************************************************//**
544  * @brief
545  *   Disable one or more VDAC interrupts.
546  *
547  * @param[in] vdac
548  *   Pointer to VDAC peripheral register block.
549  *
550  * @param[in] flags
551  *   VDAC interrupt sources to disable. Use a bitwise logic OR combination of
552  *   valid interrupt flags for the VDAC module (VDAC_IF_nnn).
553  ******************************************************************************/
VDAC_IntDisable(VDAC_TypeDef * vdac,uint32_t flags)554 __STATIC_INLINE void VDAC_IntDisable(VDAC_TypeDef *vdac, uint32_t flags)
555 {
556 #if defined(VDAC_HAS_SET_CLEAR)
557   vdac->IEN_CLR = flags;
558 #else
559   vdac->IEN &= ~flags;
560 #endif
561 }
562 
563 /***************************************************************************//**
564  * @brief
565  *   Enable one or more VDAC interrupts.
566  *
567  * @note
568  *   Depending on the use, a pending interrupt may already be set prior to
569  *   enabling the interrupt. To ignore a pending interrupt, consider using
570  *   VDAC_IntClear() prior to enabling the interrupt.
571  *
572  * @param[in] vdac
573  *   Pointer to VDAC peripheral register block.
574  *
575  * @param[in] flags
576  *   VDAC interrupt sources to enable. Use a bitwise logic OR combination
577  *   of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
578  ******************************************************************************/
VDAC_IntEnable(VDAC_TypeDef * vdac,uint32_t flags)579 __STATIC_INLINE void VDAC_IntEnable(VDAC_TypeDef *vdac, uint32_t flags)
580 {
581 #if defined(VDAC_HAS_SET_CLEAR)
582   vdac->IEN_SET = flags;
583 #else
584   vdac->IEN |= flags;
585 #endif
586 }
587 
588 /***************************************************************************//**
589  * @brief
590  *   Get pending VDAC interrupt flags.
591  *
592  * @note
593  *   The event bits are not cleared by the use of this function.
594  *
595  * @param[in] vdac
596  *   Pointer to VDAC peripheral register block.
597  *
598  * @return
599  *   VDAC interrupt sources pending. Use a bitwise logic OR combination
600  *   of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
601  ******************************************************************************/
VDAC_IntGet(VDAC_TypeDef * vdac)602 __STATIC_INLINE uint32_t VDAC_IntGet(VDAC_TypeDef *vdac)
603 {
604   return vdac->IF;
605 }
606 
607 /***************************************************************************//**
608  * @brief
609  *   Get enabled and pending VDAC interrupt flags.
610  *   Useful for handling more interrupt sources in the same interrupt handler.
611  *
612  * @param[in] vdac
613  *   Pointer to VDAC peripheral register block.
614  *
615  * @note
616  *   Interrupt flags are not cleared by the use of this function.
617  *
618  * @return
619  *   Pending and enabled VDAC interrupt sources.
620  *   The return value is the bitwise AND combination of
621  *   - the OR combination of enabled interrupt sources in VDACx_IEN_nnn
622  *     register (VDACx_IEN_nnn) and
623  *   - the OR combination of valid interrupt flags of the VDAC module
624  *     (VDACx_IF_nnn).
625  ******************************************************************************/
VDAC_IntGetEnabled(VDAC_TypeDef * vdac)626 __STATIC_INLINE uint32_t VDAC_IntGetEnabled(VDAC_TypeDef *vdac)
627 {
628   uint32_t ien = vdac->IEN;
629 
630   /* Bitwise AND of pending and enabled interrupts */
631   return vdac->IF & ien;
632 }
633 
634 /***************************************************************************//**
635  * @brief
636  *   Set one or more pending VDAC interrupts from SW.
637  *
638  * @param[in] vdac
639  *   Pointer to VDAC peripheral register block.
640  *
641  * @param[in] flags
642  *   VDAC interrupt sources to set to pending. Use a bitwise logic OR
643  *   combination of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
644  ******************************************************************************/
VDAC_IntSet(VDAC_TypeDef * vdac,uint32_t flags)645 __STATIC_INLINE void VDAC_IntSet(VDAC_TypeDef *vdac, uint32_t flags)
646 {
647 #if defined(VDAC_HAS_SET_CLEAR)
648   vdac->IF_SET = flags;
649 #else
650   vdac->IFS = flags;
651 #endif
652 }
653 
654 #if defined(_SILICON_LABS_32B_SERIES_2)
655 /***************************************************************************//**
656  * @brief
657  *    Get Vdac Status register.
658  *
659  * @return
660  *    Current STATUS register value.
661  ******************************************************************************/
VDAC_GetStatus(VDAC_TypeDef * vdac)662 __STATIC_INLINE uint32_t VDAC_GetStatus(VDAC_TypeDef *vdac)
663 {
664   return vdac->STATUS;
665 }
666 #endif
667 
668 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
669 uint32_t VDAC_PrescaleCalc(uint32_t vdacFreq, bool syncMode, uint32_t hfperFreq);
670 #else
671 uint32_t VDAC_PrescaleCalc(uint32_t vdacFreq);
672 #endif
673 
674 void VDAC_Reset(VDAC_TypeDef *vdac);
675 
676 /** @} (end addtogroup vdac) */
677 
678 #ifdef __cplusplus
679 }
680 #endif
681 
682 #endif /* defined(VDAC_COUNT) && (VDAC_COUNT > 0) */
683 #endif /* EM_VDAC_H */
684