#ifndef FREERTOS_CPP_EVENT_GROUP_HPP #define FREERTOS_CPP_EVENT_GROUP_HPP #include #include extern "C" { #include "FreeRTOS.h" #include "event_groups.h" } namespace freertos { enum class WaitMode : uint8_t { any, all }; enum class ClearMode : uint8_t { keep, clear_on_exit }; template< typename Bit > class EventMask final { static_assert( std::is_enum< Bit >::value, "EventMask requires an enum bit type" ); public: constexpr EventMask() noexcept = default; explicit constexpr EventMask( Bit bit ) noexcept : value_ { static_cast< EventBits_t >( bit ) } { } [[nodiscard]] static constexpr EventMask from_raw( EventBits_t value ) noexcept { return EventMask { value, RawTag {} }; } [[nodiscard]] constexpr EventBits_t raw() const noexcept { return value_; } [[nodiscard]] constexpr bool contains( EventMask other ) const noexcept { return ( value_ & other.value_ ) == other.value_; } friend constexpr EventMask operator|( EventMask left, EventMask right ) noexcept { return from_raw( left.value_ | right.value_ ); } private: struct RawTag {}; constexpr EventMask( EventBits_t value, RawTag ) noexcept : value_ { value } {} EventBits_t value_ {}; }; template< typename Bit > struct WaitResult final { EventMask< Bit > observed {}; [[nodiscard]] constexpr bool satisfied( EventMask< Bit > wanted, WaitMode mode ) const noexcept { const EventBits_t matched = observed.raw() & wanted.raw(); return mode == WaitMode::all ? matched == wanted.raw() : matched != 0U; } }; struct StaticEventGroupStorage final { StaticEventGroup_t control {}; }; template< typename Bit > class EventGroup final { static_assert( std::is_enum< Bit >::value, "EventGroup requires an enum bit type" ); public: explicit EventGroup( StaticEventGroupStorage & storage ) noexcept : handle_ { xEventGroupCreateStatic( &storage.control ) } { } ~EventGroup() noexcept { if( handle_ != nullptr ) vEventGroupDelete( handle_ ); } EventGroup( const EventGroup & ) = delete; EventGroup & operator=( const EventGroup & ) = delete; EventGroup( EventGroup && ) = delete; EventGroup & operator=( EventGroup && ) = delete; [[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; } [[nodiscard]] EventMask< Bit > set( EventMask< Bit > bits ) noexcept { return EventMask< Bit >::from_raw( xEventGroupSetBits( handle_, bits.raw() ) ); } [[nodiscard]] EventMask< Bit > clear( EventMask< Bit > bits ) noexcept { return EventMask< Bit >::from_raw( xEventGroupClearBits( handle_, bits.raw() ) ); } [[nodiscard]] EventMask< Bit > bits() const noexcept { return EventMask< Bit >::from_raw( xEventGroupGetBits( handle_ ) ); } [[nodiscard]] WaitResult< Bit > wait( EventMask< Bit > wanted, WaitMode mode, ClearMode clear, TickType_t timeout ) noexcept { const EventBits_t result = xEventGroupWaitBits( handle_, wanted.raw(), clear == ClearMode::clear_on_exit ? pdTRUE : pdFALSE, mode == WaitMode::all ? pdTRUE : pdFALSE, timeout ); return { EventMask< Bit >::from_raw( result ) }; } [[nodiscard]] EventGroupHandle_t native_handle() const noexcept { return handle_; } private: EventGroupHandle_t handle_ {}; }; static_assert( !std::is_copy_constructible< EventGroup< WaitMode > >::value ); } // namespace freertos #endif