1 /**************************************************************************//**
2  * @file     eadc.c
3  * @version  V2.00
4  * @brief    EADC driver source file
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2021 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10 
11 /** @addtogroup Standard_Driver Standard Driver
12   @{
13 */
14 
15 /** @addtogroup EADC_Driver EADC Driver
16   @{
17 */
18 
19 /** @addtogroup EADC_EXPORTED_FUNCTIONS EADC Exported Functions
20   @{
21 */
22 
23 /**
24   * @brief This function make EADC_module be ready to convert.
25   * @param[in] eadc The pointer of the specified EADC module.
26   * @param[in] u32InputMode Decides the input mode.
27   *                       - \ref EADC_CTL_DIFFEN_SINGLE_END      :Single end input mode.
28   *                       - \ref EADC_CTL_DIFFEN_DIFFERENTIAL    :Differential input type.
29   * @retval 0                EADC operation OK.
30   * @retval EADC_TIMEOUT_ERR EADC operation abort due to timeout error.
31   * @retval EADC_CAL_ERR     EADC has calibration error.
32   * @retval EADC_CLKDIV_ERR  EADC clock frequency is configured error.
33   * @details This function is used to set analog input mode and enable A/D Converter.
34   *         Before starting A/D conversion function, ADCEN bit (EADC_CTL[0]) should be set to 1.
35   * @note This API will reset and calibrate EADC if EADC never be calibrated after chip power on.
36   * @note This function retrun EADC_TIMEOUT_ERR if CALIF(CALSR[16]) is not set to 1.
37   */
EADC_Open(EADC_T * eadc,uint32_t u32InputMode)38 int32_t EADC_Open(EADC_T *eadc, uint32_t u32InputMode)
39 {
40     uint32_t u32Delay = SystemCoreClock >> 4;
41     uint32_t u32ClkSel0Backup, u32ClkDivBackup, u32PclkDivBackup, u32RegLockBackup = 0, u32Apb1Div;
42 
43     eadc->CTL &= (~EADC_CTL_DIFFEN_Msk);
44 
45     eadc->CTL |= (u32InputMode | EADC_CTL_ADCEN_Msk);
46 
47     /* Do calibration for EADC to decrease the effect of electrical random noise. */
48     if ((eadc->CALSR & EADC_CALSR_CALIF_Msk) == 0)
49     {
50         /* Must reset ADC before ADC calibration */
51         eadc->CTL |= EADC_CTL_ADCRST_Msk;
52         while((eadc->CTL & EADC_CTL_ADCRST_Msk) == EADC_CTL_ADCRST_Msk)
53         {
54             if (--u32Delay == 0)
55             {
56                 return EADC_TIMEOUT_ERR;
57             }
58         }
59 
60         /* Registers backup */
61         u32ClkSel0Backup = CLK->CLKSEL0;
62         u32PclkDivBackup = CLK->PCLKDIV;
63 
64         u32RegLockBackup = SYS_IsRegLocked();
65 
66         /* Unlock protected registers */
67         SYS_UnlockReg();
68 
69         /* Set EADC clock is less than 2*PCLK to do calibration correctly. */
70         if (eadc == EADC0)
71         {
72             u32ClkDivBackup = CLK->CLKDIV0;
73             CLK->CLKDIV0 = (CLK->CLKDIV0 & ~CLK_CLKDIV0_EADC0DIV_Msk) | (2 << CLK_CLKDIV0_EADC0DIV_Pos);
74             CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_EADC0SEL_Msk) | CLK_CLKSEL0_EADC0SEL_HCLK;
75         }
76         else if (eadc == EADC1)
77         {
78             u32ClkDivBackup = CLK->CLKDIV2;
79             CLK->CLKDIV2 = (CLK->CLKDIV2 & ~CLK_CLKDIV2_EADC1DIV_Msk) | (2 << CLK_CLKDIV2_EADC1DIV_Pos);
80             CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_EADC1SEL_Msk) | CLK_CLKSEL0_EADC1SEL_HCLK;
81         }
82         else if (eadc == EADC2)
83         {
84             u32ClkDivBackup = CLK->CLKDIV5;
85             CLK->CLKDIV5 = (CLK->CLKDIV5 & ~CLK_CLKDIV5_EADC2DIV_Msk) | (2 << CLK_CLKDIV5_EADC2DIV_Pos);
86             CLK->CLKSEL0 = (CLK->CLKSEL0 & ~CLK_CLKSEL0_EADC2SEL_Msk) | CLK_CLKSEL0_EADC2SEL_HCLK;
87         }
88         CLK->PCLKDIV = (CLK->PCLKDIV & ~CLK_PCLKDIV_APB1DIV_Msk);
89 
90         eadc->CALSR |= EADC_CALSR_CALIF_Msk;  /* Clear Calibration Finish Interrupt Flag */
91         eadc->CALCTL = (eadc->CALCTL & ~(0x000F0000))|0x00020000;
92         eadc->CALCTL |= EADC_CALCTL_CAL_Msk;  /* Enable Calibration function */
93 
94         u32Delay = SystemCoreClock >> 4;
95         while((eadc->CALSR & EADC_CALSR_CALIF_Msk) != EADC_CALSR_CALIF_Msk)
96         {
97             if (--u32Delay == 0)
98             {
99                 return EADC_CAL_ERR;
100             }
101         }
102 
103         /* Restore registers */
104         CLK->PCLKDIV = u32PclkDivBackup;
105         CLK->CLKSEL0 = u32ClkSel0Backup;
106         if (eadc == EADC0)
107         {
108             CLK->CLKDIV0 = u32ClkDivBackup;
109         }
110         else if (eadc == EADC1)
111         {
112             CLK->CLKDIV2 = u32ClkDivBackup;
113         }
114         else if (eadc == EADC2)
115         {
116             CLK->CLKDIV5 = u32ClkDivBackup;
117         }
118         if (u32RegLockBackup)
119         {
120             /* Lock protected registers */
121             SYS_LockReg();
122         }
123     }
124 
125     /* Check EADC clock frequency must not faster than PCLK */
126     u32Apb1Div = (CLK->PCLKDIV & CLK_PCLKDIV_APB1DIV_Msk) >> CLK_PCLKDIV_APB1DIV_Pos;
127     if (eadc == EADC0)
128     {
129         if (u32Apb1Div > ((CLK->CLKDIV0 & CLK_CLKDIV0_EADC0DIV_Msk) >> CLK_CLKDIV0_EADC0DIV_Pos))
130         {
131             return EADC_CLKDIV_ERR;
132         }
133     }
134     else if (eadc == EADC1)
135     {
136         if (u32Apb1Div > ((CLK->CLKDIV2 & CLK_CLKDIV2_EADC1DIV_Msk) >> CLK_CLKDIV2_EADC1DIV_Pos))
137         {
138             return EADC_CLKDIV_ERR;
139         }
140     }
141     else if (eadc == EADC2)
142     {
143         if (u32Apb1Div > ((CLK->CLKDIV5 & CLK_CLKDIV5_EADC2DIV_Msk) >> CLK_CLKDIV5_EADC2DIV_Pos))
144         {
145             return EADC_CLKDIV_ERR;
146         }
147     }
148 
149     return 0;
150 }
151 
152 /**
153   * @brief Disable EADC_module.
154   * @param[in] eadc The pointer of the specified EADC module.
155   * @return None
156   * @details Clear ADCEN bit (EADC_CTL[0]) to disable A/D converter analog circuit power consumption.
157   */
EADC_Close(EADC_T * eadc)158 void EADC_Close(EADC_T *eadc)
159 {
160     eadc->CTL &= ~EADC_CTL_ADCEN_Msk;
161 }
162 
163 /**
164   * @brief Configure the sample control logic module.
165   * @param[in] eadc The pointer of the specified EADC module.
166   * @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 15.
167   * @param[in] u32TriggerSrc Decides the trigger source. Valid values are:
168   *                            - \ref EADC_SOFTWARE_TRIGGER              : Disable trigger
169   *                            - \ref EADC_FALLING_EDGE_TRIGGER          : STADC pin falling edge trigger
170   *                            - \ref EADC_RISING_EDGE_TRIGGER           : STADC pin rising edge trigger
171   *                            - \ref EADC_FALLING_RISING_EDGE_TRIGGER   : STADC pin both falling and rising edge trigger
172   *                            - \ref EADC_ADINT0_TRIGGER                : EADC ADINT0 interrupt EOC pulse trigger
173   *                            - \ref EADC_ADINT1_TRIGGER                : EADC ADINT1 interrupt EOC pulse trigger
174   *                            - \ref EADC_TIMER0_TRIGGER                : Timer0 overflow pulse trigger
175   *                            - \ref EADC_TIMER1_TRIGGER                : Timer1 overflow pulse trigger
176   *                            - \ref EADC_TIMER2_TRIGGER                : Timer2 overflow pulse trigger
177   *                            - \ref EADC_TIMER3_TRIGGER                : Timer3 overflow pulse trigger
178   *                            - \ref EADC_EPWM0TG0_TRIGGER              : EPWM0TG0 trigger
179   *                            - \ref EADC_EPWM0TG1_TRIGGER              : EPWM0TG1 trigger
180   *                            - \ref EADC_EPWM0TG2_TRIGGER              : EPWM0TG2 trigger
181   *                            - \ref EADC_EPWM0TG3_TRIGGER              : EPWM0TG3 trigger
182   *                            - \ref EADC_EPWM0TG4_TRIGGER              : EPWM0TG4 trigger
183   *                            - \ref EADC_EPWM0TG5_TRIGGER              : EPWM0TG5 trigger
184   *                            - \ref EADC_EPWM1TG0_TRIGGER              : EPWM1TG0 trigger
185   *                            - \ref EADC_EPWM1TG1_TRIGGER              : EPWM1TG1 trigger
186   *                            - \ref EADC_EPWM1TG2_TRIGGER              : EPWM1TG2 trigger
187   *                            - \ref EADC_EPWM1TG3_TRIGGER              : EPWM1TG3 trigger
188   *                            - \ref EADC_EPWM1TG4_TRIGGER              : EPWM1TG4 trigger
189   *                            - \ref EADC_EPWM1TG5_TRIGGER              : EPWM1TG5 trigger
190   *                            - \ref EADC_BPWM0TG_TRIGGER               : BPWM0TG trigger
191   *                            - \ref EADC_BPWM1TG_TRIGGER               : BPWM1TG trigger
192   * @param[in] u32Channel Specifies the sample module channel, valid value are from 0 to 15.
193   * @return None
194   * @details Each of ADC control logic modules 0~15 which is configurable for ADC converter channel EADC_CH0~15 and trigger source.
195   *         sample module 16~18 is fixed for ADC channel 16, 17, 18 input sources as band-gap voltage, temperature sensor, and battery power (VBAT).
196   */
EADC_ConfigSampleModule(EADC_T * eadc,uint32_t u32ModuleNum,uint32_t u32TriggerSrc,uint32_t u32Channel)197 void EADC_ConfigSampleModule(EADC_T *eadc, \
198                              uint32_t u32ModuleNum, \
199                              uint32_t u32TriggerSrc, \
200                              uint32_t u32Channel)
201 {
202     eadc->SCTL[u32ModuleNum] &= ~(EADC_SCTL_EXTFEN_Msk | EADC_SCTL_EXTREN_Msk | EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk);
203     eadc->SCTL[u32ModuleNum] |= (u32TriggerSrc | u32Channel);
204 }
205 
206 
207 /**
208   * @brief Set trigger delay time.
209   * @param[in] eadc The pointer of the specified EADC module.
210   * @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 15.
211   * @param[in] u32TriggerDelayTime Decides the trigger delay time, valid range are between 0~0xFF.
212   * @param[in] u32DelayClockDivider Decides the trigger delay clock divider. Valid values are:
213     *                                - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_1    : Trigger delay clock frequency is ADC_CLK/1
214     *                                - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_2    : Trigger delay clock frequency is ADC_CLK/2
215     *                                - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_4    : Trigger delay clock frequency is ADC_CLK/4
216     *                                - \ref EADC_SCTL_TRGDLYDIV_DIVIDER_16   : Trigger delay clock frequency is ADC_CLK/16
217   * @return None
218   * @details User can configure the trigger delay time by setting TRGDLYCNT (EADC_SCTLn[15:8], n=0~15) and TRGDLYDIV (EADC_SCTLn[7:6], n=0~15).
219   *         Trigger delay time = (u32TriggerDelayTime) x Trigger delay clock period.
220   */
EADC_SetTriggerDelayTime(EADC_T * eadc,uint32_t u32ModuleNum,uint32_t u32TriggerDelayTime,uint32_t u32DelayClockDivider)221 void EADC_SetTriggerDelayTime(EADC_T *eadc, \
222                               uint32_t u32ModuleNum, \
223                               uint32_t u32TriggerDelayTime, \
224                               uint32_t u32DelayClockDivider)
225 {
226     eadc->SCTL[u32ModuleNum] &= ~(EADC_SCTL_TRGDLYDIV_Msk | EADC_SCTL_TRGDLYCNT_Msk);
227     eadc->SCTL[u32ModuleNum] |= ((u32TriggerDelayTime << EADC_SCTL_TRGDLYCNT_Pos) | u32DelayClockDivider);
228 }
229 
230 /**
231   * @brief Set ADC extend sample time.
232   * @param[in] eadc The pointer of the specified EADC module.
233   * @param[in] u32ModuleNum Decides the sample module number, valid value are from 0 to 18.
234   * @param[in] u32ExtendSampleTime Decides the extend sampling time, the range is from 0~255 ADC clock. Valid value are from 0 to 0xFF.
235   * @return None
236   * @details When A/D converting at high conversion rate, the sampling time of analog input voltage may not enough if input channel loading is heavy,
237   *         user can extend A/D sampling time after trigger source is coming to get enough sampling time.
238   */
EADC_SetExtendSampleTime(EADC_T * eadc,uint32_t u32ModuleNum,uint32_t u32ExtendSampleTime)239 void EADC_SetExtendSampleTime(EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime)
240 {
241     eadc->SCTL[u32ModuleNum] &= ~EADC_SCTL_EXTSMPT_Msk;
242 
243     eadc->SCTL[u32ModuleNum] |= (u32ExtendSampleTime << EADC_SCTL_EXTSMPT_Pos);
244 
245 }
246 
247 /*@}*/ /* end of group EADC_EXPORTED_FUNCTIONS */
248 
249 /*@}*/ /* end of group EADC_Driver */
250 
251 /*@}*/ /* end of group Standard_Driver */
252