//////////////////////////////////////////////////////////////////////////////// // // // Programname: HSA_LCD_Shield - Code // // Date: 16.11.2018 // // Description: Code-File of the LCD-Shield, which was designed and built in // // the Modul "Elektronikdesign". In this file you can find the // // code of all functions mentioned in the Header-File of the // // class. // // // // Author: Tobias Müller, M. Eng. // // // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////// Include Header-File //////////////////// //////////////////////////////////////////////////////////////////////////////// #include "HSA_LCD_Shield.h" //////////////////////////////////////////////////////////////////////////////// //////////////////// Protected Functions //////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////// GPIO Configuration //////////////////// bool HSA_LCD_Shield::__gpioConfig(void) { // Save Pin configuration, depending of LCD-Shield version if(this->__version == LCD_VERSION_5) { // Save Pin configuration for buttons this->__buttonUp = BUTTON_UP_V5; this->__buttonRight = BUTTON_RIGHT_V5; this->__buttonDown = BUTTON_DOWN_V5; this->__buttonLeft = BUTTON_LEFT_V5; // Save Pin configuration for LEDs this->__ledGreen = LED_GREEN_V5; this->__ledRed = LED_RED_V5; // Save Pin configuration for LCD-Backlight this->__lcdBacklight = LCD_BACKLIGHT_V5; } else if(this->__version == LCD_VERSION_6) { // Save Pin configuration for buttons this->__buttonUp = BUTTON_UP_V6; this->__buttonRight = BUTTON_RIGHT_V6; this->__buttonDown = BUTTON_DOWN_V6; this->__buttonLeft = BUTTON_LEFT_V6; // Save Pin configuration for LEDs this->__ledGreen = LED_GREEN_V6; this->__ledRed = LED_RED_V6; // Save Pin configuration for LCD-Backlight this->__lcdBacklight = LCD_BACKLIGHT_V6; } // If LCD-Shield version is unknown, exit function with error else return false; // Check config-value and setup the LEDs, depending of config-value if(strcmp(this->__config,CONFIG_L1B0) == false || strcmp(this->__config,CONFIG_L1B1) == false) { // Setup LEDs pinMode(this->__ledGreen,OUTPUT); pinMode(this->__ledRed,OUTPUT); digitalWrite(this->__ledGreen,HIGH); digitalWrite(this->__ledRed,HIGH); // Store the value "true", if LEDs are configured this->__leds = true; } else { // Store the value "false", if LEDs are not configured this->__leds = false; } // Check config-value and setup the Buttons depending of config-value if(strcmp(this->__config,CONFIG_L0B1) == false || strcmp(this->__config,CONFIG_L1B1) == false) { // Setup Buttons pinMode(this->__buttonUp,INPUT); pinMode(this->__buttonRight,INPUT); pinMode(this->__buttonDown,INPUT); pinMode(this->__buttonLeft,INPUT); // Store the value "true", if buttons are configured this->__buttons = true; } else { // Store the value "false", if buttons are not configured this->__buttons = false; } // If config-value is unknown, quit configuration, otherwise configure Display if(strcmp(this->__config,CONFIG_L1B1) != false && strcmp(this->__config,CONFIG_L0B1) != false && strcmp(this->__config,CONFIG_L1B0) != false && strcmp(this->__config,CONFIG_L0B0) != false) return false; else { // Setup LCD-Backlight pinMode(this->__lcdBacklight,OUTPUT); // Setup initial LCD-Brightness this->__lcdBrightess = 255; // Initialize I²C as Master Wire.begin(); // Define an array of Bytes for configure the Display byte buffer[] = {CONTROL_BYTE_CB, LCD_PARA_FUNC1, LCD_PARA_EXT_FUNC, LCD_PARA_ENTRY_MODE, LCD_PARA_BIAS_SET, LCD_PARA_FUNC2, LCD_PARA_INT_OSC, LCD_PARA_FOL_CON, LCD_PARA_POW_CON, LCD_PARA_CONTRAST, LCD_PARA_FUNC3, LCD_PARA_DIS_CON, LCD_PARA_CLR_DIS}; // Send array of bytes _sendMessage(buffer, sizeof(buffer)); // Exit function with positive feedback return true; } } //////////////////////////////////////////////////////////////////////////////// //////////////////// Privat Functions //////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////// Send Message //////////////////// void HSA_LCD_Shield::_sendMessage(byte* bytes, byte sizeBytes) { // Small timeout before access the I²C-Bus delayMicroseconds(DELAY_TRANS_US); // Start I²C transmission Wire.beginTransmission(this->__i2cAddress); // Send an array of Bytes over I²C, depending of its size for(byte i = 0x00; i < sizeBytes; i++) Wire.write(bytes[i]); // Stop I²C transmission Wire.endTransmission(); // Small timeout after access the I²C-Bus delayMicroseconds(DELAY_TRANS_US); // Exit function return; } //////////////////////////////////////////////////////////////////////////////// //////////////////// Public Functions //////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////// Constructor //////////////////// HSA_LCD_Shield::HSA_LCD_Shield(byte version, const char config[CONFIG_SIZE]) { // Save LCD-Shield version this->__version = version; // Save standard I²C-Address for LC-Display this->__i2cAddress = I2C_ADDRESS; // Save the configuration of Buttons/LEDs strcpy(this->__config,config); // Exit Constructor return; } HSA_LCD_Shield::HSA_LCD_Shield(byte version) { // Save LCD-Shield version this->__version = version; // Save standard I²C-Address for LC-Display this->__i2cAddress = I2C_ADDRESS; // Save the configuration of Buttons/LEDs strcpy(this->__config,CONFIG_L1B1); // Exit Constructor return; } HSA_LCD_Shield::HSA_LCD_Shield(const char config[CONFIG_SIZE]){ // Save LCD-Shield version this->__version = LCD_VERSION_6; // Save standard I²C-Address for LC-Display this->__i2cAddress = I2C_ADDRESS; // Save the configuration of Buttons/LEDs strcpy(this->__config,config); // Exit Constructor return; } HSA_LCD_Shield::HSA_LCD_Shield(void){ // Save LCD-Shield version this->__version = LCD_VERSION_6; // Save standard I²C-Address for LC-Display this->__i2cAddress = I2C_ADDRESS; // Save the configuration of Buttons/LEDs strcpy(this->__config,CONFIG_L1B1); // Exit Constructor return; } //////////////////// Deconstructor //////////////////// HSA_LCD_Shield::~HSA_LCD_Shield(void) { // Exit function return; } //////////////////// Start Configuration //////////////////// bool HSA_LCD_Shield::begin(void) { // Configure GPIOs this->__lcd = __gpioConfig(); // Exit function return this->__lcd; } bool HSA_LCD_Shield::begin(byte address) { // Save I²C-Address of LC-Display this->__i2cAddress = address; // Configure GPIOs this->__lcd = __gpioConfig(); // Exit function return this->__lcd; } //////////////////// LCD-Backlight //////////////////// bool HSA_LCD_Shield::lcdBacklight(bool value) { // check, whether LCD is configured if(this->__lcd == false) return false; // Turning on/off LCD-Backlight, depending of LCD-Version if(this->__version > LCD_VERSION_5) { // Turning on/off LCD-Backlight if(value) analogWrite(this->__lcdBacklight,this->__lcdBrightess); else analogWrite(this->__lcdBacklight,value); } else { // Turning on/off LCD-Backlight digitalWrite(this->__lcdBacklight,value); } // Exit function return true; } bool HSA_LCD_Shield::lcdBacklight(bool value, char brightness) { // check, whether LCD is configured if(this->__lcd == false) return false; // Turning on/off LCD-Backlight, depending of LCD-Version if(this->__version > LCD_VERSION_5) { // check, whether brightness value is between 0 and 100 if(brightness < 0 || brightness > 100) return false; // store new brightness value this->__lcdBrightess = map(brightness,0,100,0,255); // Turning on/off LCD-Backlight if(value) analogWrite(this->__lcdBacklight,this->__lcdBrightess); else analogWrite(this->__lcdBacklight,value); } else { // Turning on/off LCD-Backlight digitalWrite(this->__lcdBacklight,value); } // Exit function return true; } //////////////////// Clear Display //////////////////// bool HSA_LCD_Shield::clearDisplay(void) { // check, whether LCD is configured if(this->__lcd == false) return false; // Define an array of Bytes for clearing the Display byte buffer[] = {CONTROL_BYTE_CB, LCD_PARA_CLR_DIS}; // Send array of bytes _sendMessage(buffer, sizeof(buffer)); // Exit function return true; } /////////////////// Return Version //////////////////// byte HSA_LCD_Shield::returnVersion(void) { // Exit function and return the configured Version for the LCD-Shield return this->__version; } //////////////////// Return Config //////////////////// char* HSA_LCD_Shield::returnConfig(void) { // Exit function and return the configuration value return this->__config; } //////////////////// Return I²C-Address //////////////////// byte HSA_LCD_Shield::returnAddress(void){ // Exit function and return the value of the I²C-Address return this->__i2cAddress; } //////////////////// Control LEDs //////////////////// bool HSA_LCD_Shield::controlLED(byte ledPin, bool state) { // Checks, whether LED-Pins are configured if(this->__leds) { // Checks, whether LED-Color is known and control LED if(ledPin == LED_GREEN) { digitalWrite(this->__ledGreen,!state); return true; } if(ledPin == LED_RED) { digitalWrite(this->__ledRed,!state); return true; } } // Exit function with error, if LED-Pins are not configured or LED-Color is // unknown return false; } //////////////////// Get LED state //////////////////// bool HSA_LCD_Shield::getLED(byte ledPin) { // Exit function and return the value of chosen LED if(ledPin == LED_GREEN && this->__leds) return !digitalRead(this->__ledGreen); else if(ledPin == LED_RED && this->__leds) return !digitalRead(this->__ledRed); else return false; } //////////////////// Get the pressed Button //////////////////// byte HSA_LCD_Shield::getButton() { // return 1, if only button "Up" is pressed and configured if(digitalRead(this->__buttonUp) && !digitalRead(this->__buttonRight) && !digitalRead(this->__buttonDown) && !digitalRead(this->__buttonLeft) && this->__buttons) return BUTTON_UP; // return 2, if only button "Right" is pressed and configured if(!digitalRead(this->__buttonUp) && digitalRead(this->__buttonRight) && !digitalRead(this->__buttonDown) && !digitalRead(this->__buttonLeft) && this->__buttons) return BUTTON_RIGHT; // return 3, if only button "Down" is pressed and configured if(!digitalRead(this->__buttonUp) && !digitalRead(this->__buttonRight) && digitalRead(this->__buttonDown) && !digitalRead(this->__buttonLeft) && this->__buttons) return BUTTON_DOWN; // return 4, if only button "Left" is pressed and configured if(!digitalRead(this->__buttonUp) && !digitalRead(this->__buttonRight) && !digitalRead(this->__buttonDown) && digitalRead(this->__buttonLeft) && this->__buttons) return BUTTON_LEFT; // return false, if no button or more than one button is pressed or // buttons are not configured return false; } //////////////////// Write Row //////////////////// bool HSA_LCD_Shield::writeRow(byte row, const char* text) { // check, whether LCD is configured if(this->__lcd == false) return false; // If chosen Row does not exist, exit function with error if(!(row >= 0x01 && row <= 0x04)) return false; // Define buffer for test Message byte buffer[ARRAY_SIZE_ROW] = ""; // Define variable to store a boolean value, if a control-byte was found bool controlByte = false; // Create data-array with message and send the message at the end for(byte i = 0x00; i < ARRAY_SIZE_ROW; i++) { // Set control-byte for changing parameter in the first iteration if(i == 0x00) buffer[i] = CONTROL_BYTE_CB; // Change the cursor position to row in the second iteration. if(i == 0x01 && row == 0x01) buffer[i] = LCD_PARA_DIS_ROW1; if(i == 0x01 && row == 0x02) buffer[i] = LCD_PARA_DIS_ROW2; if(i == 0x01 && row == 0x03) buffer[i] = LCD_PARA_DIS_ROW3; if(i == 0x01 && row == 0x04) buffer[i] = LCD_PARA_DIS_ROW4; // Set control-byte for writing to the display in the third iteration if(i == 0x02) buffer[i] = CONTROL_BYTE_DCB; // Copy text into the buffer between iteration 2 to 13 if(i > 0x02 && i < ARRAY_SIZE_ROW) { // If no control-byte was found, copy byte into buffer if(!controlByte) { // Check byte for control-byte if(isControl(text[i - 0x03])) controlByte = true; // if not, copy byte into buffer else buffer[i] = text[i - 0x03]; } // If control-byte was found, fill message with free space if(controlByte) { // Fill Buffer with free space buffer[i] = FREE_SPACE; } } } // Send message _sendMessage(buffer,sizeof(buffer)); // Exit function with success return true; } bool HSA_LCD_Shield::writeRow(const char* text) { // check, whether LCD is configured if(this->__lcd == false) return false; // Define buffer for test Message char buffer[ARRAY_SIZE_ROW] = ""; // Define variable to store the actual row position byte rowPosition = LCD_PARA_DIS_ROW1; // Define variable, which count the copied bytes byte countBytes = 0x00; // Create data-array with messages for 4 rows and send the messages for(byte i = 0x00; i < 0x28; i++){ // If the position of the row is not selected, skip following code if(rowPosition == false) continue; // If first row is selected if(rowPosition == LCD_PARA_DIS_ROW1) { // If counted bytes has not reach max value, copy byte into buffer if(countBytes < 0x0A) buffer[countBytes] = text[i]; // Check, if copied byte was control-byte if(isControl(text[i])) { // Check if control-byte was \n or \r or end of string, // set counted bytes to max value if(text[i] == BACKSLASH_N || text[i] == BACKSLASH_R || text[i] == STRING_END) countBytes = 0x0A; // Check if control-byte was end of the string, deactivate row position if(text[i] == STRING_END) rowPosition = false; } // Otherwise increase counted bytes else countBytes++; // If count bytes is max value if(countBytes == 0x0A) { // Reset count bytes countBytes = 0x00; // write first row writeRow(0x01, buffer); // If row position is deactivated if(rowPosition == false) { // clear following rows writeRow(0x02, &text[i]); writeRow(0x03, &text[i]); writeRow(0x04, &text[i]); } // Otherwise set row position the row 2 else rowPosition = LCD_PARA_DIS_ROW2; // skip the rest of the code in this iteration continue; } } // If second row is selected if(rowPosition == LCD_PARA_DIS_ROW2) { // If counted bytes has not reach max value, copy byte into buffer if(countBytes < 0x0A) buffer[countBytes] = text[i]; // Check, if copied byte was control-byte if(isControl(text[i])) { // Check if control-byte was \n or \r or end of string, // set counted bytes to max value if(text[i] == BACKSLASH_N || text[i] == BACKSLASH_R || text[i] == STRING_END) countBytes = 0x0A; // Check if control-byte was end of the string, deactivate row position if(text[i] == STRING_END) rowPosition = false; } // Otherwise increase counted bytes else countBytes++; // If count bytes is max value if(countBytes == 0x0A) { // Reset count bytes countBytes = 0x00; // write second row writeRow(0x02, buffer); // If row position is deactivated if(rowPosition == false) { // clear following rows writeRow(0x03, &text[i]); writeRow(0x04, &text[i]); } // Otherwise set row position the row 3 else rowPosition = LCD_PARA_DIS_ROW3; // skip the rest of the code in this iteration continue; } } // If third row is selected if(rowPosition == LCD_PARA_DIS_ROW3) { // If counted bytes has not reach max value, copy byte into buffer if(countBytes < 0x0A) buffer[countBytes] = text[i]; // Check, if copied byte was control-byte if(isControl(text[i])) { // Check if control-byte was \n or \r or end of string, // set counted bytes to max value if(text[i] == BACKSLASH_N || text[i] == BACKSLASH_R || text[i] == STRING_END) countBytes = 0x0A; // Check if control-byte was end of the string, deactivate row position if(text[i] == STRING_END) rowPosition = false; } // Otherwise increase counted bytes else countBytes++; // If count bytes is max value if(countBytes == 0x0A) { // Reset count bytes countBytes = 0x00; // write third row writeRow(0x03, buffer); // If row position is deactivated, clear following row if(rowPosition == false) writeRow(0x04, &text[i]); // Otherwise set row position the row 4 else rowPosition = LCD_PARA_DIS_ROW4; // skip the rest of the code in this iteration continue; } } // If fourth row is selected if(rowPosition == LCD_PARA_DIS_ROW4) { // If counted bytes has not reach max value, copy byte into buffer if(countBytes < 0x0A) buffer[countBytes] = text[i]; // Check, if copied byte was control-byte if(isControl(text[i])) { // Check if control-byte was \n or \r or end of string, // set counted bytes to max value if(text[i] == BACKSLASH_N || text[i] == BACKSLASH_R || text[i] == STRING_END) countBytes = 0x0A; // Check if control-byte was end of the string, deactivate row position if(text[i] == STRING_END) rowPosition = false; } // Otherwise increase counted bytes else countBytes++; // If count bytes is max value if(countBytes == 0x0A) { // Reset count bytes countBytes = 0x00; // write fourth row writeRow(0x04, buffer); // If row position is not deactivated, deaktivate row position if(rowPosition != false) rowPosition = false; // skip the rest of the code in this iteration continue; } } } // Exit function return true; } //////////////////// Write Position XY //////////////////// bool HSA_LCD_Shield::writeXY(byte row, byte column, const char* text) { // check, whether LCD is configured if(this->__lcd == false) return false; // If chosen Row does not exist, exit function with error if(!(row >= 0x01 && row <= 0x04)) return false; // If chosen Column does not exist, exit function with error if(!(column >= 0x01 && column <= 0x0A)) return false; // create variable to store count of chars byte count = 0x00; // Count chars inside of text for(byte i = 0x00; i < 0x0A && !isControl(text[i]); i++) count++; // Define buffer for text Message byte buffer[ARRAY_SIZE_ROW - (0x0A - count)] = ""; // Create data-array with message and send the message at the end for(byte i = 0x00; i < sizeof(buffer); i++) { // Set control-byte for changing parameter in the first iteration if(i == 0x00) buffer[i] = CONTROL_BYTE_CB; // Change the cursor position to row/column in the second iteration. if(i == 0x01 && row == 0x01) buffer[i] = LCD_PARA_DIS_ROW1 | (column - 0x01); if(i == 0x01 && row == 0x02) buffer[i] = LCD_PARA_DIS_ROW2 | (column - 0x01); if(i == 0x01 && row == 0x03) buffer[i] = LCD_PARA_DIS_ROW3 | (column - 0x01); if(i == 0x01 && row == 0x04) buffer[i] = LCD_PARA_DIS_ROW4 | (column - 0x01); // Set control-byte for writing to the display if(i == 0x02) buffer[i] = CONTROL_BYTE_DCB; // Copy text into the buffer between iteration 2 to 13 if(i >= 0x03 && i < sizeof(buffer)) buffer[i] = text[i - 0x03]; } // Send message _sendMessage(buffer,sizeof(buffer)); // Exit function with success return true; }