Skip to content

File PotMonitor.h

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

Go to the documentation of this file

Source Code

#pragma once
#include <stdint.h>
#include "UiEventQueue.h"
#include "../sys/system.h"

namespace daisy
{
template <typename BackendType, uint32_t numPots>
class PotMonitor
{
  public:
    PotMonitor()
    : queue_(nullptr),
      backend_(nullptr),
      deadBand_(1.0 / (1 << 12)),
      deadBandIdle_(1.0 / (1 << 10)),
      timeout_(0)
    {
    }

    void Init(UiEventQueue& queueToAddEventsTo,
              BackendType&  backend,
              uint16_t      idleTimeoutMs = 500,
              float         deadBandIdle  = 1.0 / (1 << 10),
              float         deadBand      = 1.0 / (1 << 12))
    {
        queue_        = &queueToAddEventsTo;
        deadBand_     = deadBand;
        backend_      = &backend;
        deadBandIdle_ = deadBandIdle;
        timeout_      = idleTimeoutMs;

        for(uint32_t i = 0; i < numPots; i++)
        {
            lastValue_[i]        = 0.0;
            timeoutCounterMs_[i] = 0;
        }

        lastCallSysTime_ = System::GetNow();
    }

    void Process()
    {
        const auto now      = System::GetNow();
        const auto timeDiff = now - lastCallSysTime_;
        lastCallSysTime_    = now;

        for(uint32_t i = 0; i < numPots; i++)
            ProcessPot(i, backend_->GetPotValue(i), timeDiff);
    }

    bool IsMoving(uint16_t potId) const
    {
        if(potId >= numPots)
            return false;
        else
            return timeoutCounterMs_[potId] < timeout_;
    }

    float GetCurrentPotValue(uint16_t potId) const
    {
        if(potId >= numPots)
            return -1.0f;
        else
            return lastValue_[potId];
    }

    BackendType& GetBackend() { return backend_; }

    uint16_t GetNumPotsMonitored() const { return numPots; }

  private:
    void ProcessPot(uint16_t id, float value, uint32_t timeDiffMs)
    {
        // currently moving?
        if(timeoutCounterMs_[id] < timeout_)
        {
            // check if pot has left the deadband. If so, add a new message
            // to the queue.
            float delta = lastValue_[id] - value;
            if((delta > deadBand_) || (delta < -deadBand_))
            {
                lastValue_[id] = value;
                queue_->AddPotMoved(id, value);
                timeoutCounterMs_[id] = 0;
            }
            // no movement, increment timeout counter
            else
            {
                timeoutCounterMs_[id] += timeDiffMs;
                // post activity changed event after timeout expired.
                if(timeoutCounterMs_[id] == timeout_)
                {
                    queue_->AddPotActivityChanged(id, false);
                }
            }
        }
        // not moving right now
        else
        {
            // check if pot has left the idle deadband. If so, add a new message
            // to the queue and restart the timeout
            float delta = lastValue_[id] - value;
            if((delta > deadBandIdle_) || (delta < -deadBandIdle_))
            {
                lastValue_[id] = value;
                queue_->AddPotActivityChanged(id, true);
                queue_->AddPotMoved(id, value);
                timeoutCounterMs_[id] = 0;
            }
        }
    }

    PotMonitor(const PotMonitor&) = delete;
    PotMonitor& operator=(const PotMonitor&) = delete;

    UiEventQueue* queue_;
    BackendType*  backend_;
    float         deadBand_;
    float         deadBandIdle_;
    uint16_t      timeout_;
    float         lastValue_[numPots];
    uint16_t      timeoutCounterMs_[numPots];
    uint32_t      lastCallSysTime_;
};

} // namespace daisy