/*FUNCTION********************************************************************** * * Function Name : FTM_DRV_SetupChnOutputCompare * Description : Configures the FTM to generate timed pulses * When the FTM counter matches the value of compareVal argument (this is * written into CnV reg), the channel output is changed based on what is specified * in the compareMode argument. * *END**************************************************************************/ void FTM_DRV_SetupChnOutputCompare(uint32_t instance, ftm_output_compare_edge_mode_t compareMode, uint8_t channel, uint32_t compareVal) { assert(instance < FTM_INSTANCE_COUNT); assert(channel < g_ftmChannelCount[instance]); FTM_Type *ftmBase = g_ftmBase[instance]; uint32_t chnlPairnum = FTM_HAL_GetChnPairIndex(channel); FTM_HAL_SetClockSource(ftmBase, kClock_source_FTM_None); FTM_HAL_SetCounterInitVal(ftmBase, 0); FTM_HAL_SetMod(ftmBase, 0xFFFF); FTM_HAL_SetCpwms(ftmBase, 0); FTM_HAL_SetDualChnCombineCmd(ftmBase, chnlPairnum, false); FTM_HAL_SetDualEdgeCaptureCmd(ftmBase, chnlPairnum, false); FTM_HAL_SetChnEdgeLevel(ftmBase, channel, compareMode); FTM_HAL_SetChnMSnBAMode(ftmBase, channel, 1); FTM_HAL_SetChnCountVal(ftmBase, channel, compareVal); /* Set clock source to start the counter */ FTM_HAL_SetClockSource(ftmBase, s_ftmClockSource); }
/*FUNCTION********************************************************************** * * Function Name : SMARTCARD_DRV_InterfaceClockInit * Description : This function initializes clock module used for card clock generation * *END**************************************************************************/ static uint16_t SMARTCARD_DRV_InterfaceClockInit(uint8_t clockModuleInstance, uint8_t clockModuleChannel, uint32_t cardClk) { #if defined(EMVSIM_INSTANCE_COUNT) assert(clockModuleInstance < EMVSIM_INSTANCE_COUNT); EMVSIM_Type * base = g_emvsimBase[clockModuleInstance]; uint32_t emvsimClkMhz = 0; uint8_t emvsimPRSCValue; /* Retrieve EMV SIM clock */ emvsimClkMhz = CLOCK_SYS_GetEmvsimFreq(clockModuleInstance)/1000000; /* Calculate MOD value */ emvsimPRSCValue = (emvsimClkMhz*1000)/(cardClk/1000); /* Set clock prescaler */ EMVSIM_HAL_SetClockPrescaler(base, emvsimPRSCValue); /* Enable smart card clock */ EMVSIM_HAL_EnableCardClock(base); return cardClk; #elif defined(FTM_INSTANCE_COUNT) assert(clockModuleInstance < FTM_INSTANCE_COUNT); ftm_user_config_t ftmInfo; uint32_t periph_clk_mhz = 0; uint16_t ftmModValue; FTM_Type * ftmBase = g_ftmBase[clockModuleInstance]; uint32_t chnlPairnum = FTM_HAL_GetChnPairIndex(clockModuleChannel); /* Retrieve FTM system clock */ periph_clk_mhz = CLOCK_SYS_GetBusClockFreq()/1000000; /* Calculate MOD value */ ftmModValue = ((periph_clk_mhz*1000/2)/(cardClk/1000)) -1; /* Clear FTM driver user configuration */ memset(&ftmInfo, 0, sizeof(ftmInfo)); ftmInfo.BDMMode = kFtmBdmMode_11; ftmInfo.syncMethod = kFtmUseSoftwareTrig; /* Initialize FTM driver */ FTM_DRV_Init(clockModuleInstance, &ftmInfo); /* Reset FTM prescaler to 'Divide by 1', i.e., to be same clock as peripheral clock */ FTM_HAL_SetClockPs(ftmBase, kFtmDividedBy1); /* Disable FTM counter firstly */ FTM_HAL_SetClockSource(ftmBase, kClock_source_FTM_None); /* Set initial counter value */ FTM_HAL_SetCounterInitVal(ftmBase, 0); /* Set MOD value */ FTM_HAL_SetMod(ftmBase, ftmModValue); /* Other initializations to defaults */ FTM_HAL_SetCpwms(ftmBase, 0); FTM_HAL_SetDualChnCombineCmd(ftmBase, chnlPairnum, false); FTM_HAL_SetDualEdgeCaptureCmd(ftmBase, chnlPairnum, false); /* Configure mode to output compare, tougle output on match */ FTM_HAL_SetChnEdgeLevel(ftmBase, clockModuleChannel, kFtmToggleOnMatch); FTM_HAL_SetChnMSnBAMode(ftmBase, clockModuleChannel, 1); /* Configure a match value to toggle output at */ FTM_HAL_SetChnCountVal(ftmBase, clockModuleChannel, 1); /* Set clock source to start the counter */ FTM_HAL_SetClockSource(ftmBase, kClock_source_FTM_SystemClk); /* Re-calculate the actually configured smartcard clock and return to caller */ return (uint32_t)(((periph_clk_mhz*1000/2)/(FTM_HAL_GetMod(ftmBase)+1))*1000); #elif defined(TPM_INSTANCE_COUNT) assert(clockModuleInstance < TPM_INSTANCE_COUNT); assert(clockModuleChannel < FSL_FEATURE_TPM_CHANNEL_COUNTn(clockModuleInstance)); /* Initialize TPM driver parameter */ tpm_pwm_param_t param = { kTpmCenterAlignedPWM, /* mode */ kTpmHighTrue, /* edgeMode */ cardClk, /* uFrequencyHZ */ 50 /* uDutyCyclePercent */ }; /* Initialize TPM driver */ tpm_general_config_t driverInfo; memset(&driverInfo, 0, sizeof(driverInfo)); driverInfo.isDBGMode = true; TPM_DRV_Init(clockModuleInstance, &driverInfo); /* Set TPM clock source, the user will have to call the Clocking API's to set the * TPM module clock before calling this function */ TPM_DRV_SetClock(clockModuleInstance, kTpmClockSourceModuleClk, kTpmDividedBy1); /* Start TPM in PWM mode to generate smart card clock */ TPM_DRV_PwmStart(clockModuleInstance, ¶m, clockModuleChannel); return cardClk; #else return 0; #endif }
/*FUNCTION********************************************************************** * * Function Name : FTM_DRV_PwmStart * Description : Configures duty cycle and frequency and starts outputting * PWM on specified channel . * *END**************************************************************************/ ftm_status_t FTM_DRV_PwmStart(uint32_t instance, ftm_pwm_param_t *param, uint8_t channel) { uint32_t uFTMhz; uint16_t uMod, uCnv, uCnvFirstEdge = 0; assert(instance < FTM_INSTANCE_COUNT); assert(param->uDutyCyclePercent <= 100); assert(channel < g_ftmChannelCount[instance]); FTM_Type *ftmBase = g_ftmBase[instance]; /* Clear the overflow flag */ FTM_HAL_ClearTimerOverflow(ftmBase); FTM_HAL_EnablePwmMode(ftmBase, param, channel); if (s_ftmClockSource == kClock_source_FTM_None) { return kStatusFtmError; } uFTMhz = FTM_DRV_GetClock(instance); /* Based on Ref manual, in PWM mode CNTIN is to be set 0*/ FTM_HAL_SetCounterInitVal(ftmBase, 0); switch(param->mode) { case kFtmEdgeAlignedPWM: uMod = uFTMhz / (param->uFrequencyHZ) - 1; uCnv = uMod * param->uDutyCyclePercent / 100; /* For 100% duty cycle */ if(uCnv >= uMod) { uCnv = uMod + 1; } FTM_HAL_SetMod(ftmBase, uMod); FTM_HAL_SetChnCountVal(ftmBase, channel, uCnv); break; case kFtmCenterAlignedPWM: uMod = uFTMhz / (param->uFrequencyHZ * 2); uCnv = uMod * param->uDutyCyclePercent / 100; /* For 100% duty cycle */ if(uCnv >= uMod) { uCnv = uMod + 1; } FTM_HAL_SetMod(ftmBase, uMod); FTM_HAL_SetChnCountVal(ftmBase, channel, uCnv); break; case kFtmCombinedPWM: uMod = uFTMhz / (param->uFrequencyHZ) - 1; uCnv = uMod * param->uDutyCyclePercent / 100; uCnvFirstEdge = uMod * param->uFirstEdgeDelayPercent / 100; /* For 100% duty cycle */ if(uCnv >= uMod) { uCnv = uMod + 1; } FTM_HAL_SetMod(ftmBase, uMod); FTM_HAL_SetChnCountVal(ftmBase, FTM_HAL_GetChnPairIndex(channel) * 2, uCnvFirstEdge); FTM_HAL_SetChnCountVal(ftmBase, FTM_HAL_GetChnPairIndex(channel) * 2 + 1, uCnv + uCnvFirstEdge); break; default: assert(0); break; } /* Set clock source to start counter */ FTM_HAL_SetClockSource(ftmBase, s_ftmClockSource); return kStatusFtmSuccess; }
/*See fsl_ftm_driver.h for documentation of this function.*/ void FTM_DRV_PwmStart(uint8_t instance, ftm_pwm_param_t *param, uint8_t channel) { uint32_t uFTMhz; uint16_t uMod, uCnv, uCnvFirstEdge = 0; assert(instance < HW_FTM_INSTANCE_COUNT); assert(param->uDutyCyclePercent <= 100); assert(channel < FSL_FEATURE_FTM_CHANNEL_COUNTn(instance)); uint32_t ftmBaseAddr = g_ftmBaseAddr[instance]; /* Clear the overflow flag */ FTM_HAL_ClearTimerOverflow(g_ftmBaseAddr[instance]); FTM_HAL_EnablePwmMode(ftmBaseAddr, param, channel); #if FSL_FEATURE_FTM_BUS_CLOCK CLOCK_SYS_GetFreq(kBusClock, &uFTMhz); #else CLOCK_SYS_GetFreq(kSystemClock, &uFTMhz); #endif /* Based on Ref manual, in PWM mode CNTIN is to be set 0*/ FTM_HAL_SetCounterInitVal(ftmBaseAddr, 0); uFTMhz = uFTMhz / (1 << FTM_HAL_GetClockPs(ftmBaseAddr)); switch(param->mode) { case kFtmEdgeAlignedPWM: uMod = uFTMhz / (param->uFrequencyHZ) - 1; uCnv = uMod * param->uDutyCyclePercent / 100; /* For 100% duty cycle */ if(uCnv >= uMod) { uCnv = uMod + 1; } FTM_HAL_SetMod(ftmBaseAddr, uMod); FTM_HAL_SetChnCountVal(ftmBaseAddr, channel, uCnv); break; case kFtmCenterAlignedPWM: uMod = uFTMhz / (param->uFrequencyHZ * 2); uCnv = uMod * param->uDutyCyclePercent / 100; /* For 100% duty cycle */ if(uCnv >= uMod) { uCnv = uMod + 1; } FTM_HAL_SetMod(ftmBaseAddr, uMod); FTM_HAL_SetChnCountVal(ftmBaseAddr, channel, uCnv); break; case kFtmCombinedPWM: uMod = uFTMhz / (param->uFrequencyHZ) - 1; uCnv = uMod * param->uDutyCyclePercent / 100; uCnvFirstEdge = uMod * param->uFirstEdgeDelayPercent / 100; /* For 100% duty cycle */ if(uCnv >= uMod) { uCnv = uMod + 1; } FTM_HAL_SetMod(ftmBaseAddr, uMod); FTM_HAL_SetChnCountVal(ftmBaseAddr, FTM_HAL_GetChnPairIndex(channel) * 2, uCnvFirstEdge); FTM_HAL_SetChnCountVal(ftmBaseAddr, FTM_HAL_GetChnPairIndex(channel) * 2 + 1, uCnv + uCnvFirstEdge); break; default: assert(0); break; } /* Set clock source to start counter */ FTM_HAL_SetClockSource(ftmBaseAddr, kClock_source_FTM_SystemClk); }