#pragma once //#include "Arduino.h" #include "ErrorHandling/error_codes.h" #include "ITimerChannel.h" #include #if defined(USE_TIME_LITERALS) # include "frequency.h" # include using namespace std::chrono_literals; using namespace std::chrono; #endif namespace TeensyTimerTool { class BaseTimer { public: template inline errorCode begin(callback_t callback, T period, bool start = true); inline errorCode setPrescaler(int psc); inline errorCode end(); inline errorCode start(); inline errorCode stop(); inline float getMaxPeriod() const; protected: template ::value, int>* = nullptr> T getPeriod(T v) { return v; } BaseTimer(TimerGenerator* generator, bool periodic); TimerGenerator* timerGenerator; ITimerChannel* timerChannel; bool isPeriodic; uint32_t prescaler = 0; #if defined(USE_TIME_LITERALS) public: template inline float getMaxDuration() const { return getMaxPeriod() * dur::period::den / dur::period::num; } protected: template ::value, int>* = nullptr> float getPeriod(T v) { return (duration_cast>(v).count()); } template ::value, int>* = nullptr> float getPeriod(T v) { return 1'000'000 / duration_cast(v).count(); } #endif }; // INLINE IMPLEMENTATION ================================================ template errorCode BaseTimer::begin(callback_t callback, T p, bool start) { auto period = getPeriod(p); if (callback == nullptr) return postError(errorCode::callback); if (isPeriodic && period == 0) return postError(errorCode::reload); if (timerChannel == nullptr) { if (timerGenerator != nullptr) // use timer passed in during construction { timerChannel = timerGenerator(); if (timerChannel == nullptr) return postError(errorCode::noFreeChannel); } else //find the next free timer { for (unsigned i = 0; timerChannel == nullptr && i < timerCnt; i++) { timerChannel = timerPool[i](); } } if (timerChannel == nullptr) return postError(errorCode::noFreeModule); } errorCode result = timerChannel->begin(callback, period, isPeriodic); if (result == errorCode::OK) { if (isPeriodic && start) timerChannel->start(); } return postError(result); } errorCode BaseTimer::end() { return postError(errorCode::notImplemented); } errorCode BaseTimer::start() { timerChannel->start(); return errorCode::OK; // hack, implement return value in timer interface } errorCode BaseTimer::stop() { return postError(timerChannel->stop()); } float BaseTimer::getMaxPeriod() const { if (timerChannel != nullptr) { return timerChannel->getMaxPeriod(); } postError(errorCode::notInitialized); return 0; } }