/** * @file xmc_dsd.c * @date 2015-09-18 * * @cond ********************************************************************************** * XMClib v2.1.12 - XMC Peripheral Driver Library * * Copyright (c) 2015-2017, Infineon Technologies AG * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification,are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the copyright holders nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * To improve the quality of the software, users are encouraged to share * modifications, enhancements or bug fixes with Infineon Technologies AG * dave@infineon.com). ********************************************************************************** * * Change History * -------------- * * 2015-03-30: * - Initial version * * 2015-06-19: * - Removed GetDriverVersion API
* * 2015-09-18: * - Support added for XMC4800 microcontroller family
* @endcond * */ /********************************************************************************************************************* * HEADER FILES ********************************************************************************************************************/ #include "xmc_dsd.h" #if defined(DSD) /********************************************************************************************************************* * MACROS ********************************************************************************************************************/ #define XMC_DSD_MIN_FILTER_START (4U) #define XMC_DSD_MIN_DECIMATION_FACTOR (4U) #define XMC_DSD_MAX_DECIMATION_FACTOR (256U) #define XMC_DSD_MAX_DECIMATION_FACTOR_AUX (32U) /********************************************************************************************************************* * API IMPLEMENTATION ********************************************************************************************************************/ /*Enable the DSD Module*/ void XMC_DSD_Enable(XMC_DSD_t *const dsd) { XMC_ASSERT("XMC_DSD_Enable:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); XMC_UNUSED_ARG(dsd); #if defined(CLOCK_GATING_SUPPORTED) XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_DSD); #endif XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_DSD); } /*Disable the DSD Module*/ void XMC_DSD_Disable(XMC_DSD_t *const dsd) { XMC_ASSERT("XMC_DSD_Disable:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); XMC_UNUSED_ARG(dsd); XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_DSD); #if defined(CLOCK_GATING_SUPPORTED) XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_DSD); #endif } /* Enable the module clock*/ void XMC_DSD_EnableClock(XMC_DSD_t *const dsd) { XMC_ASSERT("XMC_DSD_EnableClock:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); /* Enable the module clock */ dsd->CLC &= ~(uint32_t)DSD_CLC_DISR_Msk; /* enable internal module clock */ dsd ->GLOBCFG |= (uint32_t)0x01; } void XMC_DSD_DisableClock(XMC_DSD_t *const dsd) { XMC_ASSERT("XMC_DSD_DisableClock:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); /* disable internal module clock */ dsd->GLOBCFG &= ~(uint32_t)DSD_GLOBCFG_MCSEL_Msk; /* stop the module clock */ dsd->CLC |= (uint32_t)DSD_CLC_DISR_Msk; } /* Enable the DSD module and clock */ void XMC_DSD_Init(XMC_DSD_t *const dsd) { XMC_ASSERT("XMC_DSD_Init:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); XMC_DSD_Enable(dsd); XMC_DSD_EnableClock(dsd); } bool XMC_DSD_IsEnabled(XMC_DSD_t *const dsd) { bool status; XMC_ASSERT("XMC_DSD_Disable:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); XMC_UNUSED_ARG(dsd); #if ((UC_SERIES == XMC44) || (UC_SERIES == XMC48)||(UC_SERIES == XMC47)) if(XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_DSD) == false) { if(XMC_SCU_CLOCK_IsPeripheralClockGated(XMC_SCU_PERIPHERAL_CLOCK_DSD) == false) { status = true; } else { status = false; } } else { status = false; } #else if(XMC_SCU_RESET_IsPeripheralResetAsserted(XMC_SCU_PERIPHERAL_RESET_DSD) == false) { status = true; } else { status = false; } #endif return (status); } /*Initializes the Waveform Generator*/ void XMC_DSD_Generator_Init(XMC_DSD_t *const dsd, const XMC_DSD_GENERATOR_CONFIG_t *const config) { XMC_ASSERT("XMC_DSD_GENERATOR_Init:Invalid module pointer", XMC_DSD_CHECK_MODULE_PTR(dsd)); XMC_ASSERT("XMC_DSD_GENERATOR_Init:NULL Pointer", (config != (XMC_DSD_GENERATOR_CONFIG_t *)NULL) ); /* Reset Generator */ 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); /* Generator configuration */ dsd ->CGCFG = config->generator_conf; } /* Initialize main filter,auxiliary filter,integrator, rectifier and timestamp of DSD*/ XMC_DSD_STATUS_t XMC_DSD_CH_Init( XMC_DSD_CH_t *const channel, const XMC_DSD_CH_CONFIG_t *const config) { XMC_DSD_STATUS_t status; XMC_ASSERT("XMC_DSD_CH_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel)); XMC_ASSERT("XMC_DSD_CH_Init:NULL Pointer", (config != (XMC_DSD_CH_CONFIG_t *)NULL) ); if (config->filter != (XMC_DSD_CH_FILTER_CONFIG_t*)NULL) { XMC_DSD_CH_MainFilter_Init(channel, config->filter); if (config->aux != (XMC_DSD_CH_AUX_FILTER_CONFIG_t*)NULL) { XMC_DSD_CH_AuxFilter_Init(channel, config->aux); } if (config->integrator != (XMC_DSD_CH_INTEGRATOR_CONFIG_t*)NULL) { XMC_DSD_CH_Integrator_Init(channel, config->integrator); } if (config->rectify != (XMC_DSD_CH_RECTIFY_CONFIG_t*)NULL) { XMC_DSD_CH_Rectify_Init(channel, config->rectify); } if (config->timestamp != (XMC_DSD_CH_TIMESTAMP_CONFIG_t*)NULL) { XMC_DSD_CH_Timestamp_Init(channel, config->timestamp); } status = XMC_DSD_STATUS_OK; } else { status = XMC_DSD_STATUS_ERROR; } return (status); } /* Initialize main filter of DSD */ void XMC_DSD_CH_MainFilter_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_FILTER_CONFIG_t *const config) { uint32_t decimation_factor_temp; uint32_t filter_start_value_temp; XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel)); XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:NULL Pointer", (config != (XMC_DSD_CH_FILTER_CONFIG_t *)NULL) ); XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid Filter Start Value", (config->filter_start_value >= XMC_DSD_MIN_FILTER_START)); XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid Filter Start Value", (config->filter_start_value <= config->decimation_factor)); XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid Decimation Factor", ((config->decimation_factor >= XMC_DSD_MIN_DECIMATION_FACTOR) && (config->decimation_factor <= XMC_DSD_MAX_DECIMATION_FACTOR))); XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid divider",(((uint32_t)config->clock_divider <= XMC_DSD_CH_CLK_DIV_32))); /*Set Channel frequency*/ channel->MODCFG = ((uint32_t)config->clock_divider << DSD_CH_MODCFG_DIVM_Pos) | (uint32_t)DSD_CH_MODCFG_DWC_Msk; /* Input Data/Clk */ channel->DICFG = config->demodulator_conf | (uint32_t)DSD_CH_DICFG_DSWC_Msk | (uint32_t)DSD_CH_DICFG_SCWC_Msk; /*The decimation factor of the Main CIC filter is CFMDF + 1.*/ decimation_factor_temp = config->decimation_factor-1U; filter_start_value_temp = config->filter_start_value-1U; /* Filter setup*/ channel->FCFGC = (decimation_factor_temp | (filter_start_value_temp << (uint32_t)DSD_CH_FCFGC_CFMSV_Pos)| config->main_filter_conf| (uint32_t)DSD_CH_FCFGC_CFEN_Msk); /* Offset */ channel->OFFM = (uint16_t)config->offset; } /* Initialize timestamp mode of DSD */ void XMC_DSD_CH_Timestamp_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_TIMESTAMP_CONFIG_t *const config) { uint32_t temp; XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel)); XMC_ASSERT("XMC_DSD_MAIN_FILTER_Init:NULL Pointer", (config != (XMC_DSD_CH_TIMESTAMP_CONFIG_t *)NULL) ); temp = (channel->DICFG | (uint32_t)DSD_CH_DICFG_TRWC_Msk); temp &= ~((uint32_t)DSD_CH_DICFG_TSTRMODE_Msk|(uint32_t)DSD_CH_DICFG_TRSEL_Msk); temp |= config->timestamp_conf; channel->DICFG = temp; } /* Initialize auxiliary filter of DSD */ void XMC_DSD_CH_AuxFilter_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_AUX_FILTER_CONFIG_t *const config) { uint32_t decimation_factor_temp; XMC_ASSERT("XMC_DSD_AUX_FILTER_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel)); XMC_ASSERT("XMC_DSD_AUX_FILTER_Init:NULL Pointer", (config != (XMC_DSD_CH_AUX_FILTER_CONFIG_t *)NULL) ); XMC_ASSERT("XMC_DSD_AUX_FILTER_Init:Invalid Decimation Factor", ((config->decimation_factor >= XMC_DSD_MIN_DECIMATION_FACTOR) && (config->decimation_factor <= XMC_DSD_MAX_DECIMATION_FACTOR_AUX))); channel->BOUNDSEL = config->boundary_conf; /*The decimation factor of the Aux CIC filter is CFMDF + 1.*/ decimation_factor_temp = config->decimation_factor-1U; channel->FCFGA = (decimation_factor_temp | config->aux_filter_conf); } /* Integrator initialization of DSD */ void XMC_DSD_CH_Integrator_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_INTEGRATOR_CONFIG_t *const config) { uint32_t temp; XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel)); XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:NULL Pointer", (config != (XMC_DSD_CH_INTEGRATOR_CONFIG_t *)NULL) ); XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:Invalid integration_loop", (config->integration_loop > 0U )); XMC_ASSERT("XMC_DSD_INTEGRATOR_Init:Invalid counted_values", (config->counted_values > 0U )); channel->IWCTR = ((config->integration_loop - 1U) << DSD_CH_IWCTR_REPVAL_Pos) | (config->discarded_values << DSD_CH_IWCTR_NVALDIS_Pos) | (config->stop_condition << DSD_CH_IWCTR_IWS_Pos) | ((config->counted_values - 1U) << DSD_CH_IWCTR_NVALINT_Pos); /*To ensure proper operation, ensure that bit field ITRMODE is zero before selecting any other trigger mode.*/ temp = (channel->DICFG & ~((uint32_t)DSD_CH_DICFG_ITRMODE_Msk|(uint32_t)DSD_CH_DICFG_TRSEL_Msk)) | (uint32_t)DSD_CH_DICFG_TRWC_Msk; channel->DICFG = temp; temp |= config->integrator_trigger; channel->DICFG = temp; } /* Rectifier initialization of DSD */ void XMC_DSD_CH_Rectify_Init(XMC_DSD_CH_t *const channel, const XMC_DSD_CH_RECTIFY_CONFIG_t *const config) { XMC_ASSERT("XMC_DSD_RECTIFY_Init:Invalid module pointer", XMC_DSD_CHECK_CHANNEL_PTR(channel)); XMC_ASSERT("XMC_DSD_RECTIFY_Init:NULL Pointer", (config != (XMC_DSD_CH_RECTIFY_CONFIG_t *)NULL)); XMC_ASSERT("XMC_DSD_RECTIFY_Init:NULL Pointer", (((uint16_t)config->delay + (uint16_t)config->half_cycle) <= 0xFF)); channel->RECTCFG = config->rectify_config | (uint32_t)DSD_CH_RECTCFG_RFEN_Msk; channel->CGSYNC = (((uint32_t) config->delay << (uint32_t)DSD_CH_CGSYNC_SDPOS_Pos) | (((uint32_t)config->delay + (uint32_t)config->half_cycle) << (uint32_t)DSD_CH_CGSYNC_SDNEG_Pos)); } /* API to get the result of the last conversion */ void 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) { uint32_t timestamp; uint16_t result; timestamp = channel->TSTMP; result = (uint16_t)((uint32_t)timestamp & DSD_CH_TSTMP_RESULT_Msk); *dsd_result = (int16_t)(result); *dsd_filter_count = (uint8_t) ((timestamp & (uint32_t)DSD_CH_TSTMP_CFMDCNT_Msk)>>(uint32_t)DSD_CH_TSTMP_CFMDCNT_Pos); *dsd_integration_count = (uint8_t) ((timestamp & (uint32_t)DSD_CH_TSTMP_NVALCNT_Msk)>>(uint32_t)DSD_CH_TSTMP_NVALCNT_Pos); } /* API to get the result of the last conversion with the time */ void XMC_DSD_CH_GetResult_TS_Time(XMC_DSD_CH_t* const channel, int16_t* dsd_Result, uint32_t* time) { uint32_t timestamp; uint16_t filter_count; uint16_t integrator_count; uint16_t decimation; uint16_t result; timestamp = channel->TSTMP; decimation = (uint16_t)(channel->FCFGC & DSD_CH_FCFGC_CFMDF_Msk); filter_count = (uint16_t)((timestamp & DSD_CH_TSTMP_CFMDCNT_Msk)>>DSD_CH_TSTMP_CFMDCNT_Pos); /* Integration enabled? */ if ((channel->IWCTR & DSD_CH_IWCTR_INTEN_Msk)) { integrator_count = (uint16_t) ((timestamp & DSD_CH_TSTMP_NVALCNT_Msk)>>DSD_CH_TSTMP_NVALCNT_Pos); /*See Errata number: xxyy */ if (filter_count == decimation) { integrator_count++; } *time = (uint32_t)(((uint32_t) integrator_count * ((uint32_t) decimation + 1U)) + (uint32_t) ((uint32_t)decimation - filter_count)); } else { *time = (uint32_t) ((uint32_t)decimation - filter_count); } result = (uint16_t)((uint32_t)timestamp & DSD_CH_TSTMP_RESULT_Msk); *dsd_Result = (int16_t)(result); } #endif /*DSD*/