////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// Programname: HSA_LCD_Shield - Header                                       //
// Date: 16.11.2018                                                           //
// Description: Header-File of the LCD-Shield, which was designed and built   //
//              in the Modul "Elektronikdesign". In this file you can find    //
//              the description of all functions of the class HSA_LCD_Shield. //
//                                                                            //
// Author: Tobias Müller, M. Eng.                                             //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
////////////////////             Create Header              ////////////////////
////////////////////////////////////////////////////////////////////////////////

#ifndef HSA_LCD_SHIELD
#define HSA_LCD_SHIELD

////////////////////////////////////////////////////////////////////////////////
////////////////////             Privat Symbols             ////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////          Pin-Config Version 5          ////////////////////

// Button Right
#ifndef BUTTON_RIGHT_V5
#define BUTTON_RIGHT_V5 0x02
#endif

// Button Down
#ifndef BUTTON_DOWN_V5
#define BUTTON_DOWN_V5 0x03
#endif

// Button Up
#ifndef BUTTON_UP_V5
#define BUTTON_UP_V5 0x04
#endif

// Button Left
#ifndef BUTTON_LEFT_V5
#define BUTTON_LEFT_V5 0x05
#endif

// LED Red
#ifndef LED_RED_V5
#define LED_RED_V5 0x06
#endif

// LED Green
#ifndef LED_GREEN_V5
#define LED_GREEN_V5 0x07
#endif

// LCD-Backlight
#ifndef LCD_BACKLIGHT_V5
#define LCD_BACKLIGHT_V5 0x08
#endif

////////////////////          Pin-Config Version 6          ////////////////////

// Button Right
#ifndef BUTTON_RIGHT_V6
#define BUTTON_RIGHT_V6 0x02
#endif

// Button Down
#ifndef BUTTON_DOWN_V6
#define BUTTON_DOWN_V6 0x03
#endif

// Button Up
#ifndef BUTTON_UP_V6
#define BUTTON_UP_V6 0x05
#endif

// Button Left
#ifndef BUTTON_LEFT_V6
#define BUTTON_LEFT_V6 0x06
#endif

// LED Red
#ifndef LED_RED_V6
#define LED_RED_V6 0x07
#endif

// LED Green
#ifndef LED_GREEN_V6
#define LED_GREEN_V6 0x08
#endif

// LCD-Backlight
#ifndef LCD_BACKLIGHT_V6
#define LCD_BACKLIGHT_V6 0x09
#endif

////////////////////           Display Parameters           ////////////////////

// Control Byte: No Bit set
#ifndef CONTROL_BYTE
#define CONTROL_BYTE 0x00        
#endif

// Control Byte: Continue Bit set
#ifndef CONTROL_BYTE_CB
#define CONTROL_BYTE_CB 0x80        
#endif

// Control Byte: Data/Command Selection Bit set
#ifndef CONTROL_BYTE_DCB
#define CONTROL_BYTE_DCB 0x40       // write RAM Data
#endif

// LCD-Parameter: Function Set 1
#ifndef LCD_PARA_FUNC1
#define LCD_PARA_FUNC1 0x3A        // 8 Bit, RE = 1, IS = 0
#endif

// LCD-Parameter: Function Set 2
#ifndef LCD_PARA_FUNC2
#define LCD_PARA_FUNC2 0x39        // 8 Bit, RE = 0, IS = 1
#endif

// LCD-Parameter: Function Set 3
#ifndef LCD_PARA_FUNC3
#define LCD_PARA_FUNC3 0x38        // 8 Bit, RE = 0, IS = 0
#endif

// LCD-Parameter: Extended Function
#ifndef LCD_PARA_EXT_FUNC
#define LCD_PARA_EXT_FUNC 0x09    // 4-Line Display
#endif

// LCD-Parameter: Entry Mode
#ifndef LCD_PARA_ENTRY_MODE
#define LCD_PARA_ENTRY_MODE 0x06  // Bottom View
#endif

// LCD-Parameter: Bias Setting
#ifndef LCD_PARA_BIAS_SET
#define LCD_PARA_BIAS_SET 0x1E    // BS1 = 1
#endif

// LCD-Parameter: Internal OSC
#ifndef LCD_PARA_INT_OSC
#define LCD_PARA_INT_OSC 0x1B     // BS0 = 1, Bias = 1/6
#endif

// LCD-Parameter: Follower Control
#ifndef LCD_PARA_FOL_CON
#define LCD_PARA_FOL_CON 0x6E     // Devider on, Set Value
#endif

// LCD-Parameter: Power Control
#ifndef LCD_PARA_POW_CON
#define LCD_PARA_POW_CON 0x56     // Booster on, Set Contrast
#endif

// LCD-Parameter: Contrast Set
#ifndef LCD_PARA_CONTRAST
#define LCD_PARA_CONTRAST 0x7A
#endif

// LCD-Parameter: Display on/off Control
#ifndef LCD_PARA_DIS_CON
#define LCD_PARA_DIS_CON 0x0C     // Display on, Cursor off, Blink off
#endif

// LCD-Parameter: Clear Display 
#ifndef LCD_PARA_CLR_DIS
#define LCD_PARA_CLR_DIS 0x01
#endif

// LCD-Parameter: ROM Selection
#ifndef LCD_PARA_ROM_SEL
#define LCD_PARA_ROM_SEL 0x72
#endif

// LCD-Parameter: Display Row 1 
#ifndef LCD_PARA_DIS_ROW1
#define LCD_PARA_DIS_ROW1 0x80
#endif

// LCD-Parameter: Display Row 2
#ifndef LCD_PARA_DIS_ROW2
#define LCD_PARA_DIS_ROW2 0xA0
#endif

// LCD-Parameter: Display Row 3 
#ifndef LCD_PARA_DIS_ROW3
#define LCD_PARA_DIS_ROW3 0xC0
#endif

// LCD-Parameter: Display Row 4 
#ifndef LCD_PARA_DIS_ROW4
#define LCD_PARA_DIS_ROW4 0xE0
#endif

////////////////////           ASCII-Char Symbols           ////////////////////

// Free Space 
#ifndef FREE_SPACE
#define FREE_SPACE 0x20
#endif

// End of a String
#ifndef STRING_END
#define STRING_END 0x00
#endif

// Backslash n (\n)
#ifndef BACKSLASH_N
#define BACKSLASH_N 0x0A
#endif

// Backslash r (\r)
#ifndef BACKSLASH_R
#define BACKSLASH_R 0x0D
#endif

////////////////////           Additional Symbols           ////////////////////

// Delay before and after transmission in µs
#ifndef DELAY_TRANS_US
#define DELAY_TRANS_US 0x64
#endif

// Array size for writing a row
#ifndef ARRAY_SIZE_ROW
#define ARRAY_SIZE_ROW 0x0D
#endif

// Const Char Size for Configuration
#ifndef CONFIG_SIZE
#define CONFIG_SIZE 0x05
#endif

////////////////////////////////////////////////////////////////////////////////
////////////////////             Public Symbols             ////////////////////
////////////////////////////////////////////////////////////////////////////////

////////////////////           Display Parameters           ////////////////////

// I²C Addresse (Default)
#ifndef I2C_ADDRESS
#define I2C_ADDRESS 0x3C
#endif

////////////////////               Pin-Symbols              ////////////////////

// Button Up
#ifndef BUTTON_UP
#define BUTTON_UP 0x01
#endif

// Button Right
#ifndef BUTTON_RIGHT
#define BUTTON_RIGHT 0x02
#endif

// Button Down
#ifndef BUTTON_DOWN
#define BUTTON_DOWN 0x03
#endif

// Button Left
#ifndef BUTTON_LEFT
#define BUTTON_LEFT 0x04
#endif

// LED Red
#ifndef LED_RED
#define LED_RED 0x05
#endif

// LED Green
#ifndef LED_GREEN
#define LED_GREEN 0x06
#endif

////////////////////        LCD-Shield Configurations       ////////////////////

// Config: LEDs = On, Buttons = On (Default)
#ifndef CONFIG_L1B1
#define CONFIG_L1B1 "L1B1"
#endif

// Config: LEDs = On, Buttons = Off
#ifndef CONFIG_L1B0
#define CONFIG_L1B0 "L1B0"
#endif

// Config: LEDs = Off, Buttons = On
#ifndef CONFIG_L0B1
#define CONFIG_L0B1 "L0B1"
#endif

// Config: LEDs = Off, Buttons = Off
#ifndef CONFIG_L0B0
#define CONFIG_L0B0 "L0B0"
#endif

////////////////////             Version Symbols            ////////////////////

// Version 5
#ifndef LCD_VERSION_5
#define LCD_VERSION_5 0x05
#endif

// Version 6
#ifndef LCD_VERSION_6
#define LCD_VERSION_6 0x06
#endif

////////////////////////////////////////////////////////////////////////////////
////////////////////         Include Header-File            ////////////////////
////////////////////////////////////////////////////////////////////////////////

#include <Arduino.h>
#include <Wire.h>
#include <stdio.h>

////////////////////////////////////////////////////////////////////////////////
////////////////////             Define Class               ////////////////////
////////////////////////////////////////////////////////////////////////////////

/**
 * @brief LCD-Shield Class to control all functionalities of the Shield
 */
class HSA_LCD_Shield {

////////////////////////////////////////////////////////////////////////////////
////////////////////     protected Functions/Variables      ////////////////////
////////////////////////////////////////////////////////////////////////////////

protected:

////////////////////          protected Variables           ////////////////////

byte __version;             //! @brief Store used LCD-Shield version
byte __i2cAddress;          //! @brief Store the I²C-Address of the LC-Display
char __config[CONFIG_SIZE]; //! @brief Store the Buttons/LEDs-Configuration

bool __buttons;     //! @brief Store the value "true", if the buttons configured
bool __leds;        //! @brief Store the value "true", if the LEDs configured

byte __buttonUp;    //! @brief Store address of button up
byte __buttonDown;  //! @brief Store address of button down
byte __buttonRight; //! @brief Store address of button right
byte __buttonLeft;  //! @brief Store adress of button left

byte __ledGreen;    //! @brief Store address of LED green
byte __ledRed;      //! @brief Store address of LED red

byte __lcdBacklight;//! @brief Store address of LCD-Backlight

////////////////////           GPIO Configuration           ////////////////////

/**
 * @brief Configure GPIOs, depending of LCD-Shield version
 * 
 * @return true Configuration is accepted
 * @return false Configuration is not accepted, check construction
 */
bool __gpioConfig(void);

////////////////////////////////////////////////////////////////////////////////
////////////////////       Privat Functions/Variables       ////////////////////
////////////////////////////////////////////////////////////////////////////////

private:

////////////////////               Send Message             ////////////////////

/**
 * @brief Used, to send an array of bytes to the LC-Display
 * 
 * @param bytes Array of bytes
 * @param sizeBytes Size of the array of Bytes
 */
void _sendMessage(byte* bytes, byte sizeBytes);

////////////////////////////////////////////////////////////////////////////////
////////////////////     Public Functions/Variables         ////////////////////
////////////////////////////////////////////////////////////////////////////////

public:

////////////////////               Constructor              ////////////////////

/**
 * @brief Construct a new HSA_LCD_Shield object with default Shield-ver./Config
 */
HSA_LCD_Shield();

/**
 * @brief Construct a new HSA_LCD_Shield object with different Shield version
 * 
 * @param version Version of LCD-Shield
 */
HSA_LCD_Shield(byte version);

/**
 * @brief Construct a new HSA_LCD_Shield object with different Config
 * 
 * @param config Configuration of Buttons and LEDs 
 */
HSA_LCD_Shield(const char config[CONFIG_SIZE]);

/**
 * @brief Construct a new HSA_LCD_Shield object with different Shield-ver./Config
 * 
 * @param version Version of LCD-Shield
 * @param config Configuration of Buttons and LEDs 
 */
HSA_LCD_Shield(byte version, const char config[CONFIG_SIZE]);

////////////////////             Deconstructor              ////////////////////

/**
 * @brief Destroy the HSA_LCD_Shield object
 */
~HSA_LCD_Shield(void);

////////////////////          Start Configuration           ////////////////////

/**
 * @brief Start Configuration of LC-Display and Buttons/LEDS
 * 
 * @return true Configuration is accepted
 * @return false Configuration is not accepted, check construction
 */
bool begin(void);

/**
 * @brief Start Configuration of LC-Display and Buttons/LEDS
 * 
 * @param address I²C-Address of LC-Display
 * 
 * @return true Configuration is accepted
 * @return false Configuration is not accepted, check construction
 */
bool begin(byte address);

////////////////////             LCD-Backlight              ////////////////////

/**
 * @brief Turning on/off the LCD-Backlight
 * 
 * @param value Boolean value for turning on/off the LCD-Backlight
 */
void lcdBacklight(bool value);

////////////////////             Clear Display              ////////////////////

/**
 * @brief Clear the LC-Display
 */
void clearDisplay(void);

///////////////////             Return Version              ////////////////////

/**
 * @brief Return the configured LCD-Shield version
 * 
 * @return byte Return the configured LCD-Shield version
 */
byte returnVersion(void);

////////////////////             Return Config              ////////////////////

/**
 * @brief Return the Configuration of Buttons/LEDs
 * 
 * @return char* Return the Address of the Configuration Buttons/LEDs
 */
char* returnConfig(void);

////////////////////            Return I²C-Address          ////////////////////

/**
 * @brief Return the I²C-Address of the LC-Display
 * 
 * @return byte Return the I²C-Address of the LC-Display
 */
byte returnAddress(void);

////////////////////               Control LEDs             ////////////////////

/**
 * @brief Function to control the state of a LED
 * 
 * @param ledPin Pin-Number/Name of the LED
 * @param state State of the LED
 * 
 * @return true LED control success
 * @return false LED control not success
 */
bool controlLED(char ledPin, bool state);

////////////////////               Get LED state            ////////////////////

/**
 * @brief Function to get the state of a LED
 * 
 * @param ledPin Pin-Number/Name of the LED
 * 
 * @return false LED is off or LED is unknown
 * @return true LED in on
 */
bool getLED(char ledPin);

////////////////////          Get the pressed Button        ////////////////////

/**
 * @brief Return the number of the button, which is pressed
 * 
 * @return char 0x00, if no or more than one button is pressed or buttons are 
 *              not configured
 * @return char 0x01, if only button "Up" is pressed
 * @return char 0x02, if only button "Right" is pressed
 * @return char 0x03, if only button "Down" is pressed
 * @return char 0x04, if only button "Left" is pressed
 */
byte getButton();

////////////////////                Write Row               ////////////////////

/**
 * @brief Write words over all rows.
 * 
 * @param text Array of bytes, which should be written to the rows.
 * 
 * @return false Write to Rows was not possible
 * @return true Write to Rows was successful
 */
bool writeRow(const char* text);

/**
 * @brief Write words to a targeted row.
 * 
 * @param row Choose the row to write
 * @param text Array of bytes, which should be written to the targeted row.
 * 
 * @return false Write to chosen Row was not possible
 * @return true Write to chosen Row was successful
 */
bool writeRow(byte row, const char* text);

////////////////////             Write Position XY          ////////////////////

/**
 * @brief Write words to a targeted Position (row/column)
 * 
 * @param row Choose the row to write
 * @param column Choose the column to write
 * @param text Array of bytes, which should be written.
 * 
 * @return false Write to chosen Row/Column was not possible
 * @return true Write to chosen Row/Column was successful
 */
bool writeXY(byte row, byte column, const char* text);

////////////////////////////////////////////////////////////////////////////////
////////////////////             close Header               ////////////////////
////////////////////////////////////////////////////////////////////////////////

};

#endif