EFR32 Mighty Gecko 1 Software Documentation  efr32mg1-doc-5.1.2
em_opamp.c
Go to the documentation of this file.
1 /**************************************************************************/
33 #include "em_opamp.h"
34 #if ((defined(_SILICON_LABS_32B_SERIES_0) && defined(OPAMP_PRESENT) && (OPAMP_COUNT == 1)) \
35  || (defined(_SILICON_LABS_32B_SERIES_1) && defined(VDAC_PRESENT) && (VDAC_COUNT > 0)))
36 
37 #include "em_system.h"
38 #include "em_assert.h"
39 
40 /***************************************************************************/
46 /***************************************************************************/
239 /*******************************************************************************
240  ************************** GLOBAL FUNCTIONS *******************************
241  ******************************************************************************/
242 
243 /***************************************************************************/
259 void OPAMP_Disable(
260 #if defined(_SILICON_LABS_32B_SERIES_0)
261  DAC_TypeDef *dac,
262 #elif defined(_SILICON_LABS_32B_SERIES_1)
263  VDAC_TypeDef *dac,
264 #endif
265  OPAMP_TypeDef opa)
266 {
267 #if defined(_SILICON_LABS_32B_SERIES_0)
268  EFM_ASSERT(DAC_REF_VALID(dac));
269  EFM_ASSERT(DAC_OPA_VALID(opa));
270 
271  if (opa == OPA0)
272  {
273  dac->CH0CTRL &= ~DAC_CH0CTRL_EN;
274  dac->OPACTRL &= ~DAC_OPACTRL_OPA0EN;
275  }
276  else if (opa == OPA1)
277  {
278  dac->CH1CTRL &= ~DAC_CH1CTRL_EN;
279  dac->OPACTRL &= ~DAC_OPACTRL_OPA1EN;
280  }
281  else /* OPA2 */
282  {
283  dac->OPACTRL &= ~DAC_OPACTRL_OPA2EN;
284  }
285 
286 #elif defined(_SILICON_LABS_32B_SERIES_1)
287  EFM_ASSERT(VDAC_REF_VALID(dac));
288  EFM_ASSERT(VDAC_OPA_VALID(opa));
289 
290  if (opa == OPA0)
291  {
292  dac->CMD |= VDAC_CMD_OPA0DIS;
293  while (dac->STATUS & VDAC_STATUS_OPA0ENS)
294  {
295  }
296  }
297  else if (opa == OPA1)
298  {
299  dac->CMD |= VDAC_CMD_OPA1DIS;
300  while (dac->STATUS & VDAC_STATUS_OPA1ENS)
301  {
302  }
303  }
304  else /* OPA2 */
305  {
306  dac->CMD |= VDAC_CMD_OPA2DIS;
307  while (dac->STATUS & VDAC_STATUS_OPA2ENS)
308  {
309  }
310  }
311 #endif
312 }
313 
314 
315 /***************************************************************************/
372 void OPAMP_Enable(
373 #if defined(_SILICON_LABS_32B_SERIES_0)
374  DAC_TypeDef *dac,
375 #elif defined(_SILICON_LABS_32B_SERIES_1)
376  VDAC_TypeDef *dac,
377 #endif
378  OPAMP_TypeDef opa,
379  const OPAMP_Init_TypeDef *init)
380 {
381 #if defined(_SILICON_LABS_32B_SERIES_0)
382  uint32_t offset;
383 
384  EFM_ASSERT(DAC_REF_VALID(dac));
385  EFM_ASSERT(DAC_OPA_VALID(opa));
386  EFM_ASSERT(init->bias <= (_DAC_BIASPROG_BIASPROG_MASK
387  >> _DAC_BIASPROG_BIASPROG_SHIFT));
388 
389  if (opa == OPA0)
390  {
391  EFM_ASSERT((init->outPen & ~_DAC_OPA0MUX_OUTPEN_MASK) == 0);
392 
393  dac->BIASPROG = (dac->BIASPROG
394  & ~(_DAC_BIASPROG_BIASPROG_MASK
395  | DAC_BIASPROG_HALFBIAS))
396  | (init->bias << _DAC_BIASPROG_BIASPROG_SHIFT)
397  | (init->halfBias ? DAC_BIASPROG_HALFBIAS : 0);
398 
399  if (init->defaultOffset)
400  {
401  offset = SYSTEM_GetCalibrationValue(&dac->CAL);
402  dac->CAL = (dac->CAL & ~_DAC_CAL_CH0OFFSET_MASK)
403  | (offset & _DAC_CAL_CH0OFFSET_MASK);
404  }
405  else
406  {
407  EFM_ASSERT(init->offset <= (_DAC_CAL_CH0OFFSET_MASK
408  >> _DAC_CAL_CH0OFFSET_SHIFT));
409 
410  dac->CAL = (dac->CAL & ~_DAC_CAL_CH0OFFSET_MASK)
411  | (init->offset << _DAC_CAL_CH0OFFSET_SHIFT);
412  }
413 
414  dac->OPA0MUX = (uint32_t)init->resSel
415  | (uint32_t)init->outMode
416  | init->outPen
417  | (uint32_t)init->resInMux
418  | (uint32_t)init->negSel
419  | (uint32_t)init->posSel
420  | ( init->nextOut ? DAC_OPA0MUX_NEXTOUT : 0)
421  | ( init->npEn ? DAC_OPA0MUX_NPEN : 0)
422  | ( init->ppEn ? DAC_OPA0MUX_PPEN : 0);
423 
424  dac->CH0CTRL |= DAC_CH0CTRL_EN;
425  dac->OPACTRL = (dac->OPACTRL
426  & ~(DAC_OPACTRL_OPA0SHORT
427  | _DAC_OPACTRL_OPA0LPFDIS_MASK
428  | DAC_OPACTRL_OPA0HCMDIS))
429  | (init->shortInputs ? DAC_OPACTRL_OPA0SHORT : 0)
430  | (init->lpfPosPadDisable
431  ? DAC_OPACTRL_OPA0LPFDIS_PLPFDIS : 0)
432  | (init->lpfNegPadDisable
433  ? DAC_OPACTRL_OPA0LPFDIS_NLPFDIS : 0)
434  | (init->hcmDisable ? DAC_OPACTRL_OPA0HCMDIS : 0)
435  | DAC_OPACTRL_OPA0EN;
436  }
437  else if ( opa == OPA1 )
438  {
439  EFM_ASSERT((init->outPen & ~_DAC_OPA1MUX_OUTPEN_MASK) == 0);
440 
441  dac->BIASPROG = (dac->BIASPROG
442  & ~(_DAC_BIASPROG_BIASPROG_MASK
443  | DAC_BIASPROG_HALFBIAS))
444  | (init->bias << _DAC_BIASPROG_BIASPROG_SHIFT)
445  | (init->halfBias ? DAC_BIASPROG_HALFBIAS : 0 );
446 
447  if (init->defaultOffset)
448  {
449  offset = SYSTEM_GetCalibrationValue(&dac->CAL);
450  dac->CAL = (dac->CAL & ~_DAC_CAL_CH1OFFSET_MASK)
451  | (offset & _DAC_CAL_CH1OFFSET_MASK);
452  }
453  else
454  {
455  EFM_ASSERT(init->offset <= (_DAC_CAL_CH1OFFSET_MASK
456  >> _DAC_CAL_CH1OFFSET_SHIFT));
457 
458  dac->CAL = (dac->CAL & ~_DAC_CAL_CH1OFFSET_MASK)
459  | (init->offset << _DAC_CAL_CH1OFFSET_SHIFT);
460  }
461 
462  dac->OPA1MUX = (uint32_t)init->resSel
463  | (uint32_t)init->outMode
464  | init->outPen
465  | (uint32_t)init->resInMux
466  | (uint32_t)init->negSel
467  | (uint32_t)init->posSel
468  | (init->nextOut ? DAC_OPA1MUX_NEXTOUT : 0)
469  | (init->npEn ? DAC_OPA1MUX_NPEN : 0)
470  | (init->ppEn ? DAC_OPA1MUX_PPEN : 0);
471 
472  dac->CH1CTRL |= DAC_CH1CTRL_EN;
473  dac->OPACTRL = (dac->OPACTRL
474  & ~(DAC_OPACTRL_OPA1SHORT
475  | _DAC_OPACTRL_OPA1LPFDIS_MASK
476  | DAC_OPACTRL_OPA1HCMDIS))
477  | (init->shortInputs ? DAC_OPACTRL_OPA1SHORT : 0)
478  | (init->lpfPosPadDisable
479  ? DAC_OPACTRL_OPA1LPFDIS_PLPFDIS : 0)
480  | (init->lpfNegPadDisable
481  ? DAC_OPACTRL_OPA1LPFDIS_NLPFDIS : 0)
482  | (init->hcmDisable ? DAC_OPACTRL_OPA1HCMDIS : 0)
483  | DAC_OPACTRL_OPA1EN;
484  }
485  else /* OPA2 */
486  {
487  EFM_ASSERT((init->posSel == DAC_OPA2MUX_POSSEL_DISABLE)
488  || (init->posSel == DAC_OPA2MUX_POSSEL_POSPAD)
489  || (init->posSel == DAC_OPA2MUX_POSSEL_OPA1INP)
490  || (init->posSel == DAC_OPA2MUX_POSSEL_OPATAP));
491 
492  EFM_ASSERT((init->outMode & ~DAC_OPA2MUX_OUTMODE) == 0);
493 
494  EFM_ASSERT((init->outPen & ~_DAC_OPA2MUX_OUTPEN_MASK) == 0);
495 
496  dac->BIASPROG = (dac->BIASPROG
497  & ~(_DAC_BIASPROG_OPA2BIASPROG_MASK
498  | DAC_BIASPROG_OPA2HALFBIAS))
499  | (init->bias << _DAC_BIASPROG_OPA2BIASPROG_SHIFT)
500  | (init->halfBias ? DAC_BIASPROG_OPA2HALFBIAS : 0);
501 
502  if (init->defaultOffset)
503  {
504  offset = SYSTEM_GetCalibrationValue(&dac->OPAOFFSET);
505  dac->OPAOFFSET = (dac->OPAOFFSET & ~_DAC_OPAOFFSET_OPA2OFFSET_MASK)
506  | (offset & _DAC_OPAOFFSET_OPA2OFFSET_MASK);
507  }
508  else
509  {
510  EFM_ASSERT(init->offset <= (_DAC_OPAOFFSET_OPA2OFFSET_MASK
511  >> _DAC_OPAOFFSET_OPA2OFFSET_SHIFT));
512  dac->OPAOFFSET = (dac->OPAOFFSET & ~_DAC_OPAOFFSET_OPA2OFFSET_MASK)
513  | (init->offset << _DAC_OPAOFFSET_OPA2OFFSET_SHIFT);
514  }
515 
516  dac->OPA2MUX = (uint32_t)init->resSel
517  | (uint32_t)init->outMode
518  | init->outPen
519  | (uint32_t)init->resInMux
520  | (uint32_t)init->negSel
521  | (uint32_t)init->posSel
522  | ( init->nextOut ? DAC_OPA2MUX_NEXTOUT : 0 )
523  | ( init->npEn ? DAC_OPA2MUX_NPEN : 0 )
524  | ( init->ppEn ? DAC_OPA2MUX_PPEN : 0 );
525 
526  dac->OPACTRL = (dac->OPACTRL
527  & ~(DAC_OPACTRL_OPA2SHORT
528  | _DAC_OPACTRL_OPA2LPFDIS_MASK
529  | DAC_OPACTRL_OPA2HCMDIS))
530  | (init->shortInputs ? DAC_OPACTRL_OPA2SHORT : 0)
531  | (init->lpfPosPadDisable
532  ? DAC_OPACTRL_OPA2LPFDIS_PLPFDIS : 0)
533  | (init->lpfNegPadDisable
534  ? DAC_OPACTRL_OPA2LPFDIS_NLPFDIS : 0)
535  | (init->hcmDisable ? DAC_OPACTRL_OPA2HCMDIS : 0)
536  | DAC_OPACTRL_OPA2EN;
537  }
538 
539 #elif defined(_SILICON_LABS_32B_SERIES_1)
540  uint32_t calData = 0;
541  uint32_t warmupTime;
542 
543  EFM_ASSERT(VDAC_REF_VALID(dac));
544  EFM_ASSERT(VDAC_OPA_VALID(opa));
545  EFM_ASSERT(init->settleTime <= (_VDAC_OPA_TIMER_SETTLETIME_MASK
546  >> _VDAC_OPA_TIMER_SETTLETIME_SHIFT));
547  EFM_ASSERT(init->startupDly <= (_VDAC_OPA_TIMER_STARTUPDLY_MASK
548  >> _VDAC_OPA_TIMER_STARTUPDLY_SHIFT));
549  EFM_ASSERT((init->outPen & ~_VDAC_OPA_OUT_ALTOUTPADEN_MASK) == 0);
550  EFM_ASSERT(!((init->gain3xEn == true)
551  && ((init->negSel == opaNegSelResTap)
552  || (init->posSel == opaPosSelResTap))));
553  EFM_ASSERT((init->drvStr == opaDrvStrLowerAccLowStr)
554  || (init->drvStr == opaDrvStrLowAccLowStr)
555  || (init->drvStr == opaDrvStrHighAccHighStr)
556  || (init->drvStr == opaDrvStrHigherAccHighStr));
557 
558  /* Disable OPAMP before writing to registers. */
559  OPAMP_Disable(dac, opa);
560 
561  /* Get the calibration value based on OPAMP, Drive Strength, and INCBW. */
562  switch (opa)
563  {
564  case OPA0:
565  switch (init->drvStr)
566  {
567  case opaDrvStrLowerAccLowStr:
568  calData = (init->ugBwScale ? DEVINFO->OPA0CAL0 : DEVINFO->OPA0CAL4);
569  break;
570  case opaDrvStrLowAccLowStr:
571  calData = (init->ugBwScale ? DEVINFO->OPA0CAL1 : DEVINFO->OPA0CAL5);
572  break;
573  case opaDrvStrHighAccHighStr:
574  calData = (init->ugBwScale ? DEVINFO->OPA0CAL2 : DEVINFO->OPA0CAL6);
575  break;
576  case opaDrvStrHigherAccHighStr:
577  calData = (init->ugBwScale ? DEVINFO->OPA0CAL3 : DEVINFO->OPA0CAL7);
578  break;
579  }
580  break;
581 
582  case OPA1:
583  switch (init->drvStr)
584  {
585  case opaDrvStrLowerAccLowStr:
586  calData = (init->ugBwScale ? DEVINFO->OPA1CAL0 : DEVINFO->OPA1CAL4);
587  break;
588  case opaDrvStrLowAccLowStr:
589  calData = (init->ugBwScale ? DEVINFO->OPA1CAL1 : DEVINFO->OPA1CAL5);
590  break;
591  case opaDrvStrHighAccHighStr:
592  calData = (init->ugBwScale ? DEVINFO->OPA1CAL2 : DEVINFO->OPA1CAL6);
593  break;
594  case opaDrvStrHigherAccHighStr:
595  calData = (init->ugBwScale ? DEVINFO->OPA1CAL3 : DEVINFO->OPA1CAL7);
596  break;
597  }
598  break;
599 
600  case OPA2:
601  switch (init->drvStr)
602  {
603  case opaDrvStrLowerAccLowStr:
604  calData = (init->ugBwScale ? DEVINFO->OPA2CAL0 : DEVINFO->OPA2CAL4);
605  break;
606  case opaDrvStrLowAccLowStr:
607  calData = (init->ugBwScale ? DEVINFO->OPA2CAL1 : DEVINFO->OPA2CAL5);
608  break;
609  case opaDrvStrHighAccHighStr:
610  calData = (init->ugBwScale ? DEVINFO->OPA2CAL2 : DEVINFO->OPA2CAL6);
611  break;
612  case opaDrvStrHigherAccHighStr:
613  calData = (init->ugBwScale ? DEVINFO->OPA2CAL3 : DEVINFO->OPA2CAL7);
614  break;
615  }
616  break;
617  }
618  if (!init->defaultOffsetN)
619  {
620  EFM_ASSERT(init->offsetN <= (_VDAC_OPA_CAL_OFFSETN_MASK
621  >> _VDAC_OPA_CAL_OFFSETN_SHIFT));
622  calData = (calData & ~_VDAC_OPA_CAL_OFFSETN_MASK)
623  | (init->offsetN << _VDAC_OPA_CAL_OFFSETN_SHIFT);
624  }
625  if (!init->defaultOffsetP)
626  {
627  EFM_ASSERT(init->offsetP <= (_VDAC_OPA_CAL_OFFSETP_MASK
628  >> _VDAC_OPA_CAL_OFFSETP_SHIFT));
629  calData = (calData & ~_VDAC_OPA_CAL_OFFSETP_MASK)
630  | (init->offsetP << _VDAC_OPA_CAL_OFFSETP_SHIFT);
631  }
632 
633  dac->OPA[opa].CAL = (calData & _VDAC_OPA_CAL_MASK);
634 
635  dac->OPA[opa].MUX = (uint32_t)init->resSel
636  | (init->gain3xEn ? VDAC_OPA_MUX_GAIN3X : 0)
637  | (uint32_t)init->resInMux
638  | (uint32_t)init->negSel
639  | (uint32_t)init->posSel;
640 
641  dac->OPA[opa].OUT = (uint32_t)init->outMode
642  | (uint32_t)init->outPen;
643 
644  switch (init->drvStr)
645  {
646  case opaDrvStrHigherAccHighStr:
647  warmupTime = 6;
648  break;
649 
650  case opaDrvStrHighAccHighStr:
651  warmupTime = 8;
652  break;
653 
654  case opaDrvStrLowAccLowStr:
655  warmupTime = 85;
656  break;
657 
658  case opaDrvStrLowerAccLowStr:
659  default:
660  warmupTime = 100;
661  break;
662  }
663 
664  dac->OPA[opa].TIMER = (uint32_t)(init->settleTime
665  << _VDAC_OPA_TIMER_SETTLETIME_SHIFT)
666  | (uint32_t)(warmupTime
667  << _VDAC_OPA_TIMER_WARMUPTIME_SHIFT)
668  | (uint32_t)(init->startupDly
669  << _VDAC_OPA_TIMER_STARTUPDLY_SHIFT);
670 
671  dac->OPA[opa].CTRL = (init->aportYMasterDisable
672  ? VDAC_OPA_CTRL_APORTYMASTERDIS : 0)
673  | (init->aportXMasterDisable
674  ? VDAC_OPA_CTRL_APORTXMASTERDIS : 0)
675  | (uint32_t)init->prsOutSel
676  | (uint32_t)init->prsSel
677  | (uint32_t)init->prsMode
678  | (init->prsEn ? VDAC_OPA_CTRL_PRSEN : 0)
679  | (init->halfDrvStr
680  ? VDAC_OPA_CTRL_OUTSCALE_HALF
681  : VDAC_OPA_CTRL_OUTSCALE_FULL)
682  | (init->hcmDisable ? VDAC_OPA_CTRL_HCMDIS : 0)
683  | (init->ugBwScale ? VDAC_OPA_CTRL_INCBW : 0)
684  | (uint32_t)init->drvStr;
685 
686  if (opa == OPA0)
687  {
688  dac->CMD |= VDAC_CMD_OPA0EN;
689  }
690  else if (opa == OPA1)
691  {
692  dac->CMD |= VDAC_CMD_OPA1EN;
693  }
694  else /* OPA2 */
695  {
696  dac->CMD |= VDAC_CMD_OPA2EN;
697  }
698 
699 #endif
700 }
701 
705 #endif /* (defined(OPAMP_PRESENT) && (OPAMP_COUNT == 1)
706  || defined(VDAC_PRESENT) && (VDAC_COUNT > 0) */
Emlib peripheral API "assert" implementation.
bool SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)
Get factory calibration value for a given peripheral register.
Definition: em_system.c:93
#define DEVINFO
#define _SILICON_LABS_32B_SERIES_1
System API.
Operational Amplifier (OPAMP) peripheral API.