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


#ifndef ECXX_PLATFORM_CHARACTER_LCD_4BIT_H
#define ECXX_PLATFORM_CHARACTER_LCD_4BIT_H


#include <eCxx/Platform/CharacterLCD.h>


namespace eCxx {


//
// A simple character LCD driver using 4-bit parallel output method
//
class CharacterLCD_4Bit : public CharacterLCD<CharacterLCD_4Bit> {
    public:
        inline ~CharacterLCD_4Bit() = default;

    public:
       inline CharacterLCD_4Bit(
           uint8_t     pinEN,
           uint8_t     pinRW,
           uint8_t     pinRS,
           uint8_t     pinD4,
           uint8_t     pinD5,
           uint8_t     pinD6,
           uint8_t     pinD7,
           uint8_t     pinBL,
           ActiveState atsBL = ActiveState::High
       );

       void setBacklight(bool on, bool immediate = true);

       void sendLNibble(uint8_t value) const noexcept;

       void sendCommand(uint8_t value) const noexcept;
       void sendData(uint8_t value) const noexcept;

    private:
        void init();
        void uninit();

        inline bool initialized() const;
        inline void useRWAsE2(bool val) noexcept;

        void pulseData(uint8_t value, bool rs) const noexcept;

        friend class CharacterLCD<CharacterLCD_4Bit>;

    private:
       bool    _initialized;

       uint8_t _pinEN;
       uint8_t _pinRW;
       uint8_t _pinRS;
       uint8_t _pinD4;
       uint8_t _pinD5;
       uint8_t _pinD6;
       uint8_t _pinD7;
       uint8_t _pinBL;

       bool    _blActvHigh;
       bool    _blState;

       bool    _useRWAsE2;
};


inline CharacterLCD_4Bit::CharacterLCD_4Bit(
    uint8_t     pinEN,
    uint8_t     pinRW,
    uint8_t     pinRS,
    uint8_t     pinD4,
    uint8_t     pinD5,
    uint8_t     pinD6,
    uint8_t     pinD7,
    uint8_t     pinBL,
    ActiveState atsBL
)
: _initialized(false)
, _pinEN      (pinEN)
, _pinRW      (pinRW)
, _pinRS      (pinRS)
, _pinD4      (pinD4)
, _pinD5      (pinD5)
, _pinD6      (pinD6)
, _pinD7      (pinD7)
, _pinBL      (pinBL)
, _blActvHigh (atsBL == ActiveState::High)
, _blState    (_blActvHigh)
, _useRWAsE2  (false)
{}


inline bool CharacterLCD_4Bit::initialized() const
{ return _initialized; }


inline void CharacterLCD_4Bit::useRWAsE2(bool val) noexcept
{ _useRWAsE2 = val; }


} // namespace eCxx


#endif
