#ifndef FREERTOS_SOFTWARE_TIMER_HPP #define FREERTOS_SOFTWARE_TIMER_HPP #include extern "C" { #include "FreeRTOS.h" #include "timers.h" } namespace freertos { enum class TimerPolicy { one_shot, periodic }; enum class TimerCommand { rejected = 0, accepted = 1 }; template< typename Context, TimerPolicy Policy > class SoftwareTimer final { public: SoftwareTimer( StaticTimer_t & storage, const char * name, TickType_t period, Context & context ) noexcept : handle_( xTimerCreateStatic( name, period, Policy == TimerPolicy::periodic ? pdTRUE : pdFALSE, &context, &SoftwareTimer::trampoline, &storage ) ) { } SoftwareTimer( const SoftwareTimer & ) = delete; SoftwareTimer & operator=( const SoftwareTimer & ) = delete; SoftwareTimer( SoftwareTimer && ) = delete; SoftwareTimer & operator=( SoftwareTimer && ) = delete; [[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; } [[nodiscard]] TimerCommand start( TickType_t queue_wait = 0U ) noexcept { return command_result( xTimerStart( handle_, queue_wait ) ); } [[nodiscard]] TimerCommand reset( TickType_t queue_wait = 0U ) noexcept { return command_result( xTimerReset( handle_, queue_wait ) ); } [[nodiscard]] TimerCommand change_period( TickType_t period, TickType_t queue_wait = 0U ) noexcept { return command_result( xTimerChangePeriod( handle_, period, queue_wait ) ); } [[nodiscard]] TimerCommand stop( TickType_t queue_wait = 0U ) noexcept { return command_result( xTimerStop( handle_, queue_wait ) ); } [[nodiscard]] bool active() const noexcept { return xTimerIsTimerActive( handle_ ) != pdFALSE; } [[nodiscard]] TickType_t period() const noexcept { return xTimerGetPeriod( handle_ ); } [[nodiscard]] TimerHandle_t native_handle() const noexcept { return handle_; } private: static TimerCommand command_result( BaseType_t result ) noexcept { return result == pdPASS ? TimerCommand::accepted : TimerCommand::rejected; } static void trampoline( TimerHandle_t timer ) noexcept { auto * const context = static_cast< Context * >( pvTimerGetTimerID( timer ) ); configASSERT( context != nullptr ); context->on_timer( timer ); } TimerHandle_t handle_; }; template< typename Context > using OneShotTimer = SoftwareTimer< Context, TimerPolicy::one_shot >; template< typename Context > using PeriodicTimer = SoftwareTimer< Context, TimerPolicy::periodic >; static_assert( !std::is_copy_constructible_v< OneShotTimer< int > > ); static_assert( !std::is_move_constructible_v< OneShotTimer< int > > ); } // namespace freertos #endif