/*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, &param, 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;
}
Пример #4
0
/*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);
}