1 /*
2  * Copyright 2022, 2023 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "fsl_eqdc.h"
8 
9 /*******************************************************************************
10  * Definitions
11  ******************************************************************************/
12 
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.eqdc"
16 #endif
17 
18 #if defined(EQDC_RSTS)
19 #define EQDC_RESETS_ARRAY EQDC_RSTS
20 #endif
21 /*******************************************************************************
22  * Prototypes
23  ******************************************************************************/
24 /*!
25  * @brief Get instance number for EQDC module.
26  *
27  * @param base EQDC peripheral base address
28  */
29 static uint32_t EQDC_GetInstance(EQDC_Type *base);
30 
31 /*******************************************************************************
32  * Variables
33  ******************************************************************************/
34 /*! @brief Pointers to EQDC bases for each instance. */
35 static EQDC_Type *const s_eqdcBases[] = EQDC_BASE_PTRS;
36 
37 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
38 /*! @brief Pointers to EQDC clocks for each instance. */
39 #if defined(QDC_CLOCKS)
40 static const clock_ip_name_t s_eqdcClocks[] = QDC_CLOCKS;
41 #elif defined(ENC_CLOCKS)
42 static const clock_ip_name_t s_eqdcClocks[] = ENC_CLOCKS;
43 #endif
44 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
45 
46 #if defined(EQDC_RESETS_ARRAY)
47 /* Reset array */
48 static const reset_ip_name_t s_eqdcResets[] = EQDC_RESETS_ARRAY;
49 #endif
50 
51 /*******************************************************************************
52  * Code
53  ******************************************************************************/
EQDC_GetInstance(EQDC_Type * base)54 static uint32_t EQDC_GetInstance(EQDC_Type *base)
55 {
56     uint32_t instance;
57 
58     /* Find the instance index from base address mappings. */
59     for (instance = 0; instance < ARRAY_SIZE(s_eqdcBases); instance++)
60     {
61         if (s_eqdcBases[instance] == base)
62         {
63             break;
64         }
65     }
66 
67     assert(instance < ARRAY_SIZE(s_eqdcBases));
68 
69     return instance;
70 }
71 
72 /*
73  * Initializes the EQDC module.
74  *
75  * This function initializes the EQDC by enabling the IP bus clock (optional).
76  *
77  * param base   EQDC peripheral base address.
78  * param psConfig Pointer to configuration structure.
79  */
EQDC_Init(EQDC_Type * base,const eqdc_config_t * psConfig)80 void EQDC_Init(EQDC_Type *base, const eqdc_config_t *psConfig)
81 {
82     assert(NULL != psConfig);
83 
84 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
85     /* Enable the clock. */
86     CLOCK_EnableClock(s_eqdcClocks[EQDC_GetInstance(base)]);
87 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
88 
89 #if defined(EQDC_RESETS_ARRAY)
90     RESET_ReleasePeripheralReset(s_eqdcResets[EQDC_GetInstance(base)]);
91 #endif
92 
93     /* Initialize Double-set registers */
94     EQDC_ClearBufferedRegisterLoadUpdateMode(base);
95     EQDC_ClearEqdcLdok(base);
96 
97     /* Counter value. */
98     EQDC_SetPositionCounterValue(base, psConfig->positionCounterValue);
99 
100     /* Initial value. */
101     EQDC_SetInitialPositionValue(base, psConfig->positionInitialValue);
102 
103     /* Modulus value. */
104     EQDC_SetPositionModulusValue(base, psConfig->positionModulusValue);
105 
106     /* Compare value. */
107     EQDC_SetPositionCompare0Value(base, psConfig->positionCompareValue[0]);
108     EQDC_SetPositionCompare1Value(base, psConfig->positionCompareValue[1]);
109     EQDC_SetPositionCompare2Value(base, psConfig->positionCompareValue[2]);
110     EQDC_SetPositionCompare3Value(base, psConfig->positionCompareValue[3]);
111 
112     EQDC_SetEqdcLdok(base);
113     while (EQDC_GetEqdcLdok(base) != 0U)
114     {
115     }
116 
117     /* Watchdog. */
118     EQDC_SetWatchdogTimeout(base, psConfig->watchdogTimeoutValue);
119 
120     /* Clear EQDC_REV */
121     base->REV = 0U;
122 
123     /* EQDC_IMR. */
124     base->IMR = EQDC_IMR_FPHA(psConfig->filterPhaseA) | EQDC_IMR_FPHB(psConfig->filterPhaseB) |
125                 EQDC_IMR_FIND_PRE(psConfig->filterIndPre) | EQDC_IMR_FHOM_ENA(psConfig->filterHomEna);
126 
127     /* EQDC_FILT. */
128     base->FILT = EQDC_FILT_PRSC(psConfig->prescaler) | /* Prescaler used by LASTEDGE and POSDPER. */
129                  EQDC_FILT_FILT_CS(psConfig->filterClockSourceselection) |
130                  EQDC_FILT_FILT_CNT(psConfig->filterSampleCount) | EQDC_FILT_FILT_PER(psConfig->filterSamplePeriod);
131 
132     /* EQDC_CTRL. */
133     base->CTRL = EQDC_CTRL_W1C_FLAGS |                                /* W1C flags. */
134                  (uint16_t)psConfig->homeEnableInitPosCounterMode |  /* HOME Enable trigger. */
135                  (uint16_t)psConfig->indexPresetInitPosCounterMode | /* INDEX Preset trigger. */
136                  EQDC_CTRL_REV(psConfig->enableReverseDirection) |   /* Reverse direction. */
137                  EQDC_CTRL_WDE(psConfig->enableWatchdog) |           /* Enable watchdog. */
138                  EQDC_CTRL_DMAEN(psConfig->enableDma);               /* Enable Dma. */
139 
140     /* Set mode of count. */
141     EQDC_SetCountMode(base, psConfig->countMode); /* eqdcoder count mode. */
142 
143     /* EQDC_CTRL2. */
144     base->CTRL2 =
145         EQDC_CTRL2_ONCE(psConfig->countOnce) |
146         EQDC_CTRL2_INITPOS(psConfig->enableTriggerInitPositionCounter) | /* TRIGGER initializes position counter. */
147 #if (defined(FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD) && FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD)
148         EQDC_CTRL2_EMIP(psConfig->enableIndexInitPositionCounter)|       /* Index Event Edge Mark initializes position counter */
149 #endif /* FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD */
150         EQDC_CTRL2_PMEN(psConfig->enablePeriodMeasurement) |             /* Enable period measurement. */
151         EQDC_CTRL2_OUTCTL(psConfig->outputPulseMode) |                   /* Output pulse. */
152         EQDC_CTRL2_REVMOD(psConfig->revolutionCountCondition) |          /* Revolution count condition. */
153         EQDC_CTRL2_LDMOD(psConfig->bufferedRegisterLoadMode) | /* Buffered register load (Update) mode select. */
154         EQDC_CTRL2_UPDPOS(psConfig->enableTriggerClearPositionRegisters) | /* TRIGGER clears position register. */
155         EQDC_CTRL2_UPDHLD(psConfig->enableTriggerHoldPositionRegisters);   /* TRIGGER loads position registers. */
156 
157     /* Set mode of operation. */
158     EQDC_SetOperateMode(base, psConfig->operateMode); /* eqdcoder work mode. */
159 
160     /* Enable interrupts. */
161     EQDC_EnableInterrupts(base, psConfig->enabledInterruptsMask);
162 }
163 
164 /*
165  * De-initializes the EQDC module.
166  *
167  * This function deinitializes the EQDC by:
168  * 1. Disables the IP bus clock (optional).
169  *
170  * param base EQDC peripheral base address.
171  */
EQDC_Deinit(EQDC_Type * base)172 void EQDC_Deinit(EQDC_Type *base)
173 {
174 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
175     /* Disable the clock. */
176     CLOCK_DisableClock(s_eqdcClocks[EQDC_GetInstance(base)]);
177 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
178 }
179 
180 /*!
181  * Gets an available pre-defined configuration.
182  *
183  * The default value are:
184  *    psConfig->enableReverseDirection              = false;
185  *    psConfig->countOnce                           = false;
186  *    psConfig->operateMode                         = kEQDC_QuadratureDecodeOperationMode;
187  *    psConfig->countMode                           = kEQDC_QuadratureX4;
188  *    psConfig->homeEnableInitPosCounterMode        = kEQDC_HomeInitPosCounterDisabled;
189  *    psConfig->indexPresetInitPosCounterMode       = kEQDC_IndexInitPosCounterDisabled;
190  *    psConfig->enableIndexInitPositionCounter      = false;
191  *    psConfig->enableDma                           = false;
192  *    psConfig->bufferedRegisterLoadMode            = false;
193  *    psConfig->enableTriggerInitPositionCounter    = false;
194  *    psConfig->enableTriggerClearPositionRegisters = false;
195  *    psConfig->enableTriggerHoldPositionRegisters  = false;
196  *    psConfig->enableWatchdog                      = false;
197  *    psConfig->watchdogTimeoutValue                = 0xFFFFU;
198  *    psConfig->filterPhaseA                        = 0U;
199  *    psConfig->filterPhaseB                        = 0U;
200  *    psConfig->filterIndPre                        = 0U;
201  *    psConfig->filterHomEna                        = 0U;
202  *    psConfig->filterClockSourceselection          = false;
203  *    psConfig->filterSampleCount                   = kEQDC_Filter3Samples;
204  *    psConfig->filterSamplePeriod                  = 0U;
205  *    psConfig->outputPulseMode                     = kEQDC_OutputPulseOnCounterEqualCompare;
206  *    psConfig->positionCompareValue[0]  	    = 0xFFFFFFFFU;
207  *    psConfig->positionCompareValue[1]             = 0xFFFFFFFFU;
208  *    psConfig->positionCompareValue[2]             = 0xFFFFFFFFU;
209  *    psConfig->positionCompareValue[3]             = 0xFFFFFFFFU;
210  *    psConfig->revolutionCountCondition            = kEQDC_RevolutionCountOnIndexPulse;
211  *    psConfig->positionModulusValue                = 0U;
212  *    psConfig->positionInitialValue                = 0U;
213  *    psConfig->positionCounterValue                = 0U;
214  *    psConfig->enablePeriodMeasurement             = false;
215  *    psConfig->prescaler                           = kEQDC_Prescaler1;
216  *    psConfig->enabledInterruptsMask               = 0U;
217  *
218  * param psConfig Pointer to configuration structure.
219  */
EQDC_GetDefaultConfig(eqdc_config_t * psConfig)220 void EQDC_GetDefaultConfig(eqdc_config_t *psConfig)
221 {
222     assert(NULL != psConfig);
223 
224     psConfig->enableReverseDirection              = false;
225     psConfig->countOnce                           = false;
226     psConfig->operateMode                         = kEQDC_QuadratureDecodeOperationMode; /*!< Decode Mode. */
227     psConfig->countMode                           = kEQDC_QuadratureX4;
228     psConfig->homeEnableInitPosCounterMode        = kEQDC_HomeInitPosCounterDisabled;
229     psConfig->indexPresetInitPosCounterMode       = kEQDC_IndexInitPosCounterDisabled;
230 #if (defined(FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD) && FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD)
231     psConfig->enableIndexInitPositionCounter      = false;
232 #endif /* FSL_FEATURE_EQDC_CTRL2_HAS_EMIP_BIT_FIELD */
233     psConfig->enableDma                           = false;
234     psConfig->bufferedRegisterLoadMode            = false;
235     psConfig->enableTriggerInitPositionCounter    = false;
236     psConfig->enableTriggerClearPositionRegisters = false;
237     psConfig->enableTriggerHoldPositionRegisters  = false;
238     psConfig->enableWatchdog                      = false;
239     psConfig->watchdogTimeoutValue                = 0xFFFFU;
240     psConfig->filterPhaseA                        = 0U;
241     psConfig->filterPhaseB                        = 0U;
242     psConfig->filterIndPre                        = 0U;
243     psConfig->filterHomEna                        = 0U;
244     psConfig->filterClockSourceselection          = false;
245     psConfig->filterSampleCount                   = kEQDC_Filter3Samples;
246     psConfig->filterSamplePeriod                  = 0U;
247     psConfig->outputPulseMode                     = kEQDC_OutputPulseOnCounterEqualCompare;
248     psConfig->positionCompareValue[0]             = 0xFFFFFFFFU;
249     psConfig->positionCompareValue[1]             = 0xFFFFFFFFU;
250     psConfig->positionCompareValue[2]             = 0xFFFFFFFFU;
251     psConfig->positionCompareValue[3]             = 0xFFFFFFFFU;
252     psConfig->revolutionCountCondition            = kEQDC_RevolutionCountOnIndexPulse;
253     psConfig->positionModulusValue                = 0U;
254     psConfig->positionInitialValue                = 0U;
255     psConfig->positionCounterValue                = 0U;
256     psConfig->enablePeriodMeasurement             = false;
257     psConfig->prescaler                           = kEQDC_Prescaler1;
258     psConfig->enabledInterruptsMask               = 0U;
259 }
260 
261 /*
262  * Initializes the mode of operation.
263  *
264  * The Quadrature Decoder operates in following 4 operation modes:
265  *   1.Quadrature Decode(QDC) Operation Mode (CTRL[PH1] = 0,CTRL2[OPMODE] = 0)
266  *   2.Quadrature Count(QCT) Operation Mode (CTRL[PH1] = 0,CTRL2[OPMODE] = 1)
267  *   3.Single Phase Decode(PH1DC) Operation Mode (CTRL[PH1] = 1,CTRL2[OPMODE] = 0)
268  *   4.Single Phase Count(PH1CT) Operation Mode (CTRL[PH1] = 1,CTRL2[OPMODE] = 1)
269  *
270  * param base   EQDC peripheral base address.
271  * param psConfig Pointer to configuration structure.
272  */
EQDC_SetOperateMode(EQDC_Type * base,eqdc_operate_mode_t operateMode)273 void EQDC_SetOperateMode(EQDC_Type *base, eqdc_operate_mode_t operateMode)
274 {
275     switch (operateMode)
276     {
277         case kEQDC_QuadratureDecodeOperationMode:
278             base->CTRL &= ~EQDC_CTRL_PH1_MASK;
279             base->CTRL2 &= ~EQDC_CTRL2_OPMODE_MASK;
280             break;
281 
282         case kEQDC_QuadratureCountOperationMode:
283             base->CTRL &= ~EQDC_CTRL_PH1_MASK;
284             base->CTRL2 |= EQDC_CTRL2_OPMODE_MASK;
285             break;
286 
287         case kEQDC_SinglePhaseDecodeOperationMode:
288             base->CTRL |= EQDC_CTRL_PH1_MASK;
289             base->CTRL2 &= ~EQDC_CTRL2_OPMODE_MASK;
290             break;
291 
292         case kEQDC_SinglePhaseCountOperationMode:
293             base->CTRL |= EQDC_CTRL_PH1_MASK;
294             base->CTRL2 |= EQDC_CTRL2_OPMODE_MASK;
295             break;
296 
297         default:
298             assert(false);
299             break;
300     }
301 }