1 /*
2 * Copyright 2022-2023 NXP
3 *
4 * All rights reserved.
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_sinc.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.sinc"
17 #endif
18
19 /*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
23 static uint8_t SINC_GetInstance(SINC_Type *base);
24 #endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/
25
26 /*******************************************************************************
27 * Variables
28 ******************************************************************************/
29 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
30 /*! brief Pointer to SINC clocks for each instance. */
31 static clock_ip_name_t const s_sincClocks[] = SINC_CLOCKS;
32
33 /*! brief Pointers to SINC bases for each instance. */
34 static SINC_Type *const s_sincBases[] = SINC_BASE_PTRS;
35
36 #endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/
37
38 /*******************************************************************************
39 * Code
40 ******************************************************************************/
41
42 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
SINC_GetInstance(SINC_Type * base)43 static uint8_t SINC_GetInstance(SINC_Type *base)
44 {
45 uint8_t instance;
46
47 /* Find the instance index from base address mappings. */
48 for (instance = 0U; instance < ARRAY_SIZE(s_sincBases); instance++)
49 {
50 if (s_sincBases[instance] == base)
51 {
52 break;
53 }
54 }
55
56 assert(instance < ARRAY_SIZE(s_sincBases));
57
58 return instance;
59 }
60 #endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/
61
62 /*!
63 * brief Initialize selected SINC instance, including clock options and channel options.
64 *
65 * param base SINC peripheral base address.
66 * param config The pointer to sinc_config_t structure.
67 */
SINC_Init(SINC_Type * base,const sinc_config_t * config)68 void SINC_Init(SINC_Type *base, const sinc_config_t *config)
69 {
70 assert(config != NULL);
71 uint8_t i = 0U;
72
73 /* Enable SINC clock root. */
74 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
75 CLOCK_EnableClock(s_sincClocks[SINC_GetInstance(base)]);
76 #endif /*FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL*/
77
78 SINC_EnableMaster(base, false);
79 /* Reset all function blocks except for the clock. */
80 SINC_DoSoftwareReset(base);
81
82 /* Set clock configuration. */
83 SINC_SetClkPrescale(base, config->clockPreDivider);
84 SINC_SetModulatorClockDivider(base, config->modClkDivider);
85 SINC_DisableModulatorClockOutput(base, (uint32_t)kSINC_ModClk0, config->disableModClk0Output);
86 SINC_DisableModulatorClockOutput(base, (uint32_t)kSINC_ModClk1, config->disableModClk1Output);
87 SINC_DisableModulatorClockOutput(base, (uint32_t)kSINC_ModClk2, config->disableModClk2Output);
88
89 SINC_DisableDozeMode(base, config->disableDozeMode);
90
91 for (i = 0U; i < (uint8_t)SINC_CHANNEL_COUNT; i++)
92 {
93 if (config->channelsConfigArray[i] != NULL)
94 {
95 SINC_SetChannelConfig(base, (sinc_channel_id_t)i, config->channelsConfigArray[i]);
96 }
97 }
98
99 SINC_EnableMaster(base, config->enableMaster);
100 if ((config->disableModClk0Output == false) && (config->enableMaster == true))
101 {
102 while (!SINC_CheckModulatorClockReady(base, (uint32_t)kSINC_ModClk0))
103 {
104 /* Loop until Modulator clock 0 is ready. */
105 ;
106 }
107 }
108 else if ((config->disableModClk1Output == false) && (config->enableMaster == true))
109 {
110 while (!SINC_CheckModulatorClockReady(base, (uint32_t)kSINC_ModClk1))
111 {
112 /* Loop until Modulator clock 0 is ready. */
113 ;
114 }
115 }
116 else if ((config->disableModClk2Output == false) && (config->enableMaster == true))
117 {
118 while (!SINC_CheckModulatorClockReady(base, (uint32_t)kSINC_ModClk2))
119 {
120 /* Loop until Modulator clock 0 is ready. */
121 ;
122 }
123 }
124 else
125 {
126 /* Added comments to avoid violations of MISRA C-2012 rules. */
127 }
128 }
129
130 /*!
131 * brief De-initialize selected SINC instance.
132 *
133 * param base SINC peripheral base address.
134 */
SINC_Deinit(SINC_Type * base)135 void SINC_Deinit(SINC_Type *base)
136 {
137 SINC_DoSoftwareReset(base);
138 /* Disable master */
139 SINC_EnableMaster(base, false);
140
141 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
142 CLOCK_DisableClock(s_sincClocks[SINC_GetInstance(base)]);
143 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
144 }
145
146 /*!
147 * brief Get default configuration.
148 *
149 * code {.c}
150 * config->clockPreDivider = kSINC_ClkPrescale1;
151 * config->modClkDivider = 2UL;
152 * config->disableModClk0Output = false;
153 * config->disableModClk1Output = false;
154 * config->disableModClk2Output = false;
155 *
156 * config->channelsConfigArray[SINC_CHANNEL_COUNT] = {NULL, NULL, NULL, NULL};
157 *
158 * config->disableDozeMode = false;
159 * config->enableMaster = false;
160 * endcode
161 *
162 *
163 * param config The pointer to sinc_config_t structure, must not be NULL.
164 */
SINC_GetDefaultConfig(sinc_config_t * config)165 void SINC_GetDefaultConfig(sinc_config_t *config)
166 {
167 assert(config != NULL);
168
169 config->clockPreDivider = kSINC_ClkPrescale1;
170 config->modClkDivider = 2UL;
171 config->disableModClk0Output = false;
172 config->disableModClk1Output = false;
173 config->disableModClk2Output = false;
174
175 for (uint8_t i = 0U; i < (uint8_t)SINC_CHANNEL_COUNT; i++)
176 {
177 config->channelsConfigArray[i] = NULL;
178 }
179
180 config->disableDozeMode = false;
181 config->enableMaster = false;
182 }
183
184 /*!
185 * brief Set channel configurations, including input options, conversion options and protection options.
186 *
187 * param base SINC peripheral base address.
188 * param chId Selected channel id, please refer to sinc_channel_id_t.
189 * param chConfig Pointer to sinc_channel_config_t structure, must not be NULL.
190 */
SINC_SetChannelConfig(SINC_Type * base,sinc_channel_id_t chId,sinc_channel_config_t * chConfig)191 void SINC_SetChannelConfig(SINC_Type *base, sinc_channel_id_t chId, sinc_channel_config_t *chConfig)
192 {
193 assert(chConfig != NULL);
194
195 SINC_EnableChannel(base, chId, false);
196
197 /* Set channel input options, including input clock and input source. */
198 SINC_SetChannelInputOption(base, chId, chConfig->chInputOption);
199
200 /* Set channel conversion options, including trigger source and primary filter. */
201 SINC_SetChannelConversionOption(base, chId, chConfig->chConvOption);
202
203 /* Set channel protection options, including SCD, limit check, CAD, zero crossing. */
204 SINC_SetChannelProtectionOption(base, chId, chConfig->chProtectionOption);
205
206 SINC_EnableChannelFIFO(base, chId, chConfig->bEnableFifo);
207 SINC_SetChannelFifoWatermark(base, chId, chConfig->u8FifoWaterMark);
208
209 SINC_EnableChannelPrimaryDma(base, chId, chConfig->bEnablePrimaryDma);
210
211 #if (defined(FSL_FEATURE_SINC_CACFR_HAS_ADMASEL) && FSL_FEATURE_SINC_CACFR_HAS_ADMASEL)
212 SINC_SetChannelAltDmaSource(base, chId, chConfig->altDmaSource);
213 #endif /* (defined(FSL_FEATURE_SINC_CACFR_HAS_ADMASEL) && FSL_FEATURE_SINC_CACFR_HAS_ADMASEL) */
214
215 SINC_SetChannelResultDataFormat(base, chId, chConfig->dataFormat);
216
217 SINC_EnableChannel(base, chId, chConfig->bEnableChannel);
218 }
219 /*!
220 * brief Set channel input options, including input bit format, input bit source, input bit delay, input clock source,
221 * input clock edge.
222 *
223 * param base SINC peripheral base address.
224 * param chId Selected channel id, please refer to sinc_channel_id_t.
225 * param chInputOption Pointer to sinc_channel_input_option_t structure, must not be NULL.
226 */
SINC_SetChannelInputOption(SINC_Type * base,sinc_channel_id_t chId,sinc_channel_input_option_t * chInputOption)227 void SINC_SetChannelInputOption(SINC_Type *base, sinc_channel_id_t chId, sinc_channel_input_option_t *chInputOption)
228 {
229 assert(chInputOption != NULL);
230
231 uint32_t u32Tmp;
232
233 u32Tmp = ((base->CHANNEL[(uint8_t)chId].CCFR) &
234 ~(SINC_CCFR_IBFMT_MASK | SINC_CCFR_ICSEL_MASK | SINC_CCFR_ICESEL_MASK | SINC_CCFR_IBSEL_MASK));
235 u32Tmp |= SINC_CCFR_ICSEL(chInputOption->inputClkSource) | SINC_CCFR_IBFMT(chInputOption->inputBitFormat) |
236 SINC_CCFR_ICESEL(chInputOption->inputClkEdge) | SINC_CCFR_IBSEL(chInputOption->inputBitSource);
237 base->CHANNEL[(uint8_t)chId].CCFR = u32Tmp;
238
239 u32Tmp = ((base->CHANNEL[(uint8_t)chId].CACFR) & ~SINC_CACFR_IBDLY_MASK);
240 u32Tmp |= SINC_CACFR_IBDLY(chInputOption->inputBitDelay);
241 base->CHANNEL[(uint8_t)chId].CACFR = u32Tmp;
242 }
243
244 /*!
245 * brief Set channel conversion options, including conversion mode, trigger source, and primary filter settings.
246 *
247 * param base SINC peripheral base address.
248 * param chId Selected channel id, please refer to sinc_channel_id_t.
249 * param chConvOption Pointer to sinc_channel_conv_option_t structure, must not be NULL.
250 */
SINC_SetChannelConversionOption(SINC_Type * base,sinc_channel_id_t chId,sinc_channel_conv_option_t * chConvOption)251 void SINC_SetChannelConversionOption(SINC_Type *base, sinc_channel_id_t chId, sinc_channel_conv_option_t *chConvOption)
252 {
253 assert(chConvOption != NULL);
254
255 /* Set trigger source. */
256 SINC_SetChannelTriggerSource(base, chId, chConvOption->convTriggerSource);
257
258 /* Set PF CIC options. */
259 SINC_SetChannelConversionMode(base, chId, chConvOption->convMode);
260 SINC_SetChannelPfOrder(base, chId, chConvOption->pfOrder);
261 SINC_SetChannelPfOsr(base, chId, chConvOption->u16pfOverSampleRatio);
262
263 /* Set HPF alpha coefficient. */
264 SINC_SetChannelPfHpfAlphaCoeff(base, chId, chConvOption->pfHpfAlphaCoeff);
265
266 /* Set shift options */
267 SINC_SetChannelPfShiftConfig(base, chId, chConvOption->pfShiftDirection, chConvOption->u8pfShiftBitsNum);
268
269 /* Set bias options. */
270 SINC_SetChannelPfBiasConfig(base, chId, chConvOption->pfBiasSign, chConvOption->u32pfBiasValue);
271
272 /* Enable channel's primary filter. */
273 SINC_EnableChannelPrimaryFilter(base, chId, chConvOption->enableChPrimaryFilter);
274 }
275
276 /*!
277 * brief Set channel protection options, including limit check, short-circuit detector, clock-absence detector, and
278 * zero-crossing detector.
279 *
280 * param base SINC peripheral base address.
281 * param chId Selected channel id, please refer to sinc_channel_id_t.
282 * param chProtection Pointer to sinc_channel_protection_option_t, must not be NULL.
283 */
SINC_SetChannelProtectionOption(SINC_Type * base,sinc_channel_id_t chId,sinc_channel_protection_option_t * chProtection)284 void SINC_SetChannelProtectionOption(SINC_Type *base,
285 sinc_channel_id_t chId,
286 sinc_channel_protection_option_t *chProtection)
287 {
288 assert(chProtection != NULL);
289
290 /* limit check */
291 if (chProtection->limitDetectorMode == kSINC_Lmt_Disabled)
292 {
293 base->CHANNEL[(uint8_t)chId].CCR &= ~SINC_CCR_LMTEN_MASK;
294 }
295 else
296 {
297 SINC_SetChannelLowLimitThreshold(base, chId, chProtection->u32LowLimitThreshold);
298 SINC_SetChannelHighLimitThreshold(base, chId, chProtection->u32HighLimitThreshold);
299 base->CHANNEL[(uint8_t)chId].CPROT = (base->CHANNEL[(uint8_t)chId].CPROT & ~SINC_CPROT_LMTOP_MASK) |
300 SINC_CPROT_LMTOP((uint32_t)chProtection->limitDetectorMode & 0x3UL);
301 if (chProtection->bEnableLmtBreakSignal)
302 {
303 base->CHANNEL[(uint8_t)chId].CPROT |=
304 (((((uint32_t)(chProtection->limitDetectorMode)) & 0x1CUL) >> 2UL) << SINC_CPROT_LLMTBK_SHIFT);
305 }
306 else
307 {
308 base->CHANNEL[(uint8_t)chId].CPROT &=
309 ~(((((uint32_t)(chProtection->limitDetectorMode)) & 0x1CUL) >> 2UL) << SINC_CPROT_LLMTBK_SHIFT);
310 }
311 base->CHANNEL[(uint8_t)chId].CCR |= SINC_CCR_LMTEN_MASK;
312 }
313
314 /* Short-circuit detector. */
315 if (chProtection->scdOperateMode == kSINC_Scd_OperateDisabled)
316 {
317 SINC_SetChannelScdOperateMode(base, chId, kSINC_Scd_OperateDisabled);
318 }
319 else
320 {
321 SINC_SetChannelScdLimitThreshold(base, chId, chProtection->u8ScdLimitThreshold);
322 SINC_SetChannelScdOption(base, chId, chProtection->scdOption);
323 SINC_EnableChannelScdBreakSignal(base, chId, chProtection->bEnableScdBreakSignal);
324 SINC_SetChannelScdOperateMode(base, chId, chProtection->scdOperateMode);
325 }
326
327 /* Clock-absence detector. */
328 SINC_EnableChannelCadBreakSignal(base, chId, chProtection->bEnableCadBreakSignal);
329 SINC_SetChannelCadLimitThreshold(base, chId, chProtection->cadLimitThreshold);
330
331 /* zero-crossing detector. */
332 SINC_SetChannelZcdOperateMode(base, chId, chProtection->zcdOperateMode);
333 }
334
335 /*!
336 * brief Get selected channel's number of conversions.
337 *
338 * param base SINC peripheral base address.
339 * param chId Selected channel id, refer to sinc_channel_id_t for details.
340 * return uint8_t Selected channel's number of conversions.
341 */
SINC_GetChannelConversionCount(SINC_Type * base,sinc_channel_id_t chId)342 uint8_t SINC_GetChannelConversionCount(SINC_Type *base, sinc_channel_id_t chId)
343 {
344 uint8_t u8Count;
345
346 u8Count = (uint8_t)((base->CHANNEL[(uint8_t)chId].CSR & SINC_CSR_CNUM_MASK) >> SINC_CSR_CNUM_SHIFT);
347 if ((base->CHANNEL[(uint8_t)chId].CSR & SINC_CSR_CNUM_OV_MASK) != 0UL)
348 {
349 u8Count += 128U;
350 }
351
352 return u8Count;
353 }
354