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 "sl_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); // function call for series 0/1
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 #if VDAC_COUNT == 1
90 #define VDAC_REF_VALID(ref)   ((ref) == VDAC0)
91 #elif VDAC_COUNT == 2
92 #define VDAC_REF_VALID(ref)   (((ref) == VDAC0) || ((ref) == VDAC1))
93 #else
94 #error "Undefined number of VDACs."
95 #endif
96 
97 /** @endcond */
98 
99 /*******************************************************************************
100  ********************************   ENUMS   ************************************
101  ******************************************************************************/
102 
103 #if !defined(_SILICON_LABS_32B_SERIES_2)
104 /** Channel refresh period. */
105 typedef enum {
106   vdacRefresh8  = _VDAC_CTRL_REFRESHPERIOD_8CYCLES,  /**< Refresh every 8 clock cycles. */
107   vdacRefresh16 = _VDAC_CTRL_REFRESHPERIOD_16CYCLES, /**< Refresh every 16 clock cycles. */
108   vdacRefresh32 = _VDAC_CTRL_REFRESHPERIOD_32CYCLES, /**< Refresh every 32 clock cycles. */
109   vdacRefresh64 = _VDAC_CTRL_REFRESHPERIOD_64CYCLES, /**< Refresh every 64 clock cycles. */
110 } VDAC_Refresh_TypeDef;
111 
112 /** Reference voltage for VDAC. */
113 typedef enum {
114   vdacRef1V25Ln = _VDAC_CTRL_REFSEL_1V25LN, /**< Internal low noise 1.25 V band gap reference. */
115   vdacRef2V5Ln  = _VDAC_CTRL_REFSEL_2V5LN,  /**< Internal low noise 2.5 V band gap reference. */
116   vdacRef1V25   = _VDAC_CTRL_REFSEL_1V25,   /**< Internal 1.25 V band gap reference. */
117   vdacRef2V5    = _VDAC_CTRL_REFSEL_2V5,    /**< Internal 2.5 V band gap reference. */
118   vdacRefAvdd   = _VDAC_CTRL_REFSEL_VDD,    /**< AVDD reference. */
119   vdacRefExtPin = _VDAC_CTRL_REFSEL_EXT,    /**< External pin reference. */
120 } VDAC_Ref_TypeDef;
121 
122 /** Peripheral Reflex System signal used to trigger VDAC channel conversion. */
123 typedef enum {
124   vdacPrsSelCh0 =  _VDAC_CH0CTRL_PRSSEL_PRSCH0,  /**< PRS ch 0 triggers conversion. */
125   vdacPrsSelCh1 =  _VDAC_CH0CTRL_PRSSEL_PRSCH1,  /**< PRS ch 1 triggers conversion. */
126   vdacPrsSelCh2 =  _VDAC_CH0CTRL_PRSSEL_PRSCH2,  /**< PRS ch 2 triggers conversion. */
127   vdacPrsSelCh3 =  _VDAC_CH0CTRL_PRSSEL_PRSCH3,  /**< PRS ch 3 triggers conversion. */
128   vdacPrsSelCh4 =  _VDAC_CH0CTRL_PRSSEL_PRSCH4,  /**< PRS ch 4 triggers conversion. */
129   vdacPrsSelCh5 =  _VDAC_CH0CTRL_PRSSEL_PRSCH5,  /**< PRS ch 5 triggers conversion. */
130   vdacPrsSelCh6 =  _VDAC_CH0CTRL_PRSSEL_PRSCH6,  /**< PRS ch 6 triggers conversion. */
131   vdacPrsSelCh7 =  _VDAC_CH0CTRL_PRSSEL_PRSCH7,  /**< PRS ch 7 triggers conversion. */
132 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH8)
133   vdacPrsSelCh8 =  _VDAC_CH0CTRL_PRSSEL_PRSCH8,  /**< PRS ch 8 triggers conversion. */
134 #endif
135 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH9)
136   vdacPrsSelCh9 =  _VDAC_CH0CTRL_PRSSEL_PRSCH9,  /**< PRS ch 9 triggers conversion. */
137 #endif
138 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH10)
139   vdacPrsSelCh10 = _VDAC_CH0CTRL_PRSSEL_PRSCH10, /**< PRS ch 10 triggers conversion. */
140 #endif
141 #if defined(_VDAC_CH0CTRL_PRSSEL_PRSCH11)
142   vdacPrsSelCh11 = _VDAC_CH0CTRL_PRSSEL_PRSCH11, /**< PRS ch 11 triggers conversion. */
143 #endif
144 } VDAC_PrsSel_TypeDef;
145 
146 /** Channel conversion trigger mode. */
147 typedef enum {
148   vdacTrigModeSw        = _VDAC_CH0CTRL_TRIGMODE_SW,        /**< Channel is triggered by CHnDATA or COMBDATA write. */
149   vdacTrigModePrs       = _VDAC_CH0CTRL_TRIGMODE_PRS,       /**< Channel is triggered by PRS input. */
150   vdacTrigModeRefresh   = _VDAC_CH0CTRL_TRIGMODE_REFRESH,   /**< Channel is triggered by Refresh timer. */
151   vdacTrigModeSwPrs     = _VDAC_CH0CTRL_TRIGMODE_SWPRS,     /**< Channel is triggered by CHnDATA/COMBDATA write or PRS input. */
152   vdacTrigModeSwRefresh = _VDAC_CH0CTRL_TRIGMODE_SWREFRESH, /**< Channel is triggered by CHnDATA/COMBDATA write or Refresh timer. */
153   vdacTrigModeLesense   = _VDAC_CH0CTRL_TRIGMODE_LESENSE,   /**< Channel is triggered by LESENSE. */
154 } VDAC_TrigMode_TypeDef;
155 
156 /*******************************************************************************
157  *******************************   STRUCTS   ***********************************
158  ******************************************************************************/
159 
160 /** VDAC initialization structure, common for both channels. */
161 typedef struct {
162   /** Selects between main and alternate output path calibration values. */
163   bool                  mainCalibration;
164 
165   /** Selects clock from asynchronous or synchronous (with respect to
166       peripheral clock) source. */
167   bool                  asyncClockMode;
168 
169   /** Warm-up mode, keep VDAC on (in idle) - or shutdown between conversions.*/
170   bool                  warmupKeepOn;
171 
172   /** Channel refresh period. */
173   VDAC_Refresh_TypeDef  refresh;
174 
175   /** Prescaler for VDAC clock. Clock is source clock divided by prescaler+1. */
176   uint32_t              prescaler;
177 
178   /** Reference voltage to use. */
179   VDAC_Ref_TypeDef      reference;
180 
181   /** Enable/disable reset of prescaler on CH 0 start. */
182   bool                 ch0ResetPre;
183 
184   /** Enable/disable output enable control by CH1 PRS signal. */
185   bool                 outEnablePRS;
186 
187   /** Enable/disable sine mode. */
188   bool                 sineEnable;
189 
190   /** Select if single ended or differential output mode. */
191   bool                 diff;
192 } VDAC_Init_TypeDef;
193 
194 /** Default configuration for VDAC initialization structure. */
195 #define VDAC_INIT_DEFAULT                                                \
196   {                                                                      \
197     true,                 /* Use main output path calibration values. */ \
198     false,                /* Use synchronous clock mode. */              \
199     false,                /* Turn off between sample off conversions.*/  \
200     vdacRefresh8,         /* Refresh every 8th cycle. */                 \
201     0,                    /* No prescaling. */                           \
202     vdacRef1V25Ln,        /* 1.25 V internal low noise reference. */     \
203     false,                /* Do not reset prescaler on CH 0 start. */    \
204     false,                /* VDAC output enable always on. */            \
205     false,                /* Disable sine mode. */                       \
206     false                 /* Single ended mode. */                       \
207   }
208 
209 /** VDAC channel initialization structure. */
210 typedef struct {
211   /** Enable channel. */
212   bool                  enable;
213 
214   /**
215    * Peripheral reflex system trigger selection. Only applicable if @p trigMode
216    * is set to @p vdacTrigModePrs or @p vdacTrigModeSwPrs. */
217   VDAC_PrsSel_TypeDef   prsSel;
218 
219   /** Treat the PRS signal asynchronously. */
220   bool                  prsAsync;
221 
222   /** Channel conversion trigger mode. */
223   VDAC_TrigMode_TypeDef trigMode;
224 
225   /** Set channel conversion mode to sample/shut-off mode. Default is
226    *  continuous.*/
227   bool                  sampleOffMode;
228 } VDAC_InitChannel_TypeDef;
229 
230 /** Default configuration for VDAC channel initialization structure. */
231 #define VDAC_INITCHANNEL_DEFAULT                                                \
232   {                                                                             \
233     false,            /* Leave channel disabled when initialization is done. */ \
234     vdacPrsSelCh0,    /* PRS CH 0 triggers conversion. */                       \
235     false,            /* Treat PRS channel as a synchronous signal. */          \
236     vdacTrigModeSw,   /* Conversion trigged by CH0DATA or COMBDATA write. */    \
237     false,            /* Channel conversion set to continuous. */               \
238   }
239 #else // defined(_SILICON_LABS_32B_SERIES_2)
240 
241 /** Channel refresh period. */
242 typedef enum {
243   vdacRefresh2    = _VDAC_CFG_REFRESHPERIOD_CYCLES2,    /**< Refresh every 2 clock cycles. */
244   vdacRefresh4    = _VDAC_CFG_REFRESHPERIOD_CYCLES4,    /**< Refresh every 4 clock cycles. */
245   vdacRefresh8    = _VDAC_CFG_REFRESHPERIOD_CYCLES8,    /**< Refresh every 8 clock cycles. */
246   vdacRefresh16   = _VDAC_CFG_REFRESHPERIOD_CYCLES16,   /**< Refresh every 16 clock cycles. */
247   vdacRefresh32   = _VDAC_CFG_REFRESHPERIOD_CYCLES32,   /**< Refresh every 32 clock cycles. */
248   vdacRefresh64   = _VDAC_CFG_REFRESHPERIOD_CYCLES64,   /**< Refresh every 64 clock cycles. */
249   vdacRefresh128  = _VDAC_CFG_REFRESHPERIOD_CYCLES128,  /**< Refresh every 128 clock cycles. */
250   vdacRefresh256  = _VDAC_CFG_REFRESHPERIOD_CYCLES256,  /**< Refresh every 256 clock cycles. */
251 } VDAC_Refresh_TypeDef;
252 
253 /** Timer overflow period. */
254 typedef enum {
255   vdacCycles2  = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES2,    /**< Overflows every 2 clock cycles. */
256   vdacCycles4  = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES4,    /**< Overflows every 4 clock cycles. */
257   vdacCycles8  = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES8,    /**< Overflows every 8 clock cycles. */
258   vdacCycles16 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES16,   /**< Overflows every 16 clock cycles. */
259   vdacCycles32 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES32,   /**< Overflows every 32 clock cycles. */
260   vdacCycles64 = _VDAC_CFG_TIMEROVRFLOWPERIOD_CYCLES64    /**< Overflows every 64 clock cycles. */
261 } VDAC_TimerOverflow_TypeDef;
262 
263 /** Reference voltage for VDAC. */
264 typedef enum {
265   vdacRef1V25   = _VDAC_CFG_REFRSEL_V125,   /**< Internal 1.25 V band gap reference. */
266   vdacRef2V5    = _VDAC_CFG_REFRSEL_V25,    /**< Internal 2.5 V band gap reference. */
267   vdacRefAvdd   = _VDAC_CFG_REFRSEL_VDD,    /**< AVDD reference. */
268   vdacRefExtPin = _VDAC_CFG_REFRSEL_EXT,    /**< External pin reference. */
269 } VDAC_Ref_TypeDef;
270 
271 /** Refresh source for VDAC. */
272 typedef enum {
273   vdacRefreshSrcNone          = _VDAC_CH0CFG_REFRESHSOURCE_NONE,        /**< No refresh source. */
274   vdacRefreshSrcRefreshTimer  = _VDAC_CH0CFG_REFRESHSOURCE_REFRESHTIMER,/**< Refresh triggered by refresh timer overflow. */
275   vdacRefreshSrcSyncPrs       = _VDAC_CH0CFG_REFRESHSOURCE_SYNCPRS,     /**< Refresh triggered by sync PRS. */
276   vdacRefreshSrcAsyncPrs      = _VDAC_CH0CFG_REFRESHSOURCE_ASYNCPRS,    /**< Refresh triggered by async PRS. */
277 } VDAC_RefreshSource_TypeDef;
278 
279 /** Channel conversion trigger mode. */
280 typedef enum {
281   vdacTrigModeNone          = _VDAC_CH0CFG_TRIGMODE_NONE,           /**< No conversion trigger source selected. */
282   vdacTrigModeSw            = _VDAC_CH0CFG_TRIGMODE_SW,             /**< Channel is triggered by CHnDATA or COMBDATA write. */
283   vdacTrigModeSyncPrs       = _VDAC_CH0CFG_TRIGMODE_SYNCPRS,        /**< Channel is triggered by Sync PRS input. */
284 #if defined(LESENSE_PRESENT) && defined(_VDAC_CH0CFG_TRIGMODE_LESENSE)
285   vdacTrigModeLesense       = _VDAC_CH0CFG_TRIGMODE_LESENSE,        /**< Channel is triggered by LESENSE. */
286 #endif
287   vdacTrigModeInternalTimer = _VDAC_CH0CFG_TRIGMODE_INTERNALTIMER,  /**< Channel is triggered by Internal Timer. */
288   vdacTrigModeAsyncPrs      = _VDAC_CH0CFG_TRIGMODE_ASYNCPRS        /**< Channel is triggered by Async PRS input. */
289 } VDAC_TrigMode_TypeDef;
290 
291 /** Channel power mode. */
292 typedef enum {
293   vdacPowerModeHighPower    = _VDAC_CH0CFG_POWERMODE_HIGHPOWER,     /**< High power buffer mode. */
294   vdacPowerModeLowPower     = _VDAC_CH0CFG_POWERMODE_LOWPOWER       /**< Low power buffer mode. */
295 } VDAC_PowerMode_TypeDef;
296 
297 /** VDAC channel Abus port selection. */
298 typedef enum {
299   /** No GPIO selected.  */
300   vdacChPortNone    = _VDAC_OUTCTRL_ABUSPORTSELCH0_NONE,
301   /** Port A selected.  */
302   vdacChPortA       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTA,
303   /** Port B selected.  */
304   vdacChPortB       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTB,
305   /** Port C selected.  */
306   vdacChPortC       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTC,
307   /** Port D selected.  */
308   vdacChPortD       = _VDAC_OUTCTRL_ABUSPORTSELCH0_PORTD,
309 } VDAC_ChPortSel_t;
310 
311 /*******************************************************************************
312  *******************************   STRUCTS   ***********************************
313  ******************************************************************************/
314 
315 /** VDAC initialization structure, common for both channels. */
316 typedef struct {
317   /** Number of prescaled CLK_DAC + 1 for the vdac to warmup. */
318   uint32_t                    warmupTime;
319 
320   /** Halt during debug. */
321   bool                        dbgHalt;
322 
323   /** Always allow clk_dac. */
324   bool                        onDemandClk;
325 
326   /** DMA Wakeup. */
327   bool                        dmaWakeUp;
328 
329   /** Bias keep warm enable. */
330   bool                        biasKeepWarm;
331 
332   /** Channel refresh period. */
333   VDAC_Refresh_TypeDef        refresh;
334 
335   /** Internal timer overflow period. */
336   VDAC_TimerOverflow_TypeDef  timerOverflow;
337 
338   /** Prescaler for VDAC clock. Clock is source clock divided by prescaler+1. */
339   uint32_t                    prescaler;
340 
341   /** Reference voltage to use. */
342   VDAC_Ref_TypeDef            reference;
343 
344   /** Enable/disable reset of prescaler on CH 0 start. */
345   bool                        ch0ResetPre;
346 
347   /** Sine reset mode. */
348   bool                        sineReset;
349 
350   /** Enable/disable sine mode. */
351   bool                        sineEnable;
352 
353   /** Select if single ended or differential output mode. */
354   bool                        diff;
355 
356 #if defined(VDAC_CFG_SINEMODEPRS)
357   /**  PRS controlled sinemode enable. */
358   bool                        sineModePrsEnable;
359 #endif
360 #if defined(VDAC_CFG_OUTENPRS)
361   /**  PRS controlled channel output enable. */
362   bool                        prsOutEnable;
363 #endif
364 } VDAC_Init_TypeDef;
365 
366 #if defined(VDAC_CFG_SINEMODEPRS)
367 /** Default configuration for VDAC initialization structure. */
368 #define VDAC_INIT_DEFAULT                                                                            \
369   {                                                                                                  \
370     _VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */              \
371     false,                        /* Continue while debugging. */                                    \
372     false,                        /* On demand clock. */                                             \
373     false,                        /* DMA wake up. */                                                 \
374     false,                        /* Bias keep warm. */                                              \
375     vdacRefresh2,                 /* Refresh every 2th cycle. */                                     \
376     vdacCycles2,                  /* Internal overflow every 2th cycle. */                           \
377     0,                            /* No prescaling. */                                               \
378     vdacRef1V25,                  /* 1.25 V internal low noise reference. */                         \
379     false,                        /* Do not reset prescaler on CH 0 start. */                        \
380     false,                        /* Sine wave is stopped at the sample its currently outputting. */ \
381     false,                        /* Disable sine mode. */                                           \
382     false,                        /* Differential mode. */                                           \
383     false,                        /* PRS controlled sinemode. */                                     \
384     false,                        /* PRS controlled output enable. */                                \
385   }
386 #else
387 /** Default configuration for VDAC initialization structure. */
388 #define VDAC_INIT_DEFAULT                                                                            \
389   {                                                                                                  \
390     _VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */              \
391     false,                        /* Continue while debugging. */                                    \
392     false,                        /* On demand clock. */                                             \
393     false,                        /* DMA wake up. */                                                 \
394     false,                        /* Bias keep warm. */                                              \
395     vdacRefresh2,                 /* Refresh every 2th cycle. */                                     \
396     vdacCycles2,                  /* Internal overflow every 2th cycle. */                           \
397     0,                            /* No prescaling. */                                               \
398     vdacRef1V25,                  /* 1.25 V internal low noise reference. */                         \
399     false,                        /* Do not reset prescaler on CH 0 start. */                        \
400     false,                        /* Sine wave is stopped at the sample its currently outputting. */ \
401     false,                        /* Disable sine mode. */                                           \
402     false,                        /* Differential mode. */                                           \
403   }
404 #endif
405 
406 #if defined(VDAC_CFG_SINEMODEPRS)
407 /** Sine mode configuration for VDAC initialization structure. */
408 #define VDAC_INIT_SINE_GENERATION_MODE                                                               \
409   {                                                                                                  \
410     _VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */              \
411     false,                        /* Continue while debugging. */                                    \
412     true,                         /* On demand clock. */                                             \
413     false,                        /* DMA wake up. */                                                 \
414     false,                        /* Bias keep warm. */                                              \
415     vdacRefresh8,                 /* Refresh every 8th cycle. */                                     \
416     vdacCycles2,                  /* Internal overflow every 8th cycle. */                           \
417     0,                            /* No prescaling. */                                               \
418     vdacRef1V25,                  /* 1.25 V internal low noise reference. */                         \
419     false,                        /* Do not reset prescaler on CH 0 start. */                        \
420     false,                        /* Sine wave is stopped at the sample its currently outputting. */ \
421     true,                         /* Enable sine mode. */                                            \
422     false,                        /* Differential mode. */                                           \
423     false,                        /* PRS controlled sinemode. */                                     \
424     false,                        /* PRS controlled output enable. */                                \
425   }
426 #else
427 /** Sine mode configuration for VDAC initialization structure. */
428 #define VDAC_INIT_SINE_GENERATION_MODE                                                               \
429   {                                                                                                  \
430     _VDAC_CFG_WARMUPTIME_DEFAULT, /* Number of prescaled DAC_CLK for Vdac to warmup. */              \
431     false,                        /* Continue while debugging. */                                    \
432     true,                         /* On demand clock. */                                             \
433     false,                        /* DMA wake up. */                                                 \
434     false,                        /* Bias keep warm. */                                              \
435     vdacRefresh8,                 /* Refresh every 8th cycle. */                                     \
436     vdacCycles2,                  /* Internal overflow every 8th cycle. */                           \
437     0,                            /* No prescaling. */                                               \
438     vdacRef1V25,                  /* 1.25 V internal low noise reference. */                         \
439     false,                        /* Do not reset prescaler on CH 0 start. */                        \
440     false,                        /* Sine wave is stopped at the sample its currently outputting. */ \
441     true,                         /* Enable sine mode. */                                            \
442     false,                        /* Differential mode. */                                           \
443   }
444 #endif
445 
446 /** VDAC channel initialization structure. */
447 typedef struct {
448   /** Enable channel. */
449   bool                        enable;
450 
451   /** Warm-up mode, keep VDAC on (in idle) - or shutdown between conversions.*/
452   bool                        warmupKeepOn;
453 
454   /** Select high capacitance load mode in conjunction with high power. */
455   bool                        highCapLoadEnable;
456 
457   /** Channel x FIFO Low threshold data valid level. */
458   uint32_t                    fifoLowDataThreshold;
459 
460   /** Channel refresh source. */
461   VDAC_RefreshSource_TypeDef  chRefreshSource;
462 
463   /** Channel conversion trigger mode. */
464   VDAC_TrigMode_TypeDef       trigMode;
465 
466   /** Channel power mode. */
467   VDAC_PowerMode_TypeDef      powerMode;
468 
469   /** Set channel conversion mode to sample/shut-off mode. Default is
470    *  continuous.*/
471   bool                        sampleOffMode;
472 
473   /** Vdac channel output pin. */
474   uint32_t                    pin;
475 
476   /** Vdac channel output port. */
477   VDAC_ChPortSel_t            port;
478 
479   /** Short High power and low power output. */
480   bool                        shortOutput;
481 
482   /**  Alternative output enable. */
483   bool                        auxOutEnable;
484 
485   /**  Main output enable. */
486   bool                        mainOutEnable;
487 
488   /**  Channel output hold time. */
489   uint32_t                    holdOutTime;
490 } VDAC_InitChannel_TypeDef;
491 
492 /** Default configuration for VDAC channel initialization structure. */
493 #define VDAC_INITCHANNEL_DEFAULT                                                      \
494   {                                                                                   \
495     false,                  /* Leave channel disabled when initialization is done. */ \
496     false,                  /* Turn off between sample off conversions.*/             \
497     true,                   /* Enable High cap mode. */                               \
498     0,                      /* FIFO data low watermark at 0. */                       \
499     vdacRefreshSrcNone,     /* Channel refresh source. */                             \
500     vdacTrigModeSw,         /* Conversion trigged by CH0DATA or COMBDATA write. */    \
501     vdacPowerModeHighPower, /* High power mode enabled. */                            \
502     false,                  /* Continuous conversion mode. */                         \
503     0,                      /* ABUS pin selected. */                                  \
504     vdacChPortNone,         /* No Analog bus port selected. */                        \
505     false,                  /* Output not shorted */                                  \
506     false,                  /* Alternative output disabled. */                        \
507     true,                   /* Main output enabled. */                                \
508     0,                      /* Hold out time. Previously called settle time */        \
509   }
510 
511 #endif
512 /*******************************************************************************
513  *****************************   PROTOTYPES   **********************************
514  ******************************************************************************/
515 
516 void VDAC_ChannelOutputSet(VDAC_TypeDef *vdac,
517                            unsigned int channel,
518                            uint32_t     value);
519 void VDAC_Enable(VDAC_TypeDef *vdac, unsigned int ch, bool enable);
520 void VDAC_Init(VDAC_TypeDef *vdac, const VDAC_Init_TypeDef *init);
521 void VDAC_InitChannel(VDAC_TypeDef *vdac,
522                       const VDAC_InitChannel_TypeDef *init,
523                       unsigned int ch);
524 
525 #if defined(_SILICON_LABS_32B_SERIES_2)
526 /***************************************************************************//**
527  * @brief
528  *  Start/stop Sinemode.
529  *
530  * @details
531  *   This function sends the sine mode start/stop signal to the DAC.
532  *
533  * @param[in] vdac
534  *   Pointer to VDAC peripheral register block.
535  *
536  * @param[in] start
537  *   True to start the Sine mode, false to stop it.
538  ******************************************************************************/
VDAC_SineModeStart(VDAC_TypeDef * vdac,bool start)539 __STATIC_INLINE void VDAC_SineModeStart(VDAC_TypeDef *vdac, bool start)
540 {
541   EFM_ASSERT(VDAC_REF_VALID(vdac));
542 
543   while (0UL != (vdac->STATUS & VDAC_STATUS_SYNCBUSY)) {
544   }
545 
546   if (start) {
547     vdac->CMD = VDAC_CMD_SINEMODESTART;
548     while (0UL == (vdac->STATUS & VDAC_STATUS_SINEACTIVE)) {
549     }
550   } else {
551     vdac->CMD = VDAC_CMD_SINEMODESTOP;
552     while (0UL != (vdac->STATUS & VDAC_STATUS_SINEACTIVE)) {
553     }
554   }
555 }
556 #endif
557 
558 /***************************************************************************//**
559  * @brief
560  *   Set the output signal of VDAC channel 0 to a given value.
561  *
562  * @details
563  *   This function sets the output signal of VDAC channel 0 by writing @p value
564  *   to the CH0DATA register.
565  *
566  * @param[in] vdac
567  *   Pointer to VDAC peripheral register block.
568  *
569  * @param[in] value
570  *   Value to write to channel 0 output register CH0DATA.
571  ******************************************************************************/
VDAC_Channel0OutputSet(VDAC_TypeDef * vdac,uint32_t value)572 __STATIC_INLINE void VDAC_Channel0OutputSet(VDAC_TypeDef *vdac,
573                                             uint32_t value)
574 {
575 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
576   EFM_ASSERT(value <= _VDAC_CH0DATA_MASK);
577   vdac->CH0DATA = value;
578 #elif defined(_SILICON_LABS_32B_SERIES_2)
579   EFM_ASSERT(value <= _VDAC_CH0F_MASK);
580   vdac->CH0F = value;
581 #endif
582 }
583 
584 /***************************************************************************//**
585  * @brief
586  *   Set the output signal of VDAC channel 1 to a given value.
587  *
588  * @details
589  *   This function sets the output signal of VDAC channel 1 by writing @p value
590  *   to the CH1DATA register.
591  *
592  * @param[in] vdac
593  *   Pointer to VDAC peripheral register block.
594  *
595  * @param[in] value
596  *   Value to write to channel 1 output register CH1DATA.
597  ******************************************************************************/
VDAC_Channel1OutputSet(VDAC_TypeDef * vdac,uint32_t value)598 __STATIC_INLINE void VDAC_Channel1OutputSet(VDAC_TypeDef *vdac,
599                                             uint32_t value)
600 {
601 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
602   EFM_ASSERT(value <= _VDAC_CH1DATA_MASK);
603   vdac->CH1DATA = value;
604 #elif defined(_SILICON_LABS_32B_SERIES_2)
605   EFM_ASSERT(value <= _VDAC_CH1F_MASK);
606   vdac->CH1F = value;
607 #endif
608 }
609 
610 /***************************************************************************//**
611  * @brief
612  *   Clear one or more pending VDAC interrupts.
613  *
614  * @param[in] vdac
615  *   Pointer to VDAC peripheral register block.
616  *
617  * @param[in] flags
618  *   Pending VDAC interrupt source to clear. Use a bitwise logic OR combination
619  *   of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
620  ******************************************************************************/
VDAC_IntClear(VDAC_TypeDef * vdac,uint32_t flags)621 __STATIC_INLINE void VDAC_IntClear(VDAC_TypeDef *vdac, uint32_t flags)
622 {
623 #if defined(VDAC_HAS_SET_CLEAR)
624   vdac->IF_CLR = flags;
625 #else
626   vdac->IFC = flags;
627 #endif
628 }
629 
630 /***************************************************************************//**
631  * @brief
632  *   Disable one or more VDAC interrupts.
633  *
634  * @param[in] vdac
635  *   Pointer to VDAC peripheral register block.
636  *
637  * @param[in] flags
638  *   VDAC interrupt sources to disable. Use a bitwise logic OR combination of
639  *   valid interrupt flags for the VDAC module (VDAC_IF_nnn).
640  ******************************************************************************/
VDAC_IntDisable(VDAC_TypeDef * vdac,uint32_t flags)641 __STATIC_INLINE void VDAC_IntDisable(VDAC_TypeDef *vdac, uint32_t flags)
642 {
643 #if defined(VDAC_HAS_SET_CLEAR)
644   vdac->IEN_CLR = flags;
645 #else
646   vdac->IEN &= ~flags;
647 #endif
648 }
649 
650 /***************************************************************************//**
651  * @brief
652  *   Enable one or more VDAC interrupts.
653  *
654  * @note
655  *   Depending on the use, a pending interrupt may already be set prior to
656  *   enabling the interrupt. To ignore a pending interrupt, consider using
657  *   VDAC_IntClear() prior to enabling the interrupt.
658  *
659  * @param[in] vdac
660  *   Pointer to VDAC peripheral register block.
661  *
662  * @param[in] flags
663  *   VDAC interrupt sources to enable. Use a bitwise logic OR combination
664  *   of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
665  ******************************************************************************/
VDAC_IntEnable(VDAC_TypeDef * vdac,uint32_t flags)666 __STATIC_INLINE void VDAC_IntEnable(VDAC_TypeDef *vdac, uint32_t flags)
667 {
668 #if defined(VDAC_HAS_SET_CLEAR)
669   vdac->IEN_SET = flags;
670 #else
671   vdac->IEN |= flags;
672 #endif
673 }
674 
675 /***************************************************************************//**
676  * @brief
677  *   Get pending VDAC interrupt flags.
678  *
679  * @note
680  *   The event bits are not cleared by the use of this function.
681  *
682  * @param[in] vdac
683  *   Pointer to VDAC peripheral register block.
684  *
685  * @return
686  *   VDAC interrupt sources pending. Use a bitwise logic OR combination
687  *   of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
688  ******************************************************************************/
VDAC_IntGet(VDAC_TypeDef * vdac)689 __STATIC_INLINE uint32_t VDAC_IntGet(VDAC_TypeDef *vdac)
690 {
691   return vdac->IF;
692 }
693 
694 /***************************************************************************//**
695  * @brief
696  *   Get enabled and pending VDAC interrupt flags.
697  *   Useful for handling more interrupt sources in the same interrupt handler.
698  *
699  * @param[in] vdac
700  *   Pointer to VDAC peripheral register block.
701  *
702  * @note
703  *   Interrupt flags are not cleared by the use of this function.
704  *
705  * @return
706  *   Pending and enabled VDAC interrupt sources.
707  *   The return value is the bitwise AND combination of
708  *   - the OR combination of enabled interrupt sources in VDACx_IEN_nnn
709  *     register (VDACx_IEN_nnn) and
710  *   - the OR combination of valid interrupt flags of the VDAC module
711  *     (VDACx_IF_nnn).
712  ******************************************************************************/
VDAC_IntGetEnabled(VDAC_TypeDef * vdac)713 __STATIC_INLINE uint32_t VDAC_IntGetEnabled(VDAC_TypeDef *vdac)
714 {
715   uint32_t ien = vdac->IEN;
716 
717   /* Bitwise AND of pending and enabled interrupts */
718   return vdac->IF & ien;
719 }
720 
721 /***************************************************************************//**
722  * @brief
723  *   Set one or more pending VDAC interrupts from SW.
724  *
725  * @param[in] vdac
726  *   Pointer to VDAC peripheral register block.
727  *
728  * @param[in] flags
729  *   VDAC interrupt sources to set to pending. Use a bitwise logic OR
730  *   combination of valid interrupt flags for the VDAC module (VDAC_IF_nnn).
731  ******************************************************************************/
VDAC_IntSet(VDAC_TypeDef * vdac,uint32_t flags)732 __STATIC_INLINE void VDAC_IntSet(VDAC_TypeDef *vdac, uint32_t flags)
733 {
734 #if defined(VDAC_HAS_SET_CLEAR)
735   vdac->IF_SET = flags;
736 #else
737   vdac->IFS = flags;
738 #endif
739 }
740 
741 #if defined(_SILICON_LABS_32B_SERIES_2)
742 /***************************************************************************//**
743  * @brief
744  *    Get the VDAC Status register.
745  *
746  * @param[in] vdac
747  *   Pointer to VDAC peripheral register block.
748  *
749  * @return
750  *    Current STATUS register value.
751  ******************************************************************************/
VDAC_GetStatus(VDAC_TypeDef * vdac)752 __STATIC_INLINE uint32_t VDAC_GetStatus(VDAC_TypeDef *vdac)
753 {
754   return vdac->STATUS;
755 }
756 #endif
757 
758 #if defined(_SILICON_LABS_32B_SERIES_0) || defined(_SILICON_LABS_32B_SERIES_1)
759 uint32_t VDAC_PrescaleCalc(uint32_t vdacFreq, bool syncMode, uint32_t hfperFreq);
760 #else
761 uint32_t VDAC_PrescaleCalc(VDAC_TypeDef *vdac, uint32_t vdacFreq);
762 #endif
763 
764 void VDAC_Reset(VDAC_TypeDef *vdac);
765 
766 /** @} (end addtogroup vdac) */
767 
768 #ifdef __cplusplus
769 }
770 #endif
771 
772 #endif /* defined(VDAC_COUNT) && (VDAC_COUNT > 0) */
773 #endif /* EM_VDAC_H */
774