/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef ECXX_PLATFORM_WS2812B_DRIVER_H
#define ECXX_PLATFORM_WS2812B_DRIVER_H


#include <eCxx/CTL/UninstantiableUncopyable.h>


namespace eCxx {


//
// A simple WS2812B-based LED strip/matrix driver
//
/*
 * # In AVR and AVR platforms this driver is implemented using bit banging method.
 * # In NodeMCU     platform  this driver is implemented using DMA method.
 *
 * # The raw byte buffer must be in 3 bytes per pixel format.
 *
 * # There is no need to call Application::setPinMode() manually because this driver does it automatically.
 */
class WS2812BDriver : public Uncopyable {
    public:
        static constexpr uint16_t MaximumNumberOfLEDs = 320;

    public:
        WS2812BDriver();
        ~WS2812BDriver();

        // NOTE    : The 'rawByteBuffer' parameter cannot be a nullptr
        // WARNING : In NodeMCU platform the pin must be I2S_DATA (RX0DEF/GPIO3).
        bool begin(uint8_t pin, uint16_t numberOfLEDs, const uint8_t* rawByteBuffer);
        void end();

        // Replace the raw byte buffer (it is needed when using double or custom buffering)
        // NOTE : The 'rawByteBuffer' parameter cannot be a nullptr
        inline void setRawByteBuffer(const uint8_t* rawByteBuffer);

        void update();

    private:
        uint8_t        _pin;
        const uint8_t* _rawByteBuffer;
        uint16_t       _rawByteSize;
};


inline void WS2812BDriver::setRawByteBuffer(const uint8_t* rawByteBuffer)
{
    // Check if it is not yet initialized
    if(!_rawByteBuffer) return;

    // Check if the new raw byte buffer is nullptr
    if(!rawByteBuffer) return;

    // Save the new raw byte buffer pointer
    _rawByteBuffer = rawByteBuffer;
}


//
// The WS2812BDriver class above should be compatible with these LEDs as well
//
typedef WS2812BDriver WS2811Driver;
typedef WS2812BDriver WS2812Driver;
typedef WS2812BDriver WS2813Driver;
typedef WS2812BDriver WS2815Driver;

typedef WS2812BDriver PD9823Driver;
typedef WS2812BDriver SK6812RGBDriver;


} // namespace eCxx


#endif
