Skip to content

File UiEventQueue.h

File List > external-docs > libDaisy > src > ui > UiEventQueue.h

Go to the documentation of this file

Source Code

#pragma once
#include <stdint.h>
#include "../util/FIFO.h"
#include "../util/scopedirqblocker.h"

namespace daisy
{
class UiEventQueue
{
  public:
    static constexpr uint16_t invalidButtonId = UINT16_MAX;

    static constexpr uint16_t invalidEncoderId = UINT16_MAX;

    static constexpr uint16_t invalidPotId = UINT16_MAX;

    struct __attribute__((packed)) Event
    {
        enum class EventType : uint8_t
        {
            invalid,
            buttonPressed,
            buttonReleased,
            encoderTurned,
            encoderActivityChanged,
            potMoved,
            potActivityChanged,
        };

        enum class ActivityType : uint8_t
        {
            inactive,
            active
        };

        EventType type;

        union
        {
            struct __attribute__((packed))
            {
                uint16_t id;
                uint16_t numSuccessivePresses;
                bool isRetriggering;
            } asButtonPressed;
            struct __attribute__((packed))
            {
                uint16_t id;
            } asButtonReleased;
            struct __attribute__((packed))
            {
                uint16_t id;
                int16_t increments;
                uint16_t stepsPerRev;
            } asEncoderTurned;
            struct __attribute__((packed))
            {
                uint16_t id;
                ActivityType newActivityType;
            } asEncoderActivityChanged;
            struct __attribute__((packed))
            {
                uint16_t id;
                float newPosition;
            } asPotMoved;
            struct __attribute__((packed))
            {
                uint16_t id;
                ActivityType newActivityType;
            } asPotActivityChanged;
        };
    };

    UiEventQueue() {}
    ~UiEventQueue() {}

    void AddButtonPressed(uint16_t buttonID,
                          uint16_t numSuccessivePresses,
                          bool     isRetriggering = false)
    {
        Event e;
        e.type               = Event::EventType::buttonPressed;
        e.asButtonPressed.id = buttonID;
        e.asButtonPressed.numSuccessivePresses = numSuccessivePresses;
        e.asButtonPressed.isRetriggering       = isRetriggering;
        ScopedIrqBlocker sIrqBl;
        events_.PushBack(e);
    }

    void AddButtonReleased(uint16_t buttonID)
    {
        Event m;
        m.type                = Event::EventType::buttonReleased;
        m.asButtonReleased.id = buttonID;
        ScopedIrqBlocker sIrqBl;
        events_.PushBack(m);
    }

    void AddEncoderTurned(uint16_t encoderID,
                          int16_t  increments,
                          uint16_t stepsPerRev)
    {
        Event e;
        e.type                        = Event::EventType::encoderTurned;
        e.asEncoderTurned.id          = encoderID;
        e.asEncoderTurned.increments  = increments;
        e.asEncoderTurned.stepsPerRev = stepsPerRev;
        ScopedIrqBlocker sIrqBl;
        events_.PushBack(e);
    }

    void AddEncoderActivityChanged(uint16_t encoderId, bool isActive)
    {
        Event e;
        e.type = Event::EventType::encoderActivityChanged;
        e.asEncoderActivityChanged.id = encoderId;
        e.asEncoderActivityChanged.newActivityType
            = isActive ? Event::ActivityType::active
                       : Event::ActivityType::inactive;
        ScopedIrqBlocker sIrqBl;
        events_.PushBack(e);
    }

    void AddPotMoved(uint16_t potId, float newPosition)
    {
        Event e;
        e.type                   = Event::EventType::potMoved;
        e.asPotMoved.id          = potId;
        e.asPotMoved.newPosition = newPosition;
        ScopedIrqBlocker sIrqBl;
        events_.PushBack(e);
    }

    void AddPotActivityChanged(uint16_t potId, bool isActive)
    {
        Event e;
        e.type                    = Event::EventType::potActivityChanged;
        e.asPotActivityChanged.id = potId;
        e.asPotActivityChanged.newActivityType
            = isActive ? Event::ActivityType::active
                       : Event::ActivityType::inactive;
        ScopedIrqBlocker sIrqBl;
        events_.PushBack(e);
    }

    Event GetAndRemoveNextEvent()
    {
        ScopedIrqBlocker sIrqBl;
        if(events_.IsEmpty())
        {
            Event m;
            m.type = Event::EventType::invalid;
            return m;
        }
        else
        {
            return events_.PopFront();
        }
    }

    bool IsQueueEmpty()
    {
        ScopedIrqBlocker sIrqBl;
        return events_.IsEmpty();
    }

  private:
    FIFO<Event, 256> events_;
};

} // namespace daisy