1 /***************************************************************************//**
2 * @file
3 * @brief Operational Amplifier (OPAMP) 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 #include "em_opamp.h"
32 #if ((defined(_SILICON_LABS_32B_SERIES_0) && defined(OPAMP_PRESENT) && (OPAMP_COUNT == 1)) \
33 || (defined(_SILICON_LABS_32B_SERIES_1) && defined(VDAC_PRESENT) && (VDAC_COUNT > 0)))
34
35 #include "em_system.h"
36 #include "em_assert.h"
37
38 /* *INDENT-OFF* */
39 /***************************************************************************//**
40 * @addtogroup opamp OPAMP - Operational Amplifier
41 * @brief Operational Amplifier (OPAMP) peripheral API
42 * @details
43 * This module contains functions to:
44 * @li OPAMP_Enable() Configure and enable OPAMP.
45 * @li OPAMP_Disable() Disable OPAMP.
46 *
47 * @if DOXYDOC_P1_DEVICE
48 * All OPAMP functions assume that the DAC clock is running. If DAC is not
49 * used, the clock can be turned off when OPAMPs are configured.
50 * @elseif DOXYDOC_P2_DEVICE
51 * All OPAMP functions assume that the VDAC clock is running. If VDAC is not
52 * used, the clock can be turned off when the OPAMPs are configured.
53 * @endif
54 *
55 * If the available gain values don't suit the application at hand, the resistor
56 * ladders can be disabled and external gain programming resistors used.
57 *
58 * A number of predefined OPAMP setup macros are available for configuration
59 * of the most common OPAMP topologies (see figures below).
60 *
61 * @note
62 * <em>The terms POSPAD and NEGPAD in the figures are used to indicate that these
63 * pads should be connected to a suitable signal ground.</em>
64 *
65 * \n<b>Unity gain voltage follower.</b>\n
66 * @if DOXYDOC_P1_DEVICE
67 * Use predefined macros @ref OPA_INIT_UNITY_GAIN and
68 * @ref OPA_INIT_UNITY_GAIN_OPA2.
69 * @elseif DOXYDOC_P2_DEVICE
70 * Use predefined macro @ref OPA_INIT_UNITY_GAIN.
71 * @endif
72 * @verbatim
73
74 |\
75 ___________|+\
76 | \_______
77 ___|_ / |
78 | | / |
79 | |/ |
80 |___________|
81 @endverbatim
82 *
83 * \n<b>Non-inverting amplifier.</b>\n
84 * @if DOXYDOC_P1_DEVICE
85 * Use predefined macros @ref OPA_INIT_NON_INVERTING and
86 * @ref OPA_INIT_NON_INVERTING_OPA2.
87 * @elseif DOXYDOC_P2_DEVICE
88 * Use predefined macro @ref OPA_INIT_NON_INVERTING.
89 * @endif
90 * @verbatim
91
92 |\
93 ___________|+\
94 | \_______
95 ___|_ / |
96 | | / |
97 | |/ |
98 |_____R2____|
99 |
100 R1
101 |
102 NEGPAD @endverbatim
103 *
104 * \n<b>Inverting amplifier.</b>\n
105 * @if DOXYDOC_P1_DEVICE
106 * Use predefined macros @ref OPA_INIT_INVERTING and
107 * @ref OPA_INIT_INVERTING_OPA2.
108 * @elseif DOXYDOC_P2_DEVICE
109 * Use predefined macro @ref OPA_INIT_INVERTING.
110 * @endif
111 * @verbatim
112
113 _____R2____
114 | |
115 | |\ |
116 ____R1_|___|_\ |
117 | \____|___
118 ___| /
119 | |+/
120 | |/
121 |
122 POSPAD @endverbatim
123 *
124 * \n<b>Cascaded non-inverting amplifiers.</b>\n
125 * Use predefined macros @ref OPA_INIT_CASCADED_NON_INVERTING_OPA0,
126 * @ref OPA_INIT_CASCADED_NON_INVERTING_OPA1 and
127 * @ref OPA_INIT_CASCADED_NON_INVERTING_OPA2.
128 * @verbatim
129
130 |\ |\ |\
131 ___________|+\ OPA0 ___________|+\ OPA1 ___________|+\ OPA2
132 | \_________| | \_________| | \_______
133 ___|_ / | ___|_ / | ___|_ / |
134 | | / | | | / | | | / |
135 | |/ | | |/ | | |/ |
136 |_____R2____| |_____R2____| |_____R2____|
137 | | |
138 R1 R1 R1
139 | | |
140 NEGPAD NEGPAD NEGPAD @endverbatim
141 *
142 * \n<b>Cascaded inverting amplifiers.</b>\n
143 * Use predefined macros @ref OPA_INIT_CASCADED_INVERTING_OPA0,
144 * @ref OPA_INIT_CASCADED_INVERTING_OPA1 and
145 * @ref OPA_INIT_CASCADED_INVERTING_OPA2.
146 * @verbatim
147
148 _____R2____ _____R2____ _____R2____
149 | | | | | |
150 | |\ | | |\ | | |\ |
151 ____R1_|___|_\ | ____R1_|___|_\ | ____R1_|___|_\ |
152 | \____|____| | \____|___| | \____|__
153 ___| / ___| / ___| /
154 | |+/ OPA0 | |+/ OPA1 | |+/ OPA2
155 | |/ | |/ | |/
156 | | |
157 POSPAD POSPAD POSPAD @endverbatim
158 *
159 * \n<b>Differential driver with two opamp's.</b>\n
160 * Use predefined macros @ref OPA_INIT_DIFF_DRIVER_OPA0 and
161 * @ref OPA_INIT_DIFF_DRIVER_OPA1.
162 * @verbatim
163
164 __________________________
165 | +
166 | _____R2____
167 |\ | | |
168 ___________|+\ OPA0 | | |\ OPA1 |
169 | \_________|____R1_|___|_\ | _
170 ___|_ / | | \____|______
171 | | / | ___| /
172 | |/ | | |+/
173 |________________| | |/
174 |
175 POSPAD @endverbatim
176 *
177 * \n<b>Differential receiver with three opamp's.</b>\n
178 * Use predefined macros @ref OPA_INIT_DIFF_RECEIVER_OPA0,
179 * @ref OPA_INIT_DIFF_RECEIVER_OPA1 and @ref OPA_INIT_DIFF_RECEIVER_OPA2.
180 * @verbatim
181
182 |\
183 __________|+\ OPA1
184 _ | \_________
185 ___|_ / | | _____R2____
186 | | / | | | |
187 | |/ | | | |\ |
188 |___________| |____R1_|___|_\ |
189 | \____|___
190 |\ ____R1_ ___| /
191 +__________|+\ OPA0 | | |+/ OPA2
192 | \_________| | |/
193 ___|_ / | R2
194 | | / | |
195 | |/ | NEGPAD OPA0
196 |___________|
197 @endverbatim
198 *
199 * @if DOXYDOC_P2_DEVICE
200 * \n<b>Instrumentation amplifier.</b>\n
201 * Use predefined macros @ref OPA_INIT_INSTR_AMP_OPA0 and
202 * @ref OPA_INIT_INSTR_AMP_OPA1.
203 * @verbatim
204
205 |\
206 __________|+\ OPA1
207 | \______________
208 ___|_ / |
209 | | / |
210 | |/ R2
211 |____________|
212 |
213 R1
214 |
215 R1
216 ____________|
217 | |
218 | R2
219 | |\ |
220 |___|+\ OPA0 |
221 | \_____|________
222 __________|_ /
223 | /
224 |/
225
226 @endverbatim
227 * @endif
228 *
229 * @{
230 ******************************************************************************/
231 /* *INDENT-ON* */
232
233 /*******************************************************************************
234 ************************** GLOBAL FUNCTIONS *******************************
235 ******************************************************************************/
236
237 /***************************************************************************//**
238 * @brief
239 * Disable an Operational Amplifier.
240 *
241 * @if DOXYDOC_P1_DEVICE
242 * @param[in] dac
243 * A pointer to the DAC peripheral register block.
244 * @elseif DOXYDOC_P2_DEVICE
245 * @param[in] dac
246 * A pointer to the VDAC peripheral register block.
247 * @endif
248 *
249 * @param[in] opa
250 * Selects an OPA, valid values are OPA0, OPA1, and OPA2.
251 ******************************************************************************/
OPAMP_Disable(DAC_TypeDef * dac,OPAMP_TypeDef opa)252 void OPAMP_Disable(
253 #if defined(_SILICON_LABS_32B_SERIES_0)
254 DAC_TypeDef *dac,
255 #elif defined(_SILICON_LABS_32B_SERIES_1)
256 VDAC_TypeDef *dac,
257 #endif
258 OPAMP_TypeDef opa)
259 {
260 #if defined(_SILICON_LABS_32B_SERIES_0)
261 EFM_ASSERT(DAC_REF_VALID(dac));
262 EFM_ASSERT(DAC_OPA_VALID(opa));
263
264 if (opa == OPA0) {
265 dac->CH0CTRL &= ~DAC_CH0CTRL_EN;
266 dac->OPACTRL &= ~DAC_OPACTRL_OPA0EN;
267 } else if (opa == OPA1) {
268 dac->CH1CTRL &= ~DAC_CH1CTRL_EN;
269 dac->OPACTRL &= ~DAC_OPACTRL_OPA1EN;
270 } else { /* OPA2 */
271 dac->OPACTRL &= ~DAC_OPACTRL_OPA2EN;
272 }
273
274 #elif defined(_SILICON_LABS_32B_SERIES_1)
275 EFM_ASSERT(VDAC_REF_VALID(dac));
276 EFM_ASSERT(VDAC_OPA_VALID(opa));
277
278 if (opa == OPA0) {
279 #if defined(VDAC_STATUS_OPA0ENS)
280 dac->CMD |= VDAC_CMD_OPA0DIS;
281 while (dac->STATUS & VDAC_STATUS_OPA0ENS) {
282 }
283 #endif
284 #if defined(VDAC_STATUS_OPA1ENS)
285 } else if (opa == OPA1) {
286 dac->CMD |= VDAC_CMD_OPA1DIS;
287 while (dac->STATUS & VDAC_STATUS_OPA1ENS) {
288 }
289 #endif
290 #if defined(VDAC_STATUS_OPA2ENS)
291 } else if (opa == OPA2) {
292 dac->CMD |= VDAC_CMD_OPA2DIS;
293 while (dac->STATUS & VDAC_STATUS_OPA2ENS) {
294 }
295 #endif
296 } else { /* OPA3 */
297 #if defined(VDAC_STATUS_OPA3ENS)
298 dac->CMD |= VDAC_CMD_OPA3DIS;
299 while (dac->STATUS & VDAC_STATUS_OPA3ENS) {
300 }
301 #endif
302 }
303 #endif
304 }
305
306 /***************************************************************************//**
307 * @brief
308 * Configure and enable an Operational Amplifier.
309 *
310 * @if DOXYDOC_P1_DEVICE
311 * @note
312 * The value of the alternate output enable bit mask in the OPAMP_Init_TypeDef
313 * structure should consist of one or more of the
314 * DAC_OPA[opa#]MUX_OUTPEN_OUT[output#] flags
315 * (defined in \<part_name\>_dac.h) OR'ed together. @n @n
316 * For OPA0:
317 * @li DAC_OPA0MUX_OUTPEN_OUT0
318 * @li DAC_OPA0MUX_OUTPEN_OUT1
319 * @li DAC_OPA0MUX_OUTPEN_OUT2
320 * @li DAC_OPA0MUX_OUTPEN_OUT3
321 * @li DAC_OPA0MUX_OUTPEN_OUT4
322 *
323 * For OPA1:
324 * @li DAC_OPA1MUX_OUTPEN_OUT0
325 * @li DAC_OPA1MUX_OUTPEN_OUT1
326 * @li DAC_OPA1MUX_OUTPEN_OUT2
327 * @li DAC_OPA1MUX_OUTPEN_OUT3
328 * @li DAC_OPA1MUX_OUTPEN_OUT4
329 *
330 * For OPA2:
331 * @li DAC_OPA2MUX_OUTPEN_OUT0
332 * @li DAC_OPA2MUX_OUTPEN_OUT1
333 *
334 * E.g: @n
335 * init.outPen = DAC_OPA0MUX_OUTPEN_OUT0 | DAC_OPA0MUX_OUTPEN_OUT4;
336 *
337 * @param[in] dac
338 * A pointer to the DAC peripheral register block.
339 * @elseif DOXYDOC_P2_DEVICE
340 * @note
341 * The value of the alternate output enable bit mask in the OPAMP_Init_TypeDef
342 * structure should consist of one or more of the
343 * VDAC_OPA_OUT_ALTOUTPADEN_OUT[output#] flags
344 * (defined in \<part_name\>_vdac.h) OR'ed together. @n @n
345 * @li VDAC_OPA_OUT_ALTOUTPADEN_OUT0
346 * @li VDAC_OPA_OUT_ALTOUTPADEN_OUT1
347 * @li VDAC_OPA_OUT_ALTOUTPADEN_OUT2
348 * @li VDAC_OPA_OUT_ALTOUTPADEN_OUT3
349 * @li VDAC_OPA_OUT_ALTOUTPADEN_OUT4
350 *
351 * For example: @n
352 * init.outPen = VDAC_OPA_OUT_ALTOUTPADEN_OUT0 | VDAC_OPA_OUT_ALTOUTPADEN_OUT4;
353 * @param[in] dac
354 * A pointer to the VDAC peripheral register block.
355 * @endif
356 *
357 * @param[in] opa
358 * Selects an OPA, valid values are OPA0, OPA1, and OPA2.
359 *
360 * @param[in] init
361 * A pointer to a structure containing OPAMP initialization information.
362 ******************************************************************************/
OPAMP_Enable(DAC_TypeDef * dac,OPAMP_TypeDef opa,const OPAMP_Init_TypeDef * init)363 void OPAMP_Enable(
364 #if defined(_SILICON_LABS_32B_SERIES_0)
365 DAC_TypeDef *dac,
366 #elif defined(_SILICON_LABS_32B_SERIES_1)
367 VDAC_TypeDef *dac,
368 #endif
369 OPAMP_TypeDef opa,
370 const OPAMP_Init_TypeDef *init)
371 {
372 #if defined(_SILICON_LABS_32B_SERIES_0)
373 uint32_t gain;
374
375 EFM_ASSERT(DAC_REF_VALID(dac));
376 EFM_ASSERT(DAC_OPA_VALID(opa));
377 EFM_ASSERT(init->bias <= (_DAC_BIASPROG_BIASPROG_MASK
378 >> _DAC_BIASPROG_BIASPROG_SHIFT));
379
380 if (opa == OPA0) {
381 EFM_ASSERT((init->outPen & ~_DAC_OPA0MUX_OUTPEN_MASK) == 0);
382
383 dac->BIASPROG = (dac->BIASPROG
384 & ~(_DAC_BIASPROG_BIASPROG_MASK
385 | DAC_BIASPROG_HALFBIAS))
386 | (init->bias << _DAC_BIASPROG_BIASPROG_SHIFT)
387 | (init->halfBias ? DAC_BIASPROG_HALFBIAS : 0);
388
389 if (init->defaultOffset) {
390 gain = dac->CAL & _DAC_CAL_GAIN_MASK;
391 SYSTEM_GetCalibrationValue(&dac->CAL);
392 dac->CAL = (dac->CAL & ~_DAC_CAL_GAIN_MASK) | gain;
393 } else {
394 EFM_ASSERT(init->offset <= (_DAC_CAL_CH0OFFSET_MASK
395 >> _DAC_CAL_CH0OFFSET_SHIFT));
396
397 dac->CAL = (dac->CAL & ~_DAC_CAL_CH0OFFSET_MASK)
398 | (init->offset << _DAC_CAL_CH0OFFSET_SHIFT);
399 }
400
401 dac->OPA0MUX = (uint32_t)init->resSel
402 | (uint32_t)init->outMode
403 | init->outPen
404 | (uint32_t)init->resInMux
405 | (uint32_t)init->negSel
406 | (uint32_t)init->posSel
407 | (init->nextOut ? DAC_OPA0MUX_NEXTOUT : 0)
408 | (init->npEn ? DAC_OPA0MUX_NPEN : 0)
409 | (init->ppEn ? DAC_OPA0MUX_PPEN : 0);
410
411 dac->CH0CTRL |= DAC_CH0CTRL_EN;
412 dac->OPACTRL = (dac->OPACTRL
413 & ~(DAC_OPACTRL_OPA0SHORT
414 | _DAC_OPACTRL_OPA0LPFDIS_MASK
415 | DAC_OPACTRL_OPA0HCMDIS))
416 | (init->shortInputs ? DAC_OPACTRL_OPA0SHORT : 0)
417 | (init->lpfPosPadDisable
418 ? DAC_OPACTRL_OPA0LPFDIS_PLPFDIS : 0)
419 | (init->lpfNegPadDisable
420 ? DAC_OPACTRL_OPA0LPFDIS_NLPFDIS : 0)
421 | (init->hcmDisable ? DAC_OPACTRL_OPA0HCMDIS : 0)
422 | DAC_OPACTRL_OPA0EN;
423 } else if ( opa == OPA1 ) {
424 EFM_ASSERT((init->outPen & ~_DAC_OPA1MUX_OUTPEN_MASK) == 0);
425
426 dac->BIASPROG = (dac->BIASPROG
427 & ~(_DAC_BIASPROG_BIASPROG_MASK
428 | DAC_BIASPROG_HALFBIAS))
429 | (init->bias << _DAC_BIASPROG_BIASPROG_SHIFT)
430 | (init->halfBias ? DAC_BIASPROG_HALFBIAS : 0);
431
432 if (init->defaultOffset) {
433 gain = dac->CAL & _DAC_CAL_GAIN_MASK;
434 SYSTEM_GetCalibrationValue(&dac->CAL);
435 dac->CAL = (dac->CAL & ~_DAC_CAL_GAIN_MASK) | gain;
436 } else {
437 EFM_ASSERT(init->offset <= (_DAC_CAL_CH1OFFSET_MASK
438 >> _DAC_CAL_CH1OFFSET_SHIFT));
439
440 dac->CAL = (dac->CAL & ~_DAC_CAL_CH1OFFSET_MASK)
441 | (init->offset << _DAC_CAL_CH1OFFSET_SHIFT);
442 }
443
444 dac->OPA1MUX = (uint32_t)init->resSel
445 | (uint32_t)init->outMode
446 | init->outPen
447 | (uint32_t)init->resInMux
448 | (uint32_t)init->negSel
449 | (uint32_t)init->posSel
450 | (init->nextOut ? DAC_OPA1MUX_NEXTOUT : 0)
451 | (init->npEn ? DAC_OPA1MUX_NPEN : 0)
452 | (init->ppEn ? DAC_OPA1MUX_PPEN : 0);
453
454 dac->CH1CTRL |= DAC_CH1CTRL_EN;
455 dac->OPACTRL = (dac->OPACTRL
456 & ~(DAC_OPACTRL_OPA1SHORT
457 | _DAC_OPACTRL_OPA1LPFDIS_MASK
458 | DAC_OPACTRL_OPA1HCMDIS))
459 | (init->shortInputs ? DAC_OPACTRL_OPA1SHORT : 0)
460 | (init->lpfPosPadDisable
461 ? DAC_OPACTRL_OPA1LPFDIS_PLPFDIS : 0)
462 | (init->lpfNegPadDisable
463 ? DAC_OPACTRL_OPA1LPFDIS_NLPFDIS : 0)
464 | (init->hcmDisable ? DAC_OPACTRL_OPA1HCMDIS : 0)
465 | DAC_OPACTRL_OPA1EN;
466 } else { /* OPA2 */
467 EFM_ASSERT((init->posSel == DAC_OPA2MUX_POSSEL_DISABLE)
468 || (init->posSel == DAC_OPA2MUX_POSSEL_POSPAD)
469 || (init->posSel == DAC_OPA2MUX_POSSEL_OPA1INP)
470 || (init->posSel == DAC_OPA2MUX_POSSEL_OPATAP));
471
472 EFM_ASSERT((init->outMode & ~DAC_OPA2MUX_OUTMODE) == 0);
473
474 EFM_ASSERT((init->outPen & ~_DAC_OPA2MUX_OUTPEN_MASK) == 0);
475
476 dac->BIASPROG = (dac->BIASPROG
477 & ~(_DAC_BIASPROG_OPA2BIASPROG_MASK
478 | DAC_BIASPROG_OPA2HALFBIAS))
479 | (init->bias << _DAC_BIASPROG_OPA2BIASPROG_SHIFT)
480 | (init->halfBias ? DAC_BIASPROG_OPA2HALFBIAS : 0);
481
482 if (init->defaultOffset) {
483 SYSTEM_GetCalibrationValue(&dac->OPAOFFSET);
484 } else {
485 EFM_ASSERT(init->offset <= (_DAC_OPAOFFSET_OPA2OFFSET_MASK
486 >> _DAC_OPAOFFSET_OPA2OFFSET_SHIFT));
487 dac->OPAOFFSET = (dac->OPAOFFSET & ~_DAC_OPAOFFSET_OPA2OFFSET_MASK)
488 | (init->offset << _DAC_OPAOFFSET_OPA2OFFSET_SHIFT);
489 }
490
491 dac->OPA2MUX = (uint32_t)init->resSel
492 | (uint32_t)init->outMode
493 | init->outPen
494 | (uint32_t)init->resInMux
495 | (uint32_t)init->negSel
496 | (uint32_t)init->posSel
497 | (init->nextOut ? DAC_OPA2MUX_NEXTOUT : 0)
498 | (init->npEn ? DAC_OPA2MUX_NPEN : 0)
499 | (init->ppEn ? DAC_OPA2MUX_PPEN : 0);
500
501 dac->OPACTRL = (dac->OPACTRL
502 & ~(DAC_OPACTRL_OPA2SHORT
503 | _DAC_OPACTRL_OPA2LPFDIS_MASK
504 | DAC_OPACTRL_OPA2HCMDIS))
505 | (init->shortInputs ? DAC_OPACTRL_OPA2SHORT : 0)
506 | (init->lpfPosPadDisable
507 ? DAC_OPACTRL_OPA2LPFDIS_PLPFDIS : 0)
508 | (init->lpfNegPadDisable
509 ? DAC_OPACTRL_OPA2LPFDIS_NLPFDIS : 0)
510 | (init->hcmDisable ? DAC_OPACTRL_OPA2HCMDIS : 0)
511 | DAC_OPACTRL_OPA2EN;
512 }
513
514 #elif defined(_SILICON_LABS_32B_SERIES_1)
515 uint32_t calData = 0;
516 uint32_t warmupTime;
517
518 EFM_ASSERT(VDAC_REF_VALID(dac));
519 EFM_ASSERT(VDAC_OPA_VALID(opa));
520 EFM_ASSERT(init->settleTime <= (_VDAC_OPA_TIMER_SETTLETIME_MASK
521 >> _VDAC_OPA_TIMER_SETTLETIME_SHIFT));
522 EFM_ASSERT(init->startupDly <= (_VDAC_OPA_TIMER_STARTUPDLY_MASK
523 >> _VDAC_OPA_TIMER_STARTUPDLY_SHIFT));
524 EFM_ASSERT((init->outPen & ~_VDAC_OPA_OUT_ALTOUTPADEN_MASK) == 0);
525 EFM_ASSERT(!((init->gain3xEn == true)
526 && ((init->negSel == opaNegSelResTap)
527 || (init->posSel == opaPosSelResTap))));
528 EFM_ASSERT((init->drvStr == opaDrvStrLowerAccLowStr)
529 || (init->drvStr == opaDrvStrLowAccLowStr)
530 || (init->drvStr == opaDrvStrHighAccHighStr)
531 || (init->drvStr == opaDrvStrHigherAccHighStr));
532
533 /* Disable OPAMP before writing to registers. */
534 OPAMP_Disable(dac, opa);
535
536 /* Get the calibration value based on OPAMP, Drive Strength, and INCBW. */
537 switch (opa) {
538 #if defined(VDAC_STATUS_OPA0ENS)
539 case OPA0:
540 switch (init->drvStr) {
541 case opaDrvStrLowerAccLowStr:
542 calData = (init->ugBwScale ? DEVINFO->OPA0CAL0 : DEVINFO->OPA0CAL4);
543 break;
544 case opaDrvStrLowAccLowStr:
545 calData = (init->ugBwScale ? DEVINFO->OPA0CAL1 : DEVINFO->OPA0CAL5);
546 break;
547 case opaDrvStrHighAccHighStr:
548 calData = (init->ugBwScale ? DEVINFO->OPA0CAL2 : DEVINFO->OPA0CAL6);
549 break;
550 case opaDrvStrHigherAccHighStr:
551 calData = (init->ugBwScale ? DEVINFO->OPA0CAL3 : DEVINFO->OPA0CAL7);
552 break;
553 }
554 break;
555 #endif
556
557 #if defined(VDAC_STATUS_OPA1ENS)
558 case OPA1:
559 switch (init->drvStr) {
560 case opaDrvStrLowerAccLowStr:
561 calData = (init->ugBwScale ? DEVINFO->OPA1CAL0 : DEVINFO->OPA1CAL4);
562 break;
563 case opaDrvStrLowAccLowStr:
564 calData = (init->ugBwScale ? DEVINFO->OPA1CAL1 : DEVINFO->OPA1CAL5);
565 break;
566 case opaDrvStrHighAccHighStr:
567 calData = (init->ugBwScale ? DEVINFO->OPA1CAL2 : DEVINFO->OPA1CAL6);
568 break;
569 case opaDrvStrHigherAccHighStr:
570 calData = (init->ugBwScale ? DEVINFO->OPA1CAL3 : DEVINFO->OPA1CAL7);
571 break;
572 }
573 break;
574 #endif
575
576 #if defined(VDAC_STATUS_OPA2ENS)
577 case OPA2:
578 switch (init->drvStr) {
579 case opaDrvStrLowerAccLowStr:
580 calData = (init->ugBwScale ? DEVINFO->OPA2CAL0 : DEVINFO->OPA2CAL4);
581 break;
582 case opaDrvStrLowAccLowStr:
583 calData = (init->ugBwScale ? DEVINFO->OPA2CAL1 : DEVINFO->OPA2CAL5);
584 break;
585 case opaDrvStrHighAccHighStr:
586 calData = (init->ugBwScale ? DEVINFO->OPA2CAL2 : DEVINFO->OPA2CAL6);
587 break;
588 case opaDrvStrHigherAccHighStr:
589 calData = (init->ugBwScale ? DEVINFO->OPA2CAL3 : DEVINFO->OPA2CAL7);
590 break;
591 }
592 break;
593 #endif
594
595 #if defined(VDAC_STATUS_OPA3ENS)
596 case OPA3:
597 switch (init->drvStr) {
598 case opaDrvStrLowerAccLowStr:
599 calData = (init->ugBwScale ? DEVINFO->OPA3CAL0 : DEVINFO->OPA3CAL4);
600 break;
601 case opaDrvStrLowAccLowStr:
602 calData = (init->ugBwScale ? DEVINFO->OPA3CAL1 : DEVINFO->OPA3CAL5);
603 break;
604 case opaDrvStrHighAccHighStr:
605 calData = (init->ugBwScale ? DEVINFO->OPA3CAL2 : DEVINFO->OPA3CAL6);
606 break;
607 case opaDrvStrHigherAccHighStr:
608 calData = (init->ugBwScale ? DEVINFO->OPA3CAL3 : DEVINFO->OPA3CAL7);
609 break;
610 }
611 break;
612 #endif
613 }
614 if (!init->defaultOffsetN) {
615 EFM_ASSERT(init->offsetN <= (_VDAC_OPA_CAL_OFFSETN_MASK
616 >> _VDAC_OPA_CAL_OFFSETN_SHIFT));
617 calData = (calData & ~_VDAC_OPA_CAL_OFFSETN_MASK)
618 | (init->offsetN << _VDAC_OPA_CAL_OFFSETN_SHIFT);
619 }
620 if (!init->defaultOffsetP) {
621 EFM_ASSERT(init->offsetP <= (_VDAC_OPA_CAL_OFFSETP_MASK
622 >> _VDAC_OPA_CAL_OFFSETP_SHIFT));
623 calData = (calData & ~_VDAC_OPA_CAL_OFFSETP_MASK)
624 | (init->offsetP << _VDAC_OPA_CAL_OFFSETP_SHIFT);
625 }
626
627 dac->OPA[opa].CAL = (calData & _VDAC_OPA_CAL_MASK);
628
629 dac->OPA[opa].MUX = (uint32_t)init->resSel
630 | (init->gain3xEn ? VDAC_OPA_MUX_GAIN3X : 0)
631 | (uint32_t)init->resInMux
632 | (uint32_t)init->negSel
633 | (uint32_t)init->posSel;
634
635 dac->OPA[opa].OUT = (uint32_t)init->outMode
636 | (uint32_t)init->outPen;
637
638 switch (init->drvStr) {
639 case opaDrvStrHigherAccHighStr:
640 warmupTime = 6;
641 break;
642
643 case opaDrvStrHighAccHighStr:
644 warmupTime = 8;
645 break;
646
647 case opaDrvStrLowAccLowStr:
648 warmupTime = 85;
649 break;
650
651 case opaDrvStrLowerAccLowStr:
652 default:
653 warmupTime = 100;
654 break;
655 }
656
657 dac->OPA[opa].TIMER = (uint32_t)(init->settleTime
658 << _VDAC_OPA_TIMER_SETTLETIME_SHIFT)
659 | (uint32_t)(warmupTime
660 << _VDAC_OPA_TIMER_WARMUPTIME_SHIFT)
661 | (uint32_t)(init->startupDly
662 << _VDAC_OPA_TIMER_STARTUPDLY_SHIFT);
663
664 dac->OPA[opa].CTRL = (init->aportYMasterDisable
665 ? VDAC_OPA_CTRL_APORTYMASTERDIS : 0)
666 | (init->aportXMasterDisable
667 ? VDAC_OPA_CTRL_APORTXMASTERDIS : 0)
668 | (uint32_t)init->prsOutSel
669 | (uint32_t)init->prsSel
670 | (uint32_t)init->prsMode
671 | (init->prsEn ? VDAC_OPA_CTRL_PRSEN : 0)
672 | (init->halfDrvStr
673 ? VDAC_OPA_CTRL_OUTSCALE_HALF
674 : VDAC_OPA_CTRL_OUTSCALE_FULL)
675 | (init->hcmDisable ? VDAC_OPA_CTRL_HCMDIS : 0)
676 | (init->ugBwScale ? VDAC_OPA_CTRL_INCBW : 0)
677 | (uint32_t)init->drvStr;
678
679 if (opa == OPA0) {
680 #if defined(VDAC_STATUS_OPA0ENS)
681 dac->CMD |= VDAC_CMD_OPA0EN;
682 #endif
683 #if defined(VDAC_STATUS_OPA1ENS)
684 } else if (opa == OPA1) {
685 dac->CMD |= VDAC_CMD_OPA1EN;
686 #endif
687 #if defined(VDAC_STATUS_OPA2ENS)
688 } else if (opa == OPA2) {
689 dac->CMD |= VDAC_CMD_OPA2EN;
690 #endif
691 #if defined(VDAC_STATUS_OPA3ENS)
692 } else { /* OPA3 */
693 dac->CMD |= VDAC_CMD_OPA3EN;
694 #endif
695 }
696
697 #endif
698 }
699
700 /** @} (end addtogroup opamp) */
701
702 #endif /* (defined(OPAMP_PRESENT) && (OPAMP_COUNT == 1)
703 || defined(VDAC_PRESENT) && (VDAC_COUNT > 0) */
704