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