//-----------------------------------------------------------
//  Class for waveform display
//
//  2017/04/06, Copyright (c) 2016 MIKAMI, Naoki
//-----------------------------------------------------------

#ifndef F746_WAVEFORM_DISPLAY_HPP
#define F746_WAVEFORM_DISPLAY_HPP

#include "Array.hpp"

namespace Mikami
{
    class WaveformDisplay
    {
    public:
        WaveformDisplay(LCD_DISCO_F746NG &lcd,
                        uint16_t x0, uint16_t y0, int nData,
                        uint16_t rShift)
            : X0_(x0), Y0_(y0), R_SHIFT_(rShift),
              H1_(Y0_+LIMIT_+1), H2_(Y0_-LIMIT_-1),
              lcd_(lcd) { Axis(nData); }

        void Execute(const Array<int16_t> &xn)
        {
            lcd_.SetTextColor(GuiBase::ENUM_BACK);
            lcd_.FillRect(X0_, Y0_-LIMIT_-1,
                          xn.Length(), (LIMIT_+1)*2+1);
            Axis(xn.Length());
            lcd_.SetTextColor(LINE_COLOR_);
            uint16_t x1 = X0_;
            uint16_t y1 = Clip(xn[0]);
            for (int n=1; n<xn.Length(); n++)
            {
                uint16_t x2 = X0_ + n;
                uint16_t y2 = Clip(xn[n]);
                lcd_.DrawLine(x1, y1, x2, y2);
                if ((y1 == H1_) || (y1 == H2_))
                    lcd_.DrawPixel(x1, y1, LCD_COLOR_RED);
                x1 = x2;
                y1 = y2;
            }
        }

    private:
        static const uint16_t LIMIT_ = 32;
        static const uint32_t LINE_COLOR_ = LCD_COLOR_CYAN;
        const uint16_t X0_, Y0_;
        const uint16_t R_SHIFT_;
        const uint16_t H1_, H2_;

        LCD_DISCO_F746NG& lcd_;

        // Clipping
        uint16_t Clip(int16_t xn)
        {
            int16_t x = xn >> R_SHIFT_;
            if (x >  LIMIT_ ) x =  LIMIT_ + 1;
            if (x < -LIMIT_ ) x = -(LIMIT_ + 1) ;
            return Y0_ - x;
        }

        void Axis(int nData)
        {
            lcd_.SetTextColor(LCD_COLOR_WHITE);
            lcd_.DrawLine(X0_-5, Y0_, X0_+nData+5, Y0_);
        }

        // disallow copy constructor and assignment operator
        WaveformDisplay(const WaveformDisplay& );
        WaveformDisplay& operator=(const WaveformDisplay& );
    };
}
#endif  // F746_WAVEFORM_DISPLAY_HPP
