1 /**
2  * @file xmc_dsd.c
3  * @date 2019-05-07
4  *
5  * @cond
6  **********************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification,are permitted provided that the following conditions are met:
14  *
15  *   Redistributions of source code must retain the above copyright notice,
16  *   this list of conditions and the following disclaimer.
17  *
18  *   Redistributions in binary form must reproduce the above copyright notice,
19  *   this list of conditions and the following disclaimer in the documentation
20  *   and/or other materials provided with the distribution.
21  *
22  *   Neither the name of the copyright holders nor the names of its contributors
23  *   may be used to endorse or promote products derived from this software without
24  *   specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30  * LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * To improve the quality of the software, users are encouraged to share
39  * modifications, enhancements or bug fixes with Infineon Technologies AG
40  * dave@infineon.com).
41  **********************************************************************************
42  *
43  * Change History
44  * --------------
45  *
46  * 2015-03-30:
47  *     - Initial version
48  *
49  * 2015-06-19:
50  *     - Removed GetDriverVersion API <BR>
51  *
52  * 2015-09-18:
53  *     - Support added for XMC4800 microcontroller family <BR>
54  *
55  * 2019-05-07:
56  *     - Fixed compilation warnings
57  *
58  * @endcond
59  *
60  */
61 
62 /*********************************************************************************************************************
63  * HEADER FILES
64  ********************************************************************************************************************/
65 #include "xmc_dsd.h"
66 
67 #if defined(DSD)
68 
69 /*********************************************************************************************************************
70  * MACROS
71  ********************************************************************************************************************/
72 
73 #define XMC_DSD_MIN_FILTER_START  (4U)
74 #define XMC_DSD_MIN_DECIMATION_FACTOR (4U)
75 #define XMC_DSD_MAX_DECIMATION_FACTOR (256U)
76 #define XMC_DSD_MAX_DECIMATION_FACTOR_AUX (32U)
77 
78 /*********************************************************************************************************************
79  * API IMPLEMENTATION
80  ********************************************************************************************************************/
81 
82 /*Enable the DSD Module*/
XMC_DSD_Enable(XMC_DSD_t * const dsd)83 void XMC_DSD_Enable(XMC_DSD_t *const dsd)
84 {
85   XMC_ASSERT("XMC_DSD_Enable:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
86   XMC_UNUSED_ARG(dsd);
87 
88 #if defined(CLOCK_GATING_SUPPORTED)
89   XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_DSD);
90 #endif
91   XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_DSD);
92 }
93 
94 /*Disable the DSD Module*/
XMC_DSD_Disable(XMC_DSD_t * const dsd)95 void XMC_DSD_Disable(XMC_DSD_t *const dsd)
96 {
97   XMC_ASSERT("XMC_DSD_Disable:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
98   XMC_UNUSED_ARG(dsd);
99 
100   XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_DSD);
101 #if defined(CLOCK_GATING_SUPPORTED)
102   XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_DSD);
103 #endif
104 }
105 
106 /* Enable the module clock*/
XMC_DSD_EnableClock(XMC_DSD_t * const dsd)107 void XMC_DSD_EnableClock(XMC_DSD_t *const dsd)
108 {
109   XMC_ASSERT("XMC_DSD_EnableClock:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
110   /* Enable the module clock */
111   dsd->CLC &= ~(uint32_t)DSD_CLC_DISR_Msk;
112   /* enable internal module clock */
113   dsd ->GLOBCFG |= (uint32_t)0x01;
114 }
115 
XMC_DSD_DisableClock(XMC_DSD_t * const dsd)116 void XMC_DSD_DisableClock(XMC_DSD_t *const dsd)
117 {
118   XMC_ASSERT("XMC_DSD_DisableClock:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
119 
120   /* disable internal module clock */
121   dsd->GLOBCFG &= ~(uint32_t)DSD_GLOBCFG_MCSEL_Msk;
122 
123   /* stop the module clock */
124   dsd->CLC |= (uint32_t)DSD_CLC_DISR_Msk;
125 
126 }
127 
128 /* Enable the DSD module and clock */
XMC_DSD_Init(XMC_DSD_t * const dsd)129 void XMC_DSD_Init(XMC_DSD_t *const dsd)
130 {
131   XMC_ASSERT("XMC_DSD_Init:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
132   XMC_DSD_Enable(dsd);
133   XMC_DSD_EnableClock(dsd);
134 }
135 
XMC_DSD_IsEnabled(XMC_DSD_t * const dsd)136 bool XMC_DSD_IsEnabled(XMC_DSD_t *const dsd)
137 {
138   bool status;
139   XMC_ASSERT("XMC_DSD_Disable:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
140   XMC_UNUSED_ARG(dsd);
141 
142   #if ((UC_SERIES == XMC44) || (UC_SERIES == XMC48)||(UC_SERIES == XMC47))
143   if(XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_DSD) == false)
144   {
145     if(XMC_SCU_CLOCK_IsPeripheralClockGated(XMC_SCU_PERIPHERAL_CLOCK_DSD) == false)
146     {
147       status = true;
148     }
149 	else
150 	{
151       status = false;
152 	}
153   }
154   else
155   {
156     status = false;
157   }
158   #else
159   if(XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_DSD) == false)
160   {
161     status = true;
162   }
163   else
164   {
165     status = false;
166   }
167   #endif
168 
169   return (status);
170 }
171 
172 /*Initializes the Waveform Generator*/
XMC_DSD_Generator_Init(XMC_DSD_t * const dsd,const XMC_DSD_GENERATOR_CONFIG_t * const config)173 void XMC_DSD_Generator_Init(XMC_DSD_t *const dsd, const XMC_DSD_GENERATOR_CONFIG_t *const config)
174 {
175   XMC_ASSERT("XMC_DSD_GENERATOR_Init:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd));
176   XMC_ASSERT("XMC_DSD_GENERATOR_Init:NULL Pointer", (config != (XMC_DSD_GENERATOR_CONFIG_t *)NULL) );
177   /* Reset Generator */
178   dsd ->CGCFG &= ~((uint32_t)DSD_CGCFG_CGMOD_Msk | (uint32_t)DSD_CGCFG_BREV_Msk | (uint32_t)DSD_CGCFG_SIGPOL_Msk | (uint32_t)DSD_CGCFG_DIVCG_Msk);
179 
180   /* Generator configuration */
181   dsd ->CGCFG = config->generator_conf;
182 }
183 
184 /* Initialize main filter,auxiliary filter,integrator, rectifier and timestamp of DSD*/
XMC_DSD_CH_Init(XMC_DSD_CH_t * const channel,const XMC_DSD_CH_CONFIG_t * const config)185 XMC_DSD_STATUS_t XMC_DSD_CH_Init( XMC_DSD_CH_t *const channel, const XMC_DSD_CH_CONFIG_t *const config)
186 {
187   XMC_DSD_STATUS_t status;
188 
189   XMC_ASSERT("XMC_DSD_CH_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel));
190   XMC_ASSERT("XMC_DSD_CH_Init:NULL Pointer", (config != (XMC_DSD_CH_CONFIG_t *)NULL) );
191 
192   if (config->filter != (XMC_DSD_CH_FILTER_CONFIG_t*)NULL)
193   {
194     XMC_DSD_CH_MainFilter_Init(channel, config->filter);
195 
196     if (config->aux != (XMC_DSD_CH_AUX_FILTER_CONFIG_t*)NULL)
197     {
198       XMC_DSD_CH_AuxFilter_Init(channel, config->aux);
199     }
200     if (config->integrator != (XMC_DSD_CH_INTEGRATOR_CONFIG_t*)NULL)
201     {
202       XMC_DSD_CH_Integrator_Init(channel, config->integrator);
203     }
204     if (config->rectify != (XMC_DSD_CH_RECTIFY_CONFIG_t*)NULL)
205     {
206       XMC_DSD_CH_Rectify_Init(channel, config->rectify);
207     }
208     if (config->timestamp != (XMC_DSD_CH_TIMESTAMP_CONFIG_t*)NULL)
209     {
210       XMC_DSD_CH_Timestamp_Init(channel, config->timestamp);
211     }
212     status =  XMC_DSD_STATUS_OK;
213   }
214   else
215   {
216     status =  XMC_DSD_STATUS_ERROR;
217   }
218   return (status);
219 
220 }
221 
222 /* Initialize main filter of DSD */
XMC_DSD_CH_MainFilter_Init(XMC_DSD_CH_t * const channel,const XMC_DSD_CH_FILTER_CONFIG_t * const config)223 void XMC_DSD_CH_MainFilter_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_FILTER_CONFIG_t *const config)
224 {
225   uint32_t decimation_factor_temp;
226   uint32_t filter_start_value_temp;
227 
228   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel));
229   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:NULL Pointer", (config != (XMC_DSD_CH_FILTER_CONFIG_t *)NULL) );
230   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid Filter Start Value", (config->filter_start_value >= XMC_DSD_MIN_FILTER_START));
231   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid Filter Start Value", (config->filter_start_value <= config->decimation_factor));
232   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid Decimation Factor",
233       ((config->decimation_factor >= XMC_DSD_MIN_DECIMATION_FACTOR) && (config->decimation_factor <= XMC_DSD_MAX_DECIMATION_FACTOR)));
234 
235   /*Set Channel frequency*/
236   channel->MODCFG = ((uint32_t)config->clock_divider << DSD_CH_MODCFG_DIVM_Pos) | (uint32_t)DSD_CH_MODCFG_DWC_Msk;
237 
238   /* Input Data/Clk */
239   channel->DICFG = config->demodulator_conf | (uint32_t)DSD_CH_DICFG_DSWC_Msk | (uint32_t)DSD_CH_DICFG_SCWC_Msk;
240 
241   /*The decimation factor of the Main CIC filter is CFMDF + 1.*/
242   decimation_factor_temp = config->decimation_factor-1U;
243   filter_start_value_temp = config->filter_start_value-1U;
244 
245   /* Filter setup*/
246   channel->FCFGC = (decimation_factor_temp |
247 		  (filter_start_value_temp << (uint32_t)DSD_CH_FCFGC_CFMSV_Pos)|
248 		  config->main_filter_conf|
249 		  (uint32_t)DSD_CH_FCFGC_CFEN_Msk);
250 
251   /* Offset */
252   channel->OFFM = (uint16_t)config->offset;
253 }
254 
255 /* Initialize timestamp mode of DSD */
XMC_DSD_CH_Timestamp_Init(XMC_DSD_CH_t * const channel,const XMC_DSD_CH_TIMESTAMP_CONFIG_t * const config)256 void XMC_DSD_CH_Timestamp_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_TIMESTAMP_CONFIG_t *const config)
257 {
258   uint32_t temp;
259   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel));
260   XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:NULL Pointer", (config != (XMC_DSD_CH_TIMESTAMP_CONFIG_t *)NULL) );
261 
262   temp = (channel->DICFG | (uint32_t)DSD_CH_DICFG_TRWC_Msk);
263   temp &= ~((uint32_t)DSD_CH_DICFG_TSTRMODE_Msk|(uint32_t)DSD_CH_DICFG_TRSEL_Msk);
264   temp |= config->timestamp_conf;
265   channel->DICFG = temp;
266 }
267 
268 /* Initialize auxiliary filter of DSD */
XMC_DSD_CH_AuxFilter_Init(XMC_DSD_CH_t * const channel,const XMC_DSD_CH_AUX_FILTER_CONFIG_t * const config)269 void XMC_DSD_CH_AuxFilter_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_AUX_FILTER_CONFIG_t *const config)
270 {
271   uint32_t decimation_factor_temp;
272 
273   XMC_ASSERT("XMC_DSD_AUX_FILTER_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel));
274   XMC_ASSERT("XMC_DSD_AUX_FILTER_Init:NULL Pointer", (config != (XMC_DSD_CH_AUX_FILTER_CONFIG_t *)NULL) );
275   XMC_ASSERT("XMC_DSD_AUX_FILTER_Init:Invalid Decimation Factor",
276       ((config->decimation_factor >= XMC_DSD_MIN_DECIMATION_FACTOR) && (config->decimation_factor <= XMC_DSD_MAX_DECIMATION_FACTOR_AUX)));
277 
278   channel->BOUNDSEL = config->boundary_conf;
279   /*The decimation factor of the Aux CIC filter is CFMDF + 1.*/
280   decimation_factor_temp = config->decimation_factor-1U;
281   channel->FCFGA = (decimation_factor_temp | config->aux_filter_conf);
282 }
283 
284 /* Integrator initialization of DSD */
XMC_DSD_CH_Integrator_Init(XMC_DSD_CH_t * const channel,const XMC_DSD_CH_INTEGRATOR_CONFIG_t * const config)285 void XMC_DSD_CH_Integrator_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_INTEGRATOR_CONFIG_t *const config)
286 {
287   uint32_t temp;
288   XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel));
289   XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:NULL Pointer", (config != (XMC_DSD_CH_INTEGRATOR_CONFIG_t *)NULL) );
290   XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:Invalid integration_loop", (config->integration_loop > 0U ));
291   XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:Invalid counted_values", (config->counted_values > 0U ));
292 
293   channel->IWCTR = ((config->integration_loop - 1U) << DSD_CH_IWCTR_REPVAL_Pos)
294                    | (config->discarded_values << DSD_CH_IWCTR_NVALDIS_Pos)
295                    | (config->stop_condition << DSD_CH_IWCTR_IWS_Pos)
296                    | ((config->counted_values - 1U) << DSD_CH_IWCTR_NVALINT_Pos);
297 
298   /*To ensure proper operation, ensure that bit field ITRMODE is zero before selecting any other trigger mode.*/
299   temp = (channel->DICFG & ~((uint32_t)DSD_CH_DICFG_ITRMODE_Msk|(uint32_t)DSD_CH_DICFG_TRSEL_Msk)) | (uint32_t)DSD_CH_DICFG_TRWC_Msk;
300 
301   channel->DICFG = temp;
302 
303   temp |=  config->integrator_trigger;
304   channel->DICFG = temp;
305 }
306 
307 /* Rectifier initialization of DSD */
XMC_DSD_CH_Rectify_Init(XMC_DSD_CH_t * const channel,const XMC_DSD_CH_RECTIFY_CONFIG_t * const config)308 void XMC_DSD_CH_Rectify_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_RECTIFY_CONFIG_t *const config)
309 {
310   XMC_ASSERT("XMC_DSD_RECTIFY_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel));
311   XMC_ASSERT("XMC_DSD_RECTIFY_Init:NULL Pointer", (config != (XMC_DSD_CH_RECTIFY_CONFIG_t *)NULL));
312   XMC_ASSERT("XMC_DSD_RECTIFY_Init:NULL Pointer", (((uint16_t)config->delay + (uint16_t)config->half_cycle) <= 0xFF));
313 
314   channel->RECTCFG = config->rectify_config | (uint32_t)DSD_CH_RECTCFG_RFEN_Msk;
315   channel->CGSYNC = (((uint32_t) config->delay << (uint32_t)DSD_CH_CGSYNC_SDPOS_Pos)
316                       | (((uint32_t)config->delay + (uint32_t)config->half_cycle) << (uint32_t)DSD_CH_CGSYNC_SDNEG_Pos));
317 }
318 
319 /* API to get the result of the last conversion */
XMC_DSD_CH_GetResult_TS(XMC_DSD_CH_t * const channel,int16_t * dsd_result,uint8_t * dsd_filter_count,uint8_t * dsd_integration_count)320 void XMC_DSD_CH_GetResult_TS(XMC_DSD_CH_t* const channel,
321                              int16_t* dsd_result,
322                              uint8_t* dsd_filter_count,
323                              uint8_t* dsd_integration_count)
324 {
325   uint32_t timestamp;
326   uint16_t result;
327 
328   timestamp = channel->TSTMP;
329   result = (uint16_t)((uint32_t)timestamp & DSD_CH_TSTMP_RESULT_Msk);
330   *dsd_result = (int16_t)(result);
331   *dsd_filter_count = (uint8_t) ((timestamp & (uint32_t)DSD_CH_TSTMP_CFMDCNT_Msk)>>(uint32_t)DSD_CH_TSTMP_CFMDCNT_Pos);
332   *dsd_integration_count = (uint8_t) ((timestamp & (uint32_t)DSD_CH_TSTMP_NVALCNT_Msk)>>(uint32_t)DSD_CH_TSTMP_NVALCNT_Pos);
333 }
334 
335 /* API to get the result of the last conversion with the time */
XMC_DSD_CH_GetResult_TS_Time(XMC_DSD_CH_t * const channel,int16_t * dsd_Result,uint32_t * time)336 void XMC_DSD_CH_GetResult_TS_Time(XMC_DSD_CH_t* const channel, int16_t* dsd_Result, uint32_t* time)
337 {
338   uint32_t timestamp;
339   uint16_t filter_count;
340   uint16_t integrator_count;
341   uint16_t decimation;
342   uint16_t result;
343 
344   timestamp = channel->TSTMP;
345   decimation = (uint16_t)(channel->FCFGC & DSD_CH_FCFGC_CFMDF_Msk);
346   filter_count = (uint16_t)((timestamp & DSD_CH_TSTMP_CFMDCNT_Msk)>>DSD_CH_TSTMP_CFMDCNT_Pos);
347 
348   /* Integration enabled? */
349   if ((channel->IWCTR & DSD_CH_IWCTR_INTEN_Msk))
350   {
351     integrator_count = (uint16_t) ((timestamp & DSD_CH_TSTMP_NVALCNT_Msk)>>DSD_CH_TSTMP_NVALCNT_Pos);
352 
353     /*See Errata number: xxyy */
354     if (filter_count == decimation)
355     {
356       integrator_count++;
357     }
358     *time = (uint32_t)(((uint32_t) integrator_count * ((uint32_t) decimation + 1U)) + (uint32_t) ((uint32_t)decimation - filter_count));
359   }
360   else
361   {
362     *time = (uint32_t) ((uint32_t)decimation - filter_count);
363   }
364   result = (uint16_t)((uint32_t)timestamp & DSD_CH_TSTMP_RESULT_Msk);
365   *dsd_Result = (int16_t)(result);
366 }
367 
368 
369 
370 #endif /*DSD*/
371 
372 
373