em_acmp.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_acmp.h"
00035 #if defined(ACMP_COUNT) && (ACMP_COUNT > 0)
00036 
00037 #include <stdbool.h>
00038 #include "em_bitband.h"
00039 #include "em_assert.h"
00040 
00041 /***************************************************************************/
00046 /***************************************************************************/
00052 /*******************************************************************************
00053  *******************************   DEFINES   ***********************************
00054  ******************************************************************************/
00055 
00061 #if (ACMP_COUNT == 1)
00062 #define ACMP_REF_VALID(ref)    ((ref) == ACMP0)
00063 #elif (ACMP_COUNT == 2)
00064 #define ACMP_REF_VALID(ref)    (((ref) == ACMP0) || ((ref) == ACMP1))
00065 #else
00066 #error Undefined number of analog comparators (ACMP).
00067 #endif
00068 
00071 /*******************************************************************************
00072  **************************   GLOBAL FUNCTIONS   *******************************
00073  ******************************************************************************/
00074 
00075 /***************************************************************************/
00096 void ACMP_CapsenseInit(ACMP_TypeDef *acmp, const ACMP_CapsenseInit_TypeDef *init)
00097 {
00098   /* Make sure the module exists on the selected chip */
00099   EFM_ASSERT(ACMP_REF_VALID(acmp));
00100 
00101   /* Make sure that vddLevel is within bounds */
00102   EFM_ASSERT(init->vddLevel < 64);
00103 
00104   /* Make sure biasprog is within bounds */
00105   EFM_ASSERT(init->biasProg < 16);
00106 
00107   /* Set control register. No need to set interrupt modes */
00108   acmp->CTRL = (init->fullBias << _ACMP_CTRL_FULLBIAS_SHIFT)
00109                | (init->halfBias << _ACMP_CTRL_HALFBIAS_SHIFT)
00110                | (init->biasProg << _ACMP_CTRL_BIASPROG_SHIFT)
00111                | (init->warmTime << _ACMP_CTRL_WARMTIME_SHIFT)
00112                | (init->hysteresisLevel << _ACMP_CTRL_HYSTSEL_SHIFT);
00113 
00114   /* Select capacative sensing mode by selecting a resistor and enabling it */
00115   acmp->INPUTSEL = (init->resistor << _ACMP_INPUTSEL_CSRESSEL_SHIFT)
00116                    | ACMP_INPUTSEL_CSRESEN
00117                    | (init->lowPowerReferenceEnabled << _ACMP_INPUTSEL_LPREF_SHIFT)
00118                    | (init->vddLevel << _ACMP_INPUTSEL_VDDLEVEL_SHIFT)
00119                    | ACMP_INPUTSEL_NEGSEL_CAPSENSE;
00120 
00121   /* Enable ACMP if requested.
00122    * Note: BITBAND_Peripheral() function is used for setting/clearing single
00123    * bit peripheral register bitfields. */
00124   BITBAND_Peripheral(&(acmp->CTRL),
00125                      (uint32_t)_ACMP_CTRL_EN_SHIFT,
00126                      (uint32_t)init->enable);
00127 }
00128 
00129 /***************************************************************************/
00143 void ACMP_CapsenseChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef channel)
00144 {
00145   /* Make sure that only external channels are used */
00146   EFM_ASSERT(channel <= _ACMP_INPUTSEL_POSSEL_CH7);
00147 
00148   /* Set channel as positive channel in ACMP */
00149   SET_BIT_FIELD(acmp->INPUTSEL, _ACMP_INPUTSEL_POSSEL_MASK, channel,
00150                 _ACMP_INPUTSEL_POSSEL_SHIFT);
00151 }
00152 
00153 /***************************************************************************/
00160 void ACMP_Disable(ACMP_TypeDef *acmp)
00161 {
00162   acmp->CTRL &= ~ACMP_CTRL_EN;
00163 }
00164 
00165 /***************************************************************************/
00172 void ACMP_Enable(ACMP_TypeDef *acmp)
00173 {
00174   acmp->CTRL |= ACMP_CTRL_EN;
00175 }
00176 
00177 /***************************************************************************/
00188 void ACMP_Reset(ACMP_TypeDef *acmp)
00189 {
00190   /* Make sure the module exists on the selected chip */
00191   EFM_ASSERT(ACMP_REF_VALID(acmp));
00192 
00193   acmp->CTRL     = _ACMP_CTRL_RESETVALUE;
00194   acmp->INPUTSEL = _ACMP_INPUTSEL_RESETVALUE;
00195   acmp->IEN      = _ACMP_IEN_RESETVALUE;
00196   acmp->IFC      = _ACMP_IF_MASK;
00197 }
00198 
00199 /***************************************************************************/
00219 void ACMP_GPIOSetup(ACMP_TypeDef *acmp, uint32_t location, bool enable, bool invert)
00220 {
00221   /* Sanity checking of location */
00222 #if defined( _ACMP_ROUTE_LOCATION_LOC3 )
00223   EFM_ASSERT(location <= _ACMP_ROUTE_LOCATION_LOC3);
00224 
00225 #elif defined( _ACMP_ROUTE_LOCATION_LOC2 )
00226   EFM_ASSERT(location <= _ACMP_ROUTE_LOCATION_LOC2);
00227 
00228 #elif defined( _ACMP_ROUTE_LOCATION_LOC1 )
00229   EFM_ASSERT(location <= _ACMP_ROUTE_LOCATION_LOC1);
00230 
00231 #else
00232 #error Illegal pin location (ACMP).
00233 #endif
00234 
00235 
00236   /* Set GPIO inversion */
00237   SET_BIT_FIELD(acmp->CTRL, _ACMP_CTRL_GPIOINV_MASK, invert,
00238                 _ACMP_CTRL_GPIOINV_SHIFT);
00239 
00240   acmp->ROUTE = (location << _ACMP_ROUTE_LOCATION_SHIFT)
00241                 | (enable << _ACMP_ROUTE_ACMPPEN_SHIFT);
00242 }
00243 
00244 /***************************************************************************/
00257 void ACMP_ChannelSet(ACMP_TypeDef *acmp, ACMP_Channel_TypeDef negSel,
00258                      ACMP_Channel_TypeDef posSel)
00259 {
00260   /* Sanity checking of ACMP inputs */
00261   EFM_ASSERT(posSel <= _ACMP_INPUTSEL_POSSEL_CH7);
00262 
00263 #if defined(_ACMP_INPUTSEL_NEGSEL_DAC0CH1)
00264   EFM_ASSERT(negSel <= _ACMP_INPUTSEL_NEGSEL_DAC0CH1);
00265 #elif defined(_ACMP_INPUTSEL_NEGSEL_CAPSENSE)
00266   EFM_ASSERT(negSel <= _ACMP_INPUTSEL_NEGSEL_CAPSENSE);
00267 #else
00268 #error Illegal negative input selection (ACMP).
00269 #endif
00270 
00271   acmp->INPUTSEL = (acmp->INPUTSEL & ~(_ACMP_INPUTSEL_POSSEL_MASK |
00272                                        _ACMP_INPUTSEL_NEGSEL_MASK))
00273                    | (negSel << _ACMP_INPUTSEL_NEGSEL_SHIFT)
00274                    | (posSel << _ACMP_INPUTSEL_POSSEL_SHIFT);
00275 }
00276 
00277 /***************************************************************************/
00288 void ACMP_Init(ACMP_TypeDef *acmp, const ACMP_Init_TypeDef *init)
00289 {
00290   /* Make sure the module exists on the selected chip */
00291   EFM_ASSERT(ACMP_REF_VALID(acmp));
00292 
00293   /* Make sure biasprog is within bounds */
00294   EFM_ASSERT(init->biasProg < 16);
00295 
00296   /* Set control register. No need to set interrupt modes */
00297   acmp->CTRL = (init->fullBias << _ACMP_CTRL_FULLBIAS_SHIFT)
00298                | (init->halfBias << _ACMP_CTRL_HALFBIAS_SHIFT)
00299                | (init->biasProg << _ACMP_CTRL_BIASPROG_SHIFT)
00300                | (init->interruptOnFallingEdge << _ACMP_CTRL_IFALL_SHIFT)
00301                | (init->interruptOnRisingEdge << _ACMP_CTRL_IRISE_SHIFT)
00302                | (init->warmTime << _ACMP_CTRL_WARMTIME_SHIFT)
00303                | (init->hysteresisLevel << _ACMP_CTRL_HYSTSEL_SHIFT)
00304                | (init->inactiveValue << _ACMP_CTRL_INACTVAL_SHIFT);
00305 
00306   acmp->INPUTSEL = (init->lowPowerReferenceEnabled << _ACMP_INPUTSEL_LPREF_SHIFT)
00307                    | (init->vddLevel << _ACMP_INPUTSEL_VDDLEVEL_SHIFT);
00308 
00309   /* Enable ACMP if requested.
00310    * Note: BITBAND_Peripheral() function is used for setting/clearing single
00311    * bit peripheral register bitfields. */
00312   BITBAND_Peripheral(&(acmp->CTRL),
00313                      (uint32_t)_ACMP_CTRL_EN_SHIFT,
00314                      (uint32_t)init->enable);
00315 }
00316 
00317 
00320 #endif /* defined(ACMP_COUNT) && (ACMP_COUNT > 0) */