Advanced Distributed Systems module at HSLU
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

214 lines
6.8 KiB

/**
* \file
* \brief Timer driver
* \author Erich Styger, erich.styger@hslu.ch
* \license SPDX-License-Identifier: BSD-3-Clause
* This module implements the driver for all our timers.
*/
#include "platform.h"
#include "Timer.h"
#if PL_CONFIG_USE_EVENTS
#include "Event.h"
#endif
#include "Trigger.h"
#include "fsl_ftm.h"
#if PL_CONFIG_USE_QUADRATURE
#include "fsl_pit.h"
#include "QuadCounter.h"
#endif
#include "Tacho.h"
void TMR_OnInterrupt(void) { /* called from RTOS tick hook */
/* this one gets called from an interrupt!!!! */
#if PL_CONFIG_USE_EVENTS
static unsigned int cntr = 0;
#define BLINK_PERIOD_MS 2000
/* this one gets called from an interrupt!!!! */
cntr++;
if ((cntr%(BLINK_PERIOD_MS/TMR_TICK_MS))==0) { /* every two seconds */
EVNT_SetEvent(EVNT_LED_HEARTBEAT);
}
#endif
TRG_AddTick();
TACHO_Sample();
}
#if PL_CONFIG_USE_LINE_SENSOR
/*------------------------------------------------------------------------------------------- */
/* Reflectance Sensor free running timer */
/*------------------------------------------------------------------------------------------- */
#define REFLECTANCE_FTM_BASEADDR FTM1 /* FTM0 and FTM1 works, but FTM2 crashes? */
#define REFLECTANCE_FTM_CLOCK_SRC kFTM_SystemClock
#define REFLECTANCE_FTM_IRQ_NUM FTM1_IRQn
#define REFLECTANCE_FTM_IRQ_HANDLER FTM1_IRQHandler
#define REFLECTANCE_FTM_SOURCE_CLOCK (CLOCK_GetFreq(kCLOCK_BusClk))
#if 0
void REFLECTANCE_FTM_IRQ_HANDLER(void) { /* called every 1 ms */
/* Clear interrupt flag.*/
FTM_ClearStatusFlags(REFLECTANCE_FTM_BASEADDR, kFTM_TimeOverflowFlag);
__DSB();
}
#endif
void TMR_StartReflectanceTimer(void) {
FTM_StartTimer(REFLECTANCE_FTM_BASEADDR, REFLECTANCE_FTM_CLOCK_SRC);
}
void TMR_StopReflectanceTimer(void) {
FTM_StopTimer(REFLECTANCE_FTM_BASEADDR);
}
void TMR_ResetReflectanceTimerCounter(void) {
REFLECTANCE_FTM_BASEADDR->CNT = 0; /* there is no SDK function for this */
}
uint32_t TMR_GetReflectanceTimerCounter(void) {
return FTM_GetCurrentTimerCount(REFLECTANCE_FTM_BASEADDR);
}
uint32_t TMR_GetRefelectanceTimerFrequencyHz(void) {
return REFLECTANCE_FTM_SOURCE_CLOCK;
}
static void InitReflectanceTimer(void) {
ftm_config_t ftmInfo;
FTM_GetDefaultConfig(&ftmInfo);
/* Divide FTM clock by 4 */
ftmInfo.prescale = kFTM_Prescale_Divide_1;
/* Initialize FTM module */
FTM_Init(REFLECTANCE_FTM_BASEADDR, &ftmInfo);
FTM_SetTimerPeriod(REFLECTANCE_FTM_BASEADDR, 0xFFFF /*USEC_TO_COUNT(10000U), REFLECTANCE_FTM_SOURCE_CLOCK)*/);
// FTM_EnableInterrupts(REFLECTANCE_FTM_BASEADDR, kFTM_TimeOverflowInterruptEnable);
// EnableIRQ(REFLECTANCE_FTM_IRQ_NUM);
FTM_StartTimer(REFLECTANCE_FTM_BASEADDR, REFLECTANCE_FTM_CLOCK_SRC);
}
#endif /* PL_CONFIG_USE_LINE_SENSOR */
/*------------------------------------------------------------------------------------------- */
#if PL_CONFIG_USE_MOTORS
/*
* Left motor: PTC5, FTM0, Ch2
* Right motor: PTC4, FTM0, Ch3
*/
#define MOTOR_PWM_FTM_BASEADDR FTM0
#define MOTOR_FTM_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_BusClk)
#define MOTOR_PWM_LEFT_FTM_CHANNEL 2U
#define MOTOR_PWM_RIGHT_FTM_CHANNEL 3U
void TMR_SetLeftMotorPWMDutyPercent(uint8_t percent) {
FTM_UpdatePwmDutycycle(MOTOR_PWM_FTM_BASEADDR, (ftm_chnl_t)MOTOR_PWM_LEFT_FTM_CHANNEL, kFTM_EdgeAlignedPwm, 100-percent);
/* Software trigger to update registers */
FTM_SetSoftwareTrigger(MOTOR_PWM_FTM_BASEADDR, true);
}
void TMR_SetRightMotorPWMDutyPercent(uint8_t percent) {
FTM_UpdatePwmDutycycle(MOTOR_PWM_FTM_BASEADDR, (ftm_chnl_t)MOTOR_PWM_RIGHT_FTM_CHANNEL, kFTM_EdgeAlignedPwm, 100-percent);
/* Software trigger to update registers */
FTM_SetSoftwareTrigger(MOTOR_PWM_FTM_BASEADDR, true);
}
void TMR_SetLeftMotorPWMRatio(uint16_t val) {
TMR_SetLeftMotorPWMDutyPercent(val>>8);
}
void TMR_SetRightMotorPWMRatio(uint16_t val) {
TMR_SetRightMotorPWMDutyPercent(val>>8);
}
void TMR_MotorPWMStart(void) {
FTM_StartTimer(MOTOR_PWM_FTM_BASEADDR, kFTM_SystemClock);
}
void TMR_MotorPWMStop(void) {
FTM_StopTimer(MOTOR_PWM_FTM_BASEADDR);
}
static void InitMotorPWMTimer(void) {
ftm_chnl_pwm_signal_param_t ftmParam[2];
ftm_config_t ftmInfo;
/* Configure ftm params with frequency 24kHZ */
ftmParam[0].chnlNumber = (ftm_chnl_t)MOTOR_PWM_LEFT_FTM_CHANNEL;
ftmParam[0].level = kFTM_LowTrue;
ftmParam[0].dutyCyclePercent = 0U;
ftmParam[0].firstEdgeDelayPercent = 0U;
ftmParam[1].chnlNumber = (ftm_chnl_t)MOTOR_PWM_RIGHT_FTM_CHANNEL;
ftmParam[1].level = kFTM_LowTrue;
ftmParam[1].dutyCyclePercent = 0U;
ftmParam[1].firstEdgeDelayPercent = 0U;
/*
* ftmInfo.prescale = kFTM_Prescale_Divide_1;
* ftmInfo.bdmMode = kFTM_BdmMode_0;
* ftmInfo.pwmSyncMode = kFTM_SoftwareTrigger;
* ftmInfo.reloadPoints = 0;
* ftmInfo.faultMode = kFTM_Fault_Disable;
* ftmInfo.faultFilterValue = 0;
* ftmInfo.deadTimePrescale = kFTM_Deadtime_Prescale_1;
* ftmInfo.deadTimeValue = 0;
* ftmInfo.extTriggers = 0;
* ftmInfo.chnlInitState = 0;
* ftmInfo.chnlPolarity = 0;
* ftmInfo.useGlobalTimeBase = false;
*/
FTM_GetDefaultConfig(&ftmInfo);
/* Initialize FTM module */
FTM_Init(MOTOR_PWM_FTM_BASEADDR, &ftmInfo);
FTM_SetupPwm(MOTOR_PWM_FTM_BASEADDR, ftmParam, 2U, kFTM_EdgeAlignedPwm, 24000U, MOTOR_FTM_SOURCE_CLOCK);
TMR_SetLeftMotorPWMDutyPercent(0);
TMR_SetRightMotorPWMDutyPercent(0);
// FTM_StartTimer(MOTOR_PWM_FTM_BASEADDR, kFTM_SystemClock);
}
#endif /* PL_CONFIG_USE_MOTORS */
/*------------------------------------------------------------------------------------------- */
#if PL_CONFIG_USE_QUADRATURE
#define QUADRATURE_PIT_BASEADDR PIT
#define QUADRATURE_PIT_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_BusClk)
#define QUADRATURE_PIT_CHANNEL kPIT_Chnl_0
#define QUADRATURE_PIT_HANDLER PIT0_IRQHandler
#define QUADRATURE_PIT_IRQ_ID PIT0_IRQn
void QUADRATURE_PIT_HANDLER(void) {
PIT_ClearStatusFlags(QUADRATURE_PIT_BASEADDR, QUADRATURE_PIT_CHANNEL, kPIT_TimerFlag);
QuadCounter_Sample();
__DSB();
}
static void InitQuadratureTimer(void) {
pit_config_t config;
PIT_GetDefaultConfig(&config);
config.enableRunInDebug = false;
PIT_Init(QUADRATURE_PIT_BASEADDR, &config);
PIT_SetTimerPeriod(QUADRATURE_PIT_BASEADDR, QUADRATURE_PIT_CHANNEL, USEC_TO_COUNT(200U, QUADRATURE_PIT_SOURCE_CLOCK));
PIT_EnableInterrupts(QUADRATURE_PIT_BASEADDR, QUADRATURE_PIT_CHANNEL, kPIT_TimerInterruptEnable);
NVIC_SetPriority(QUADRATURE_PIT_IRQ_ID, 0);
EnableIRQ(QUADRATURE_PIT_IRQ_ID);
PIT_StartTimer(QUADRATURE_PIT_BASEADDR, QUADRATURE_PIT_CHANNEL);
}
#endif /* PL_CONFIG_USE_QUADRATURE */
/*------------------------------------------------------------------------------------------- */
void TMR_Init(void) {
#if PL_CONFIG_USE_LINE_SENSOR
InitReflectanceTimer();
#endif
#if PL_CONFIG_USE_MOTORS
InitMotorPWMTimer();
#endif
#if PL_CONFIG_USE_QUADRATURE
InitQuadratureTimer();
#endif
}
void TMR_Deinit(void) {
}