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