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


#ifndef ECXX_PLATFORM_BCM_OUTPUT_H
#define ECXX_PLATFORM_BCM_OUTPUT_H


#include <eCxx/Platform/Common/Application.h>


namespace eCxx {


//
// A simple BCM (binary code modulation) waveform generator
//
/*
 * # In all platforms this generator is implemented using bit banging method.
 *
 * # Application::setPinMode() must be called manually just like when using Application::analogWrite()
 */
template <uint8_t ChannelN>
class BCMOutput : public Uncopyable {
    public:
        static constexpr uint8_t NumberOfChannels = ChannelN;

    public:
        inline BCMOutput() = delete;
        inline ~BCMOutput() = default;

    public:
        inline BCMOutput(const uint8_t (&pin)[NumberOfChannels]) noexcept;

        inline uint8_t& operator[](uint8_t channelIndex) noexcept;
        inline uint8_t operator[](uint8_t channelIndex) const noexcept;

        // NOTE : # This function must be called periodically at a minimum frequency
        //          of ~50 kHz for a relatively flicker-free visual.
        //        # Using timer/counter interrupt is highly recommended for stability.
        inline void ICACHE_RAM_ATTR update() noexcept;

    private:
        static constexpr uint8_t BackBuffer  = 0;
        static constexpr uint8_t FrontBuffer = 1;

        Application::_PinFDW _pinFDW[NumberOfChannels];

        uint8_t              _channelValue[2][NumberOfChannels];

        uint8_t              _bcmPhase;
        uint8_t              _bcmCounter;
};


//
// Include the implementation file
//
#define INCLUDE_ECXX_PLATFORM_BCM_OUTPUT_TPP
#include "BCMOutput.tpp"


} // namespace eCxx


#endif
