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;
            }
        };
    }