Skip to content

File evamMinmaxDecor.h

File List > src > evamMinmaxDecor.h

Go to the documentation of this file

#pragma once

#include "evamRingBuffer.h"

namespace evam
{
    struct MinmaxConfig {
        unsigned char n;

        MinmaxConfig(unsigned char n) : n(n) {}
    };

    template <class TMotor, unsigned char N>
    class MinmaxDecor : public TMotor
    {
        static_assert(N >= 2 && N <= 5, "N out of range 2..5");

    private:
        MinmaxConfig mConfig;
        RingBuffer<signed short, N * N> mRing;
        signed short mMaxBuffer[N];
        signed short mMinBuffer[N];

    public:
        MinmaxDecor() : mConfig(N)
        {
            for (unsigned char i = 0; i < N; ++i)
            {
                mMaxBuffer[i] = 0;
                mMinBuffer[i] = 0;
            }
        }

        template<typename... Args>
        MinmaxDecor(MinmaxConfig config, Args... args) 
            : mConfig(config), TMotor(args...)
        {
            for (unsigned char i = 0; i < N; ++i)
            {
                mMaxBuffer[i] = 0;
                mMinBuffer[i] = 0;
            }
        }

        void Go(signed short value)
        {
            mRing.put(value);

            if (mRing.isFull())
            {
                for (unsigned char chunk = 0; chunk < N; chunk++)
                {
                    unsigned char start = chunk * N;
                    signed short maxVal = mRing.get(start);
                    signed short minVal = maxVal;

                    for (unsigned char i = 1; i < N; ++i)
                    {
                        signed short val = mRing.get(start + i);
                        if (val > maxVal)
                            maxVal = val;
                        if (val < minVal)
                            minVal = val;
                    }

                    mMaxBuffer[chunk] = maxVal;
                    mMinBuffer[chunk] = minVal;
                }

                value = (getMinimax() + getMaximin()) / 2;
            }

            TMotor::Go(value);
        }

    private:
        signed short getMinimax() const
        {
            signed short result = mMaxBuffer[0];
            for (unsigned char i = 1; i < N; ++i)
                if (mMaxBuffer[i] < result)
                    result = mMaxBuffer[i];
            return result;
        }

        signed short getMaximin() const
        {
            signed short result = mMinBuffer[0];
            for (unsigned char i = 1; i < N; ++i)
                if (mMinBuffer[i] > result)
                    result = mMinBuffer[i];
            return result;
        }
    };
}