1 /**************************************************************************//**
2  * @file     acmp.c
3  * @version  V1.0
4  * @brief    M2L31 series Analog Comparator (ACMP) driver source file
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10 
11 /** @addtogroup Standard_Driver Standard Driver
12   @{
13 */
14 
15 /** @addtogroup ACMP_Driver ACMP Driver
16   @{
17 */
18 
19 int32_t g_ACMP_i32ErrCode = 0;  /*!< ACMP global error code */
20 
21 /** @addtogroup ACMP_EXPORTED_FUNCTIONS ACMP Exported Functions
22   @{
23 */
24 
25 
26 /**
27   * @brief  Configure the specified ACMP module
28   *
29   * @param[in]  acmp The pointer of the specified ACMP module
30   * @param[in]  u32ChNum Comparator number.
31   * @param[in]  u32NegSrc Comparator negative input selection.  Including:
32   *                  - \ref ACMP_CTL_NEGSEL_PIN
33   *                  - \ref ACMP_CTL_NEGSEL_CRV
34   *                  - \ref ACMP_CTL_NEGSEL_VBG
35   *                  - \ref ACMP_CTL_NEGSEL_DAC0
36   *                  - \ref ACMP_CTL_NEGSEL_DAC1
37   * @param[in]  u32HysSel The hysteresis function option. Including:
38   *                  - \ref ACMP_CTL_HYSTERESIS_40MV
39   *                  - \ref ACMP_CTL_HYSTERESIS_20MV
40   *                  - \ref ACMP_CTL_HYSTERESIS_DISABLE
41   *
42   * @return     None
43   *
44   * @details    Configure hysteresis function, select the source of negative input and enable analog comparator.
45   * @note       This API will reset and calibrate ACMP if ACMP never be calibrated after chip power on.
46   */
ACMP_Open(ACMP_T * acmp,uint32_t u32ChNum,uint32_t u32NegSrc,uint32_t u32HysSel)47 void ACMP_Open(ACMP_T *acmp, uint32_t u32ChNum, uint32_t u32NegSrc, uint32_t u32HysSel)
48 {
49     uint32_t u32Delay = SystemCoreClock;    /* 1 second */
50 
51     g_ACMP_i32ErrCode = 0;
52 
53     /* Do calibration for ACMP to decrease the effect of electrical random noise. */
54     if (acmp == ACMP01)
55     {
56         if (((acmp->CALSR & ACMP_CALSR_DONE0_Msk) == 0) || ((acmp->CALSR & ACMP_CALSR_DONE1_Msk) == 0))
57         {
58             /* Must reset ACMP before ACMP calibration */
59             SYS->IPRST1 |= (SYS_IPRST1_ACMP01RST_Msk);
60             SYS->IPRST1 &= ~(SYS_IPRST1_ACMP01RST_Msk);
61 
62             /* Calibration ACMP0 */
63             acmp->CTL[0] |= ACMP_CTL_ACMPEN_Msk;
64 
65             /* MUST enable CRV and set NEGSEL to CRV for ACMP calibration. */
66             acmp->VREF = (ACMP_VREF_CRV0EN_Msk | ACMP_VREF_CRV0SSEL_Msk);
67             acmp->CTL[0] = (acmp->CTL[0] & ~(ACMP_CTL_NEGSEL_Msk)) |
68                            (ACMP_CTL_NEGSEL_CRV);
69 
70             acmp->CALCTL |= ACMP_CALCTL_CALTRG0_Msk;            /* Start to calibration */
71             u32Delay = SystemCoreClock;
72             while ((acmp->CALSR & ACMP_CALSR_DONE0_Msk) == 0)   /* Wait calibration finish */
73             {
74                 if (--u32Delay == 0)
75                 {
76                     g_ACMP_i32ErrCode = ACMP_TIMEOUT_ERR;
77                     break;
78                 }
79             }
80 
81             /* Calibration ACMP1 */
82             acmp->CTL[1] |= ACMP_CTL_ACMPEN_Msk;
83 
84             /* MUST enable CRV and set NEGSEL to CRV for ACMP calibration. */
85             acmp->VREF = (ACMP_VREF_CRV1EN_Msk | ACMP_VREF_CRV1SSEL_Msk);
86             acmp->CTL[1] = (acmp->CTL[1] & ~(ACMP_CTL_NEGSEL_Msk)) |
87                            (ACMP_CTL_NEGSEL_CRV);
88 
89             acmp->CALCTL |= ACMP_CALCTL_CALTRG1_Msk;            /* Start to calibration */
90             u32Delay = SystemCoreClock;
91             while ((acmp->CALSR & ACMP_CALSR_DONE1_Msk) == 0)   /* Wait calibration finish */
92             {
93                 if (--u32Delay == 0)
94                 {
95                     g_ACMP_i32ErrCode = ACMP_TIMEOUT_ERR;
96                     break;
97                 }
98             }
99         }
100         acmp->CTL[u32ChNum] = (acmp->CTL[u32ChNum] & (~(ACMP_CTL_NEGSEL_Msk | ACMP_CTL_HYSSEL_Msk))) | (u32NegSrc | u32HysSel | ACMP_CTL_ACMPEN_Msk);
101     }
102 
103     if (acmp == ACMP2)
104     {
105         /* Do calibration for ACMP to decrease the effect of electrical random noise. */
106         if ((acmp->CALSR & ACMP_CALSR_DONE2_Msk) == 0)
107         {
108             /* Must reset ACMP before ACMP calibration */
109             SYS->IPRST3 |= (SYS_IPRST3_ACMP2RST_Msk);
110             SYS->IPRST3 &= ~(SYS_IPRST3_ACMP2RST_Msk);
111 
112             /* Calibration ACMP0 */
113             acmp->CTL[0] |= ACMP_CTL_ACMPEN_Msk;
114 
115             /* MUST enable CRV and set NEGSEL to CRV for ACMP calibration. */
116             acmp->VREF = (ACMP_VREF_CRV2EN_Msk | ACMP_VREF_CRV2SSEL_Msk);
117             acmp->CTL[0] = (acmp->CTL[0] & ~(ACMP_CTL_NEGSEL_Msk)) |
118                            (ACMP_CTL_NEGSEL_CRV);
119 
120             acmp->CALCTL |= ACMP_CALCTL_CALTRG2_Msk;            /* Start to calibration */
121             u32Delay = SystemCoreClock;
122             while ((acmp->CALSR & ACMP_CALSR_DONE2_Msk) == 0)   /* Wait calibration finish */
123             {
124                 if (--u32Delay == 0)
125                 {
126                     g_ACMP_i32ErrCode = ACMP_TIMEOUT_ERR;
127                     break;
128                 }
129             }
130         }
131         acmp->CTL[0] = (acmp->CTL[u32ChNum] & (~(ACMP_CTL_NEGSEL_Msk | ACMP_CTL_HYSSEL_Msk))) | (u32NegSrc | u32HysSel | ACMP_CTL_ACMPEN_Msk);
132     }
133 }
134 
135 /**
136   * @brief  Close analog comparator
137   *
138   * @param[in]  acmp The pointer of the specified ACMP module
139   * @param[in]  u32ChNum Comparator number.
140   *
141   * @return     None
142   *
143   * @details  This function will clear ACMPEN bit of ACMP_CTL register to disable analog comparator.
144   */
ACMP_Close(ACMP_T * acmp,uint32_t u32ChNum)145 void ACMP_Close(ACMP_T *acmp, uint32_t u32ChNum)
146 {
147     if (acmp == ACMP01)
148     {
149         acmp->CTL[u32ChNum] &= (~ACMP_CTL_ACMPEN_Msk);
150     }
151 
152     if (acmp == ACMP2)
153     {
154         acmp->CTL[0] &= (~ACMP_CTL_ACMPEN_Msk);
155     }
156 }
157 
158 /*@}*/ /* end of group ACMP_EXPORTED_FUNCTIONS */
159 
160 /*@}*/ /* end of group ACMP_Driver */
161 
162 /*@}*/ /* end of group Standard_Driver */
163 
164 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
165