Esempio n. 1
0
/*!
 * @brief FTM interrupt handler.
 */
void BOARD_FTM_IRQ_HANDLER(void)
{
    // The overflow interrupt is the start of each cycle and is handled first.
    if(FTM_HAL_HasTimerOverflowed(BOARD_FTM_BASE))
    {
        // Clear the interrupt.
        FTM_HAL_ClearTimerOverflow(BOARD_FTM_BASE);

        // Update LED state/duty cycle for the X-axis.
        FTM_HAL_SetChnCountVal(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL, g_xValue);

        // Only turn on the LED if the new duty cycle is not 0.
        if(g_xValue)
        {
            LED3_ON;
            FTM_HAL_EnableChnInt(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL);
        }
        else
        {
            LED3_OFF;
            FTM_HAL_DisableChnInt(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL);
        }

        // Update LED state/duty cycle for the Y-axis.
        FTM_HAL_SetChnCountVal(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL, g_yValue);

        // Only turn on the LED if the new duty cycle is not 0.
        if(g_yValue)
        {
            LED2_ON;
            FTM_HAL_EnableChnInt(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL);
        }
        else
        {
            LED2_OFF;
            FTM_HAL_DisableChnInt(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL);
        }

        // Perform a software sync to update the counter registers.
        FTM_HAL_SetSoftwareTriggerCmd(BOARD_FTM_BASE, true);
    }

    // X-axis match: Clear interrupt and turn LED off.
    if(FTM_HAL_HasChnEventOccurred(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL))
    {
        FTM_HAL_ClearChnEventFlag(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL);
        LED3_OFF;
    }

    // Y-axis match: Clear interrupt and turn LED off.
    if(FTM_HAL_HasChnEventOccurred(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL))
    {
        FTM_HAL_ClearChnEventFlag(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL);
        LED2_OFF;
    }
}
Esempio n. 2
0
/*FUNCTION**********************************************************************
 *
 * Function Name : FTM_HAL_DisablePwmMode
 * Description   : Disables the PWM output mode.
 *
 *END**************************************************************************/
void FTM_HAL_DisablePwmMode(FTM_Type *ftmBase, ftm_pwm_param_t *config, uint8_t channel)
{
    uint8_t chnlPairnum = FTM_HAL_GetChnPairIndex(channel);

    FTM_HAL_SetChnCountVal(ftmBase, channel, 0);
    FTM_HAL_SetChnEdgeLevel(ftmBase, channel, 0);
    FTM_HAL_SetChnMSnBAMode(ftmBase, channel, 0);
    FTM_HAL_SetCpwms(ftmBase, 0);
    FTM_HAL_SetDualChnCombineCmd(ftmBase, chnlPairnum, false);
}
void FTM_DRV_PwmChangeDutyCycle(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];


    uMod = FTM_HAL_GetMod(ftmBaseAddr);

    uCnv = uMod * param->uDutyCyclePercent / 100;
    /* For 100% duty cycle */
    if(uCnv >= uMod)
    {
      uCnv = uMod + 1;
    }
    FTM_HAL_SetChnCountVal(ftmBaseAddr, channel, uCnv);
}
/*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);
}
Esempio n. 5
0
/*************************************************************************
 * Function Name: FTM0_SetDutyCycle
 * Parameters: duty cycle value
 * Return: none
 * Description: Set PWM dutycycle
 *************************************************************************/
void FTM0_SetDutyCycle(int16 inpDuty)
{
  int FirstEdge, SecondEdge, duty;

  duty = MLIB_Mul_F16(inpDuty, PWM_MODULO/4);

  FirstEdge = -PWM_MODULO/4 - duty;
  if (FirstEdge < (-PWM_MODULO/2)) FirstEdge = -PWM_MODULO/2;

  SecondEdge = PWM_MODULO/4 + duty;
  if (SecondEdge > (PWM_MODULO/2)) SecondEdge = PWM_MODULO/2;

  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 0, FirstEdge);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 1, SecondEdge);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 2, FirstEdge);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 3, SecondEdge);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 4, FirstEdge);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 5, SecondEdge);
  FTM_HAL_SetPwmLoadCmd(FTM0_BASE_PTR, true);
}
/*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;
}
/*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
}
Esempio n. 8
0
/*************************************************************************
 * Function Name: FTM0_init
 * Parameters: none
 * Return: none
 * Description: FlexTimer 0 initialization
 *************************************************************************/
void FTM0_init(void)
{
  FTM_HAL_SetWriteProtectionCmd(FTM0_BASE_PTR, false);//false: Write-protection is disabled
  FTM_HAL_Enable(FTM0_BASE_PTR, true);//true: all registers including FTM-specific registers are available

  FTM_HAL_SetCounterInitVal(FTM0_BASE_PTR, (uint16_t)(-PWM_MODULO/2));
  FTM_HAL_SetMod(FTM0_BASE_PTR, (uint16_t)PWM_MODULO/2-1); // 20 kHz

  FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 0, 2);
  FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 1, 2);
  FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 2, 2);
  FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 3, 2);
  FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 4, 2);
  FTM_HAL_SetChnEdgeLevel(FTM0_BASE_PTR, 5, 2);

  // output mask updated on PWM synchronization (not on rising edge of clock)
  FTM_HAL_SetMaxLoadingCmd(FTM0_BASE_PTR, true);//True to enable minimum loading point
  FTM_HAL_SetOutmaskPwmSyncModeCmd(FTM0_BASE_PTR, 1);//true if OUTMASK register is updated only by PWM sync\n

  FTM_HAL_SetDualChnPwmSyncCmd(FTM0_BASE_PTR, 0, true);//True to enable PWM synchronization
  FTM_HAL_SetDualChnPwmSyncCmd(FTM0_BASE_PTR, 1, true);
  FTM_HAL_SetDualChnPwmSyncCmd(FTM0_BASE_PTR, 2, true);
  FTM_HAL_SetDualChnDeadtimeCmd(FTM0_BASE_PTR, 0, true);//True to enable deadtime insertion, false to disable
  FTM_HAL_SetDualChnDeadtimeCmd(FTM0_BASE_PTR, 1, true);
  FTM_HAL_SetDualChnDeadtimeCmd(FTM0_BASE_PTR, 2, true);
  FTM_HAL_SetDualChnCompCmd(FTM0_BASE_PTR, 0, true);//True to enable complementary mode, false to disable
  FTM_HAL_SetDualChnCompCmd(FTM0_BASE_PTR, 1, true);
  FTM_HAL_SetDualChnCompCmd(FTM0_BASE_PTR, 2, true);
  FTM_HAL_SetDualChnCombineCmd(FTM0_BASE_PTR, 0, true);// True to enable channel pair to combine, false to disable
  FTM_HAL_SetDualChnCombineCmd(FTM0_BASE_PTR, 1, true);
  FTM_HAL_SetDualChnCombineCmd(FTM0_BASE_PTR, 2, true);

  // High transistors have negative polarity (MC33927/37)
  FTM_HAL_SetDeadtimePrescale(FTM0_BASE_PTR, kFtmDivided1);
  FTM_HAL_SetDeadtimeCount(FTM0_BASE_PTR, FTM_DEADTIME_DTVAL(63)); // DTVAL - deadtime value (0-63): deadtime period = DTPS x DTVAL
  FTM_HAL_SetInitTriggerCmd(FTM0_BASE_PTR, true);//True to enable, false to disable
  FTM_HAL_SetChnOutputPolarityCmd(FTM0_BASE_PTR, 0,  1);
  FTM_HAL_SetChnOutputPolarityCmd(FTM0_BASE_PTR, 2,  1);
  FTM_HAL_SetChnOutputPolarityCmd(FTM0_BASE_PTR, 4,  1);


  /* Following line configures:
     - enhanced PWM synchronization, FTM counter reset on SW sync
     - output SW control / polarity registers updated on PWM synchronization (not on rising edge of clock)
     - output SW control/inverting(swap)/mask registers updated from buffers on SW synchronization */  
  FTM_HAL_SetPwmSyncModeCmd(FTM0_BASE_PTR, true);// true means use Enhanced PWM synchronization\n
  FTM_HAL_SetCounterSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software trigger activates register sync\n
  FTM_HAL_SetSwoctrlPwmSyncModeCmd(FTM0_BASE_PTR, true);//true means SWOCTRL register is updated by PWM synch\n
  FTM_HAL_SetInvctrlPwmSyncModeCmd(FTM0_BASE_PTR, true);//true means INVCTRL register is updated by PWM synch\n
  FTM_HAL_SetSwoctrlSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software trigger activates register sync\n
  FTM_HAL_SetInvctrlSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software trigger activates register sync\n
  FTM_HAL_SetOutmaskSoftwareSyncModeCmd(FTM0_BASE_PTR, true);//true means software

  FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 0, 1);//Sets the FTM peripheral timer channel output mask.
  FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 1, 1);
  FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 2, 1);
  FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 3, 1);
  FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 4, 1);
  FTM_HAL_SetChnOutputMask(FTM0_BASE_PTR, 5, 1);

  FTM_HAL_SetCounter(FTM0_BASE_PTR, 1U);         // update of FTM settings
  // no ISR, counting up, system clock, divide by 1
  FTM_HAL_SetClockSource(FTM0_BASE_PTR, kClock_source_FTM_SystemClk);
  
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 0, (uint16_t)(-PWM_MODULO/4));
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 1,(uint16_t) PWM_MODULO/4);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 2, (uint16_t)(-PWM_MODULO/4));
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 3,(uint16_t) PWM_MODULO/4);
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 4, (uint16_t)(-PWM_MODULO/4));
  FTM_HAL_SetChnCountVal(FTM0_BASE_PTR, 5,(uint16_t) PWM_MODULO/4);

  FTM_HAL_SetSoftwareTriggerCmd(FTM0_BASE_PTR, 1);
  
  FTM_HAL_SetPwmLoadCmd(FTM0_BASE_PTR, 1);

  // FTM0 PWM output pins
  PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 1, kPortMuxAlt4);
  PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 3, kPortMuxAlt4);
  PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 4, kPortMuxAlt4);
  PORT_HAL_SetMuxMode(PORTD_BASE_PTR, 4, kPortMuxAlt4);
  PORT_HAL_SetMuxMode(PORTD_BASE_PTR, 5, kPortMuxAlt4);
#if defined(KV10Z7_SERIES)
  PORT_HAL_SetMuxMode(PORTE_BASE_PTR, 25, kPortMuxAlt3);
#elif (defined(KV10Z1287_SERIES) || defined(KV11Z7_SERIES))
  PORT_HAL_SetMuxMode(PORTC_BASE_PTR, 2, kPortMuxAlt4);
#endif

  GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 1, kGpioDigitalOutput);
  GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 3, kGpioDigitalOutput);
  GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 4, kGpioDigitalOutput);

  GPIO_HAL_SetPinDir(GPIOD_BASE_PTR, 4, kGpioDigitalOutput);
  GPIO_HAL_SetPinDir(GPIOD_BASE_PTR, 5, kGpioDigitalOutput);
#if defined(KV10Z7_SERIES)
  GPIO_HAL_SetPinDir(GPIOE_BASE_PTR, 25, kGpioDigitalOutput);
#elif (defined(KV10Z1287_SERIES) || defined(KV11Z7_SERIES))
  GPIO_HAL_SetPinDir(GPIOC_BASE_PTR, 2, kGpioDigitalOutput);
#endif
}
/*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);
}
Esempio n. 10
0
/*!
 * @brief Main demo function.
 */
int main (void)
{
    ftm_pwm_param_t xAxisParams, yAxisParams;
    accel_dev_t accDev;
    accel_dev_interface_t accDevice;
    accel_sensor_data_t accelData;
    accel_i2c_interface_t i2cInterface;
    int16_t xData, yData;
    int16_t xAngle, yAngle;
    uint32_t ftmModulo;

    // Register callback func for I2C
    i2cInterface.i2c_init       =  I2C_DRV_MasterInit;
    i2cInterface.i2c_read       =  I2C_DRV_MasterReceiveDataBlocking;
    i2cInterface.i2c_write      =  I2C_DRV_MasterSendDataBlocking;

    accDev.i2c = &i2cInterface;
    accDev.accel = &accDevice;

    accDev.slave.baudRate_kbps  = BOARD_ACCEL_BAUDRATE;
    accDev.slave.address        = BOARD_ACCEL_ADDR;
    accDev.bus                  = BOARD_ACCEL_I2C_INSTANCE;

    // Initialize standard SDK demo application pins.
    hardware_init();

    // Accel device driver utilizes the OSA, so initialize it.
    OSA_Init();

    // Initialize the LEDs used by this application.
    LED2_EN;
    LED3_EN;

    // Print the initial banner.
    PRINTF("Bubble Level Demo!\r\n\r\n");

    // Initialize the Accel.
    accel_init(&accDev);

    // Turn on the clock to the FTM.
    CLOCK_SYS_EnableFtmClock(BOARD_FTM_INSTANCE);

    // Initialize the FTM module.
    FTM_HAL_Init(BOARD_FTM_BASE);

    // Configure the sync mode to software.
    FTM_HAL_SetSyncMode(BOARD_FTM_BASE, kFtmUseSoftwareTrig);

    // Enable the overflow interrupt.
    FTM_HAL_EnableTimerOverflowInt(BOARD_FTM_BASE);

    // Set the FTM clock divider to /16.
    FTM_HAL_SetClockPs(BOARD_FTM_BASE, kFtmDividedBy16);

    // Configure the FTM channel used for the X-axis.  Initial duty cycle is 0%.
    xAxisParams.mode = kFtmEdgeAlignedPWM;
    xAxisParams.edgeMode = kFtmHighTrue;

    FTM_HAL_EnablePwmMode(BOARD_FTM_BASE, &xAxisParams, BOARD_FTM_X_CHANNEL);
    FTM_HAL_SetChnCountVal(BOARD_FTM_BASE, BOARD_FTM_X_CHANNEL, 0);

    // Configure the FTM channel used for the Y-axis.  Initial duty cycle is 0%.
    yAxisParams.mode = kFtmEdgeAlignedPWM;
    yAxisParams.edgeMode = kFtmHighTrue;

    FTM_HAL_EnablePwmMode(BOARD_FTM_BASE, &yAxisParams, BOARD_FTM_Y_CHANNEL);
    FTM_HAL_SetChnCountVal(BOARD_FTM_BASE, BOARD_FTM_Y_CHANNEL, 0);

    // Get the FTM reference clock and calculate the modulo value.
    ftmModulo = (CLOCK_SYS_GetFtmSystemClockFreq(BOARD_FTM_INSTANCE) /
                  (1 << FTM_HAL_GetClockPs(BOARD_FTM_BASE))) /
                  (BOARD_FTM_PERIOD_HZ - 1);

    // Initialize the FTM counter.
    FTM_HAL_SetCounterInitVal(BOARD_FTM_BASE, 0);
    FTM_HAL_SetMod(BOARD_FTM_BASE, ftmModulo);

    // Set the clock source to start the FTM.
    FTM_HAL_SetClockSource(BOARD_FTM_BASE, kClock_source_FTM_SystemClk);

    // Enable the FTM interrupt at the NVIC level.
    INT_SYS_EnableIRQ(BOARD_FTM_IRQ_VECTOR);

    // Main loop.  Get sensor data and update globals for the FTM timer update.
    while(1)
    {
        // Wait 5 ms in between samples (accelerometer updates at 200Hz).
        OSA_TimeDelay(5);

        // Get new accelerometer data.
          accDev.accel->accel_read_sensor_data(&accDev,&accelData);

        // Turn off interrupts (FTM) while updating new duty cycle values.
        INT_SYS_DisableIRQGlobal();

        // Get the X and Y data from the sensor data structure.
        xData = (int16_t)((accelData.data.accelXMSB << 8) | accelData.data.accelXLSB);
        yData = (int16_t)((accelData.data.accelYMSB << 8) | accelData.data.accelYLSB);

        // Convert raw data to angle (normalize to 0-90 degrees).  No negative
        // angles.
        xAngle = abs((int16_t)(xData * 0.011));
        yAngle = abs((int16_t)(yData * 0.011));

        // Set values for next FTM ISR udpate.  Use 5 degrees as the threshold
        // for whether to turn the LED on or not.
        g_xValue = (xAngle > 5) ? (uint16_t)((xAngle / 90.0) * ftmModulo) : 0;
        g_yValue = (yAngle > 5) ? (uint16_t)((yAngle / 90.0) * ftmModulo) : 0;

        // Re-enable interrupts.
        INT_SYS_EnableIRQGlobal();

        // Print out the raw accelerometer data.
        PRINTF("x= %d y = %d\r\n", xData, yData);
    }
}