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 }