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.
121 lines
3.8 KiB
121 lines
3.8 KiB
#pragma once
|
|
|
|
#include "Arduino.h"
|
|
#include "FTM_ChannelInfo.h"
|
|
#include "FTM_Info.h"
|
|
#include "ITimerChannel.h"
|
|
|
|
namespace TeensyTimerTool
|
|
{
|
|
class FTM_Channel : public ITimerChannel
|
|
{
|
|
public:
|
|
inline FTM_Channel(FTM_r_t *regs, FTM_ChannelInfo *ci);
|
|
inline virtual ~FTM_Channel();
|
|
|
|
inline float getMaxPeriod() const override;
|
|
|
|
inline errorCode begin(callback_t cb, float period, bool periodic) { return doBegin(cb, period, periodic); } ///hacky improve in later version
|
|
inline errorCode begin(callback_t cb, uint32_t period, bool periodic) { return doBegin(cb, period, periodic); };
|
|
|
|
inline errorCode trigger(float tcnt) override FASTRUN;
|
|
inline errorCode triggerDirect(uint32_t reload) override FASTRUN;
|
|
inline errorCode getTriggerReload(float delay, uint32_t *reload) override;
|
|
|
|
inline errorCode start() override;
|
|
inline errorCode stop() override;
|
|
|
|
inline uint16_t ticksFromMicros(float micros);
|
|
|
|
// inline void setPeriod(uint32_t) {}
|
|
|
|
protected:
|
|
FTM_ChannelInfo *ci;
|
|
FTM_r_t *regs;
|
|
callback_t *pCallback = nullptr;
|
|
|
|
template <typename period_t>
|
|
inline errorCode doBegin(callback_t cb, period_t period, bool periodic);
|
|
};
|
|
|
|
// IMPLEMENTATION ==============================================
|
|
|
|
FTM_Channel::FTM_Channel(FTM_r_t *regs, FTM_ChannelInfo *channelInfo)
|
|
: ITimerChannel(nullptr)
|
|
{
|
|
this->regs = regs;
|
|
this->ci = channelInfo;
|
|
}
|
|
|
|
template <typename period_t>
|
|
errorCode FTM_Channel::doBegin(callback_t callback, period_t period, bool periodic)
|
|
{
|
|
ci->isPeriodic = periodic;
|
|
ci->reload = ticksFromMicros(period);
|
|
ci->callback = callback;
|
|
|
|
return errorCode::OK;
|
|
}
|
|
|
|
errorCode FTM_Channel::start()
|
|
{
|
|
ci->chRegs->CV = regs->CNT + ci->reload; // compare value (current counter + pReload)
|
|
ci->chRegs->SC &= ~FTM_CSC_CHF; // reset timer flag
|
|
ci->chRegs->SC = FTM_CSC_MSA | FTM_CSC_CHIE; // enable interrupts
|
|
return errorCode::OK;
|
|
}
|
|
|
|
errorCode FTM_Channel::stop()
|
|
{
|
|
ci->chRegs->SC &= ~FTM_CSC_CHIE; // enable interrupts
|
|
ci->chRegs->SC &= ~FTM_CSC_CHF; // reset timer flag
|
|
|
|
return errorCode::OK;
|
|
}
|
|
|
|
errorCode FTM_Channel::getTriggerReload(float delay, uint32_t *reload)
|
|
{
|
|
*reload = ticksFromMicros(delay);
|
|
return errorCode::OK;
|
|
}
|
|
|
|
errorCode FTM_Channel::trigger(float delay)
|
|
{
|
|
return triggerDirect(ticksFromMicros(delay));
|
|
}
|
|
|
|
errorCode FTM_Channel::triggerDirect(uint32_t reload)
|
|
{
|
|
uint32_t cv = regs->CNT + reload + 1; // calc early to minimize error
|
|
ci->chRegs->SC &= ~FTM_CSC_CHF; // Reset timer flag
|
|
//
|
|
regs->SC &= ~FTM_SC_CLKS_MASK; // need to switch off clock to immediately set new CV
|
|
ci->chRegs->CV = cv; // compare value (current counter + pReload)
|
|
regs->SC |= FTM_SC_CLKS(0b01); // restart clock
|
|
//
|
|
ci->chRegs->SC = FTM_CSC_MSA | FTM_CSC_CHIE; // enable interrupts
|
|
|
|
return errorCode::OK;
|
|
}
|
|
|
|
float FTM_Channel::getMaxPeriod() const
|
|
{
|
|
return (0xFFFF * 1E-6f) / ci->ticksPerMicrosecond; // max period in seconds
|
|
}
|
|
|
|
uint16_t FTM_Channel::ticksFromMicros(float micros)
|
|
{
|
|
uint32_t rl = ci->ticksPerMicrosecond * micros;
|
|
if (rl > 0xFFFF)
|
|
{
|
|
postError(errorCode::periodOverflow); // warning only, continues with clipped value
|
|
rl = 0xFFFF;
|
|
}
|
|
return rl;
|
|
}
|
|
|
|
FTM_Channel::~FTM_Channel()
|
|
{
|
|
}
|
|
|
|
} // namespace TeensyTimerTool
|
|
|