////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// Programname: HSA_LCD_Shield - Header                                       //
// Date: 23.04.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

////////////////////////////////////////////////////////////////////////////////
////////////////////             Define Symbol              ////////////////////
////////////////////////////////////////////////////////////////////////////////

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

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

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

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

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

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

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

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

// 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

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

// Control Byte: Data/Command Selection Bit
#ifndef CONTROL_BYTE_DCB
#define CONTROL_BYTE_DCB 0x40
#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 0x0F     // Display on, Cursor on, Blink on
#endif

// LCD-Parameter: Clear Display 
#ifndef LCD_PARA_CLR_DIS
#define LCD_PARA_CLR_DIS 0x01
#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

// 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

// 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

////////////////////////////////////////////////////////////////////////////////
////////////////////         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           ////////////////////

char __i2cAddress;  //! @brief Store the I²C-Address of the LC-Display
char __config[0x05];//! @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

////////////////////////////////////////////////////////////////////////////////
////////////////////       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);

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

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

public:

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

/**
 * @brief Construct a new HSA_LCD_Shield object with default I²C-Address/Config
 */
HSA_LCD_Shield();

/**
 * @brief Construct a new HSA_LCD_Shield object with different I²C-Address
 * 
 * @param address Address of the LC-Display  
 */
HSA_LCD_Shield(char address);

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

/**
 * @brief Construct a new HSA_LCD_Shield object with different I²C-Address/Config
 * 
 * @param address Address of the LC-Display  
 * @param config Configuration of Buttons and LEDs 
 */
HSA_LCD_Shield(char address,const char config[0x05]);

////////////////////             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);

////////////////////             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 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 char Return the I²C-Address of the LC-Display
 */
char 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
 */
void controlLed(char ledPin, bool state);

////////////////////          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
 * @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
 */
char getButton();

////////////////////                Write Row 1             ////////////////////

/**
 * @brief Write words in the first row.
 * 
 * @param bytes Array of bytes, which should be written to the first row.
 */
void writeRow1(const char* bytes);

////////////////////                Write Row 2             ////////////////////

/**
 * @brief Write words in the second row.
 * 
 * @param bytes Array of bytes, which should be written to the second row.
 */
void writeRow2(const char* bytes);

////////////////////                Write Row 3             ////////////////////

/**
 * @brief Write words in the third row.
 * 
 * @param bytes Array of bytes, which should be written to the third row.
 */
void writeRow3(const char* bytes);

////////////////////                Write Row 4             ////////////////////

/**
 * @brief Write words in the fourth row.
 * 
 * @param bytes Array of bytes, which should be written to the fourth row.
 */
void writeRow4(const char* bytes);

////////////////////                Write 4 Rows            ////////////////////

/**
 * @brief Write words to all four rows.
 * 
 * @param bytes Array of bytes, which should be written to the four rows.
 */
void write4Rows(const char* bytes);

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

};

#endif