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.
178 lines
4.6 KiB
178 lines
4.6 KiB
#pragma once
|
|
#include "../../ITimerChannel.h"
|
|
//#include "Arduino.h"
|
|
#include <cmath>
|
|
#include "ErrorHandling/error_codes.h"
|
|
#include "config.h"
|
|
#include "imxrt.h"
|
|
|
|
namespace TeensyTimerTool
|
|
{
|
|
class TMRChannel : public ITimerChannel
|
|
{
|
|
public:
|
|
inline TMRChannel(IMXRT_TMR_CH_t* regs, callback_t* cbStorage);
|
|
inline virtual ~TMRChannel();
|
|
|
|
inline errorCode begin(callback_t cb, float tcnt, bool periodic) override;
|
|
inline errorCode start() override;
|
|
inline errorCode stop() override;
|
|
|
|
inline errorCode trigger(float tcnt) override;
|
|
inline float getMaxPeriod() const override;
|
|
|
|
inline errorCode setPeriod(float us) override;
|
|
inline void setPrescaler(uint32_t psc); // psc 0..7 -> prescaler: 1..128
|
|
|
|
protected:
|
|
IMXRT_TMR_CH_t* regs;
|
|
callback_t** pCallback = nullptr;
|
|
float pscValue;
|
|
uint32_t pscBits;
|
|
|
|
inline float_t microsecondToCounter(const float_t us) const;
|
|
inline float_t counterToMicrosecond(const float_t cnt) const;
|
|
};
|
|
|
|
// IMPLEMENTATION ==============================================
|
|
|
|
TMRChannel::TMRChannel(IMXRT_TMR_CH_t* regs, callback_t* cbStorage)
|
|
: ITimerChannel(cbStorage)
|
|
{
|
|
this->regs = regs;
|
|
setPrescaler(TMR_DEFAULT_PSC);
|
|
}
|
|
|
|
TMRChannel::~TMRChannel()
|
|
{
|
|
}
|
|
|
|
errorCode TMRChannel::start()
|
|
{
|
|
regs->CNTR = 0x0000;
|
|
|
|
regs->CSCTRL &= ~TMR_CSCTRL_TCF1;
|
|
regs->CSCTRL |= TMR_CSCTRL_TCF1EN;
|
|
return errorCode::OK;
|
|
}
|
|
|
|
errorCode TMRChannel::stop()
|
|
{
|
|
regs->CSCTRL &= ~TMR_CSCTRL_TCF1EN;
|
|
return errorCode::OK;
|
|
}
|
|
|
|
|
|
errorCode TMRChannel::begin(callback_t cb, float tcnt, bool periodic)
|
|
{
|
|
const float_t t = microsecondToCounter(tcnt);
|
|
uint16_t reload;
|
|
if (t > 0xFFFF)
|
|
{
|
|
postError(errorCode::periodOverflow);
|
|
reload = 0xFFFE;
|
|
} else
|
|
{
|
|
reload = (uint16_t)t - 1;
|
|
}
|
|
|
|
regs->CTRL = 0x0000;
|
|
regs->LOAD = 0x0000;
|
|
regs->COMP1 = reload;
|
|
regs->CMPLD1 = reload;
|
|
regs->CNTR = 0x0000;
|
|
setCallback(cb);
|
|
|
|
if (!periodic)
|
|
regs->CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(pscBits) | TMR_CTRL_ONCE | TMR_CTRL_LENGTH;
|
|
|
|
else
|
|
regs->CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(pscBits) | TMR_CTRL_LENGTH;
|
|
|
|
start();
|
|
return t > 0xFFFF ? errorCode::periodOverflow : errorCode::OK;
|
|
}
|
|
|
|
|
|
errorCode TMRChannel::trigger(float tcnt) // quick and dirty, should be optimized
|
|
{
|
|
const float_t t = microsecondToCounter(tcnt);
|
|
uint16_t reload = t > 0xFFFF ? 0xFFFF : (uint16_t)t;
|
|
|
|
regs->CTRL = 0x0000;
|
|
regs->LOAD = 0x0000;
|
|
regs->COMP1 = reload;
|
|
regs->CMPLD1 = reload;
|
|
regs->CNTR = 0x0000;
|
|
|
|
regs->CSCTRL &= ~TMR_CSCTRL_TCF1;
|
|
regs->CSCTRL |= TMR_CSCTRL_TCF1EN;
|
|
|
|
regs->CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(pscBits) | TMR_CTRL_ONCE | TMR_CTRL_LENGTH;
|
|
|
|
return errorCode::OK;
|
|
}
|
|
|
|
void TMRChannel::setPrescaler(uint32_t psc) // psc 0..7 -> prescaler: 1..128
|
|
{
|
|
pscValue = 1 << (psc & 0b0111);
|
|
pscBits = 0b1000 | (psc & 0b0111);
|
|
}
|
|
|
|
float TMRChannel::getMaxPeriod() const
|
|
{
|
|
return pscValue / 150'000'000.0f * 0xFFFE;
|
|
}
|
|
|
|
// void TMRChannel::_setNextPeriod(const uint16_t cnt)
|
|
// {
|
|
// regs->CMPLD1 = cnt;
|
|
// }
|
|
|
|
// errorCode TMRChannel::_setCurrentPeriod(const uint16_t cnt)
|
|
// {
|
|
|
|
// regs->COMP1 = cnt;
|
|
|
|
// //Do we need to wait some cycle for IP bus to update here / cache flush?
|
|
// //asm volatile("dsb");
|
|
|
|
// if (regs->CNTR > cnt)
|
|
// {
|
|
// //if counter alrready went over setted value force a triggering
|
|
// regs->CNTR = cnt;
|
|
// return errorCode::triggeredLate;
|
|
// }
|
|
|
|
// else
|
|
// {
|
|
// return errorCode::OK;
|
|
// }
|
|
// }
|
|
|
|
errorCode TMRChannel::setPeriod(float us)
|
|
{
|
|
//const float_t t = microsecondToCounter(us);
|
|
|
|
// if (t <= 0xFFFF)
|
|
// {
|
|
// return _setCurrentPeriod(t);
|
|
// } else
|
|
// {
|
|
// return errorCode::periodOverflow;
|
|
// }
|
|
return errorCode::notImplemented;
|
|
}
|
|
|
|
|
|
float_t TMRChannel::microsecondToCounter(const float_t us) const
|
|
{
|
|
return us * 150.0f / pscValue;
|
|
}
|
|
|
|
float_t TMRChannel::counterToMicrosecond(const float_t cnt) const
|
|
{
|
|
return cnt * pscValue / 150.0f;
|
|
}
|
|
|
|
} // namespace TeensyTimerTool
|
|
|