diff --git a/.gitignore b/.gitignore index c6f9a44..8234f63 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ .vscode/settings.json +.vscode + +.github/* +.github +.codespellrc diff --git a/CMakeLists.txt b/CMakeLists.txt index 34fda7c..50d35ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5) idf_component_register(SRCS "LiquidCrystal_Base.cpp" "LiquidCrystal.cpp" "LiquidCrystal_I2C.cpp" - INCLUDE_DIRS "." + INCLUDE_DIRS ".", "./coreLCD" REQUIRES arduino) -project(LiquidCrystal) \ No newline at end of file +project(LiquidCrystal_Base) \ No newline at end of file diff --git a/README.adoc b/README.adoc index 06df6e3..9bc1f96 100644 --- a/README.adoc +++ b/README.adoc @@ -28,6 +28,8 @@ TIP: To find the latest versions, refer to https://github.com/VladVanyuk/BaseLiq * Added https://github.com/MartyMacGyver/Arduino_I2C_Scanner/tree/masterp[I2C_scanner] in examples +* Added https://github.com/mrkaleArduinoLib/LiquidCrystal_I2C/tree/master[Complete Test] in examples. Also added readme file. + === License This project is released under a {License} License. diff --git a/docs/extras/info/2004_I2C_Serial_LCD_Display.jpg b/docs/extras/info/2004_I2C_Serial_LCD_Display.jpg new file mode 100644 index 0000000..64c30b5 Binary files /dev/null and b/docs/extras/info/2004_I2C_Serial_LCD_Display.jpg differ diff --git a/docs/extras/info/2004_Pinout.jpg b/docs/extras/info/2004_Pinout.jpg new file mode 100644 index 0000000..1075560 Binary files /dev/null and b/docs/extras/info/2004_Pinout.jpg differ diff --git a/docs/extras/info/Character_Set.jpg b/docs/extras/info/Character_Set.jpg new file mode 100644 index 0000000..878d10a Binary files /dev/null and b/docs/extras/info/Character_Set.jpg differ diff --git a/docs/extras/info/Chinese_I2C_Serial_LCD_Converter_Board_1602_2004.jpg b/docs/extras/info/Chinese_I2C_Serial_LCD_Converter_Board_1602_2004.jpg new file mode 100644 index 0000000..12b6940 Binary files /dev/null and b/docs/extras/info/Chinese_I2C_Serial_LCD_Converter_Board_1602_2004.jpg differ diff --git a/docs/extras/info/readme.txt b/docs/extras/info/readme.txt new file mode 100644 index 0000000..e60f8b2 --- /dev/null +++ b/docs/extras/info/readme.txt @@ -0,0 +1,47 @@ +// LiquidCrystal_I2C V2.0 - Mario H. atmega@xs4all.nl +// Mods for Chinese I2C converter board - Murray R. Van Luyn. vanluynm@iinet.net.au + +The LiquidCrystal_I2C library is a modified version of the standard LiquidCrystal library as found on +the Arduino website. +This library is intended to be used when a parallel HD44780 compatible LCD is controlled over I2C using +a Chinese PCF8574 extender. +4 of the 8 outputs are used for LCD data lines 4 to 7. +4 outputs are used for the Enable, register-select, Read/Write and backlight control lines. + +The Chinese PCF8574 extender is available in two versions, the PCF8574 and the PCF8574A. +The only difference between the two is the I2C base address. +The base address for the PCF8574 is 0x27 and the base address for the PCF8574A is 0x4E. +The examples included in this zip file assume the use of an PCF8574 set for address 0x27 +(A0, A1 and A3 un-linked, so pulled high). + +For PCF8574 the addressing is: + +Jp3 Jp2 Jp1 +A2 A1 A0 Dec Hex +L L L 32 0x20 +L L H 33 0x21 +L H L 34 0x22 +L H H 35 0x23 +H L L 36 0x24 +H L H 37 0x25 +H H L 38 0x26 +H H H 39 0x27 + +For PCF8574A the addressing is: + +Jp3 Jp2 Jp1 +A2 A1 A0 Dec Hex +L L L 56 0x38 +L L H 57 0x39 +L H L 64 0x40 +L H H 74 0x4A +H L L 75 0x4B +H L H 76 0x4C +H H L 77 0x4D +H H H 78 0x4E + +For compatibility reasons this library contains some aliases for functions that are known under different +names in other libraries. This should make it fairly easy to implement the library in existing sketches +without changing to much code. +Functions not supported by this library will return nothing at all and in case a return value is expected +the function will return 0. diff --git a/examples/AllSymbols/AllSymbols.ino b/examples/AllSymbols/AllSymbols.ino index a9db916..72dbbe8 100644 --- a/examples/AllSymbols/AllSymbols.ino +++ b/examples/AllSymbols/AllSymbols.ino @@ -1,5 +1,4 @@ -#include -#include +#include uint8_t bell[8] = {0x4, 0xe, 0xe, 0xe, 0x1f, 0x0, 0x4}; uint8_t note[8] = {0x2, 0x3, 0x2, 0xe, 0x1e, 0xc, 0x0}; @@ -11,57 +10,57 @@ uint8_t cross[8] = {0x0, 0x1b, 0xe, 0x4, 0xe, 0x1b, 0x0}; uint8_t retarrow[8] = {0x1, 0x1, 0x5, 0x9, 0x1f, 0x8, 0x4}; uint8_t happy[8] = - { - 0b00000, - 0b10001, - 0b00000, - 0b00000, - 0b10001, - 0b01110, - 0b00000, - 0b00000, +{ + 0b00000, + 0b10001, + 0b00000, + 0b00000, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }; uint8_t wow[8] = - { - 0b00000, - 0b10001, - 0b00000, - 0b01110, - 0b10001, - 0b01110, - 0b00000, - 0b00000, +{ + 0b00000, + 0b10001, + 0b00000, + 0b01110, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }; uint8_t anchor[8] = - { - 0b01110, - 0b01010, - 0b01110, - 0b00100, - 0b10101, - 0b10101, - 0b01110, - 0b00100}; +{ + 0b01110, + 0b01010, + 0b01110, + 0b00100, + 0b10101, + 0b10101, + 0b01110, + 0b00100 +}; uint8_t snow[8] = - { - 0b01000, - 0b11101, - 0b01011, - 0b00001, - 0b00100, - 0b01110, - 0b00100, - 0b10000}; +{ + 0b01000, + 0b11101, + 0b01011, + 0b00001, + 0b00100, + 0b01110, + 0b00100, + 0b10000 +}; // Set the LCD address to 0x27 for a 16 chars and 2 line display LiquidCrystal_I2C lcd(0x27, 20, 4); LiquidCrystal_I2C lcd2(0x26, 16, 2); -LiquidCrystal_I2C *lcd_ptr; - void setup() { lcd.init(); @@ -94,14 +93,27 @@ void keyCodes2004(uint8_t i) lcd.print("Codes 0x"); lcd.print(i, HEX); lcd.print("-0x"); - lcd.print(i + 16, HEX); + lcd.print(i + 60, HEX); lcd.setCursor(0, 1); - for (int j = 0; j < 16; j++) + for (int j = 0; j < 20; j++) + { + lcd.write(i + j); + } + + i+=20; + lcd.setCursor(0, 2); + for (int j = 0; j < 20; j++) + { + lcd.write(i + j); + } + + i+=20; + lcd.setCursor(0, 3); + for (int j = 0; j < 20; j++) { lcd.write(i + j); } - } void keyCodes1602(uint8_t i) @@ -117,22 +129,21 @@ void keyCodes1602(uint8_t i) { lcd2.write(i + j); } - } // display all keycodes void displayKeyCodes(void) { + // symbols 0x10-0x20 are usualy shown as empty uint8_t i = 0; - while (1) { keyCodes2004(i); keyCodes1602(i); - delay(5000); + delay(10000); - i += 16; + i += 16; } } diff --git a/examples/Autoscroll/Autoscroll.ino b/examples/Autoscroll/Autoscroll.ino index 7b8a1c5..5cbf377 100644 --- a/examples/Autoscroll/Autoscroll.ino +++ b/examples/Autoscroll/Autoscroll.ino @@ -31,7 +31,7 @@ by Tom Igoe modified 7 Nov 2016 by Arturo Guadalupi - modified 30 Nov 2024 + modified 2 Feb 2024 by Vladislav Vanyuk This example code is in the public domain. @@ -40,29 +40,27 @@ https://github.com/arduino-libraries/LiquidCrystal */ + +// choose what connection type your display is // #define TYPE_LCD #define TYPE_LCD_I2C + +// include the library code: #include +// virtual base class pointer to an object LiquidCrystal_Base *lcd; #if (defined TYPE_LCD) -// include the library code: -#include // initialize the library by associating any needed LCD interface pin // with the Arduino pin number it is connected to const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; LiquidCrystal lcd_normal(rs, en, d4, d5, d6, d7); #elif (defined TYPE_LCD_I2C) - -#include -LiquidCrystal_I2C lcd_i2c(0x27, 20, 4); //(0x27, 16, 2) - +LiquidCrystal_I2C lcd_i2c(0x27, 16, 2) //(0x27, 20, 4) #endif - - void setup() { Serial.begin(9600); diff --git a/examples/Blink/Blink.ino b/examples/Blink/Blink.ino index 4fba777..fc135b9 100644 --- a/examples/Blink/Blink.ino +++ b/examples/Blink/Blink.ino @@ -31,6 +31,8 @@ by Tom Igoe modified 7 Nov 2016 by Arturo Guadalupi + modified 2 Feb 2024 + by Vladislav Vanyuk This example code is in the public domain. @@ -40,25 +42,41 @@ */ // include the library code: -#include +#include +#define LCD_TYPE 1 // 0 - LCD, 1 - LCD_I2C + +LiquidCrystal_Base *lcd; + +#if (LCD_TYPE == 0) // initialize the library by associating any needed LCD interface pin // with the Arduino pin number it is connected to const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; -LiquidCrystal lcd(rs, en, d4, d5, d6, d7); +LiquidCrystal lcd_normal(rs, en, d4, d5, d6, d7); +#elif (LCD_TYPE == 1) +LiquidCrystal_I2C lcd_i2c(0x27, 16, 2); //(0x27, 20, 4) +#else +error("Please select the LCD type") +#endif void setup() { +#if (LCD_TYPE == 0) + lcd = &lcd_normal; +#elif (LCD_TYPE == 1) + lcd = &lcd_i2c; +#endif + // set up the LCD's number of columns and rows: - lcd.begin(16, 2); - // Print a message to the LCD. - lcd.print("hello, world!"); + lcd->begin(16, 2); + // Print a message to the LCD + lcd->print("Cursor Blinking"); } void loop() { // Turn off the blinking cursor: - lcd.noBlink(); + lcd->noBlink(); delay(3000); // Turn on the blinking cursor: - lcd.blink(); + lcd->blink(); delay(3000); } diff --git a/examples/CompleteTest/CompleteTest.ino b/examples/CompleteTest/CompleteTest.ino new file mode 100644 index 0000000..2306daa --- /dev/null +++ b/examples/CompleteTest/CompleteTest.ino @@ -0,0 +1,172 @@ +/* + NAME: + Demo sketch for complete printing test of LCD + + DESCRIPTION: + The sketch demonstrates capabalities of the LCD by displaying several + test. + * The sketch is intended preferrably for 16x2 LCD, but can be configured + for 20x4 LCDs just by uncommenting and commenting related sections. + * The sketch is just for demonstration purposes, so that it is not + optimized for memory usage. + + LICENSE: + This program is free software; you can redistribute it and/or modify + it under the terms of the MIT License (MIT). + + CREDITS: + Inspired by the example LCD_Test in the library LCDi2cW + from "4-2-2009 dale@wentztech.com". + + CREDENTIALS: + Author: Libor Gabaj + Version: 1.1.0 + Updated: 04.03.2015 +*/ + +#include + +// LCD address and geometry for LCD 1602 +const byte lcdAddr = 0x27; // Typical address of I2C backpack for 1602 +const byte lcdCols = 20; // Number of characters in a row of display +const byte lcdRows = 4; // Number of lines of display + +// LCD address and geometry for LCD 2004 +//const byte lcdAddr = 0x26; // Typical address of I2C backpack for 2004 +//const byte lcdCols = 16; // Number of characters in a row of display +//const byte lcdRows = 2; // Number of lines of display + +// Initialize library and setting LCD geometry +LiquidCrystal_I2C lcd(lcdAddr, lcdCols, lcdRows); + +// Demo constants +const int testDelayFast = 100; +const int testDelay = 500; // Delay between tests in ms +const int testDelayLong = 1000; +const int demoDelay = 3000; // Delay between demos in ms +const byte demoNumMin = 1; // Range of demo tests +const byte demoNumMax = 255; +const byte charNumMin = 0; // Code of first displayed character +const byte charNumMax = 255; // Code of last displayed character + +// Demo variables +byte col, row; +unsigned int demoNum, charNum; +char buffer[lcdCols + 1]; + +void setup() { + // Initialize LCD + lcd.init(); + lcd.backlight(); // Switch on the backlight LED, if any or wired +} + +void loop() +{ + demoNum = max(demoNumMin, 1); + while(demoNum >= demoNumMin && demoNum <= demoNumMax) { + lcd.clear(); + lcd.noCursor(); + lcd.noBlink(); + sprintf(buffer, "%u.", demoNum); + lcd.print(buffer); + + switch (demoNum) { + case 1: + lcd.print(F("Hello World!")); + break; + case 2: + lcd.print(F("Dash Cursor")); + lcd.setCursor(0, 1); + lcd.cursor(); + break; + case 3: + lcd.print (F("Block Cursor")); + lcd.setCursor(0, 1); + lcd.blink(); + break; + case 4: + lcd.print(F("No Cursor")); + lcd.setCursor(0, 1); + break; + case 5: + for (byte row=0; row < lcdRows; row++) { + lcd.print(F("Line ")); + lcd.print(row); + delay(testDelay); + lcd.setCursor(0, row + 1); + } + break; + case 6: + lcd.print(F("Positions")); + lcd.setCursor(0, 1); + for (byte col = 0; col < lcdCols; col++) { + lcd.write(col%10 + char('0')); + delay(testDelayFast); + } + break; + case 7: + lcd.print(F("Clearing")); + for (byte row = 1; row < lcdRows; row++) { + // Fill row + lcd.setCursor(0, row); + for (byte col = 0; col < lcdCols; col++) { + lcd.write(col%10 + char('0')); + } + delay(testDelayFast); + // Clear row + for (byte i = 0; i < lcdCols / 2; i++) { + lcd.setCursor(lcdCols / 2 - i - 1, row); + lcd.write(' '); + lcd.setCursor(lcdCols / 2 + i, row); + lcd.write(' '); + delay(testDelayFast); + } + } + break; + case 8: + lcd.print(F("Count Mem to 255")); + int current_pos = 1; + for (unsigned int i = 0; i < 256; i++) { + lcd.clear(current_pos); + sprintf(buffer, "%03u 0x%02X %c", i, i, i); + lcd.print(buffer); + if (lcdCols >= 20) { + lcd.print(" B"); + lcd.print(i, BIN); + } + current_pos++; + if (current_pos > 3) + { + current_pos = 1; + } + + delay(testDelayLong); + } + break; + case 9: + lcd.print(F("Characters")); + lcd.cursor(); + charNum = charNumMin; + while(charNum <= charNumMax) { + row = 1; + do { + lcd.clear(row); + col = 0; + lcd.setCursor(col, row); + do { + lcd.write(char(charNum++)); + delay(testDelayFast); + } while(++col < lcdCols && charNum <= charNumMax); + } while(++row < lcdRows && charNum <= charNumMax); + } + lcd.noCursor(); + break; + + default: + demoNum = 0; + continue; + } + delay(demoDelay); + demoNum++; + } +} \ No newline at end of file diff --git a/examples/Cursor/Cursor.ino b/examples/Cursor/Cursor.ino index f187aee..aa5d4b3 100644 --- a/examples/Cursor/Cursor.ino +++ b/examples/Cursor/Cursor.ino @@ -32,6 +32,8 @@ by Tom Igoe modified 7 Nov 2016 by Arturo Guadalupi + modified 2 Feb 2024 + by Vladislav Vanyuk This example code is in the public domain. @@ -40,25 +42,40 @@ */ // include the library code: -#include +#include +//comment to use the normal LCD class +#define LCD_I2C + +LiquidCrystal_Base *lcd; + +#ifndef LCD_I2C // initialize the library by associating any needed LCD interface pin // with the Arduino pin number it is connected to const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; -LiquidCrystal lcd(rs, en, d4, d5, d6, d7); +LiquidCrystal lcd_normal(rs, en, d4, d5, d6, d7); +#else +LiquidCrystal_I2C lcd_i2c(0x27, 20, 4); //(0x27, 16, 2) +#endif void setup() { +#ifndef LCD_I2C + lcd = &lcd_normal; +#else + lcd = &lcd_i2c; +#endif + // set up the LCD's number of columns and rows: - lcd.begin(16, 2); + lcd->begin(16, 2); //crush test: this code example is a modification of the original example to test the LiquidCrystal_I2C class // Print a message to the LCD. - lcd.print("hello, world!"); + lcd->print("Cursor ON/OFF"); } void loop() { // Turn off the cursor: - lcd.noCursor(); + lcd->noCursor(); delay(500); // Turn on the cursor: - lcd.cursor(); + lcd->cursor(); delay(500); } diff --git a/examples/CustomCharacter/CustomCharacter.ino b/examples/CustomCharacter/CustomCharacter.ino deleted file mode 100644 index 128d00e..0000000 --- a/examples/CustomCharacter/CustomCharacter.ino +++ /dev/null @@ -1,152 +0,0 @@ -/* - LiquidCrystal Library - Custom Characters - - Demonstrates how to add custom characters on an LCD display. - The LiquidCrystal library works with all LCD displays that are - compatible with the Hitachi HD44780 driver. There are many of - them out there, and you can usually tell them by the 16-pin interface. - - This sketch prints "I Arduino!" and a little dancing man - to the LCD. - - The circuit: - * LCD RS pin to digital pin 12 - * LCD Enable pin to digital pin 11 - * LCD D4 pin to digital pin 5 - * LCD D5 pin to digital pin 4 - * LCD D6 pin to digital pin 3 - * LCD D7 pin to digital pin 2 - * LCD R/W pin to ground - * 10K potentiometer: - * ends to +5V and ground - * wiper to LCD VO pin (pin 3) - * 10K potentiometer on pin A0 - - created 21 Mar 2011 - by Tom Igoe - modified 11 Nov 2013 - by Scott Fitzgerald - modified 7 Nov 2016 - by Arturo Guadalupi - modified 17 Mar 2020 - by Deepak Khatri - - Based on Adafruit's example at - https://github.com/adafruit/SPI_VFD/blob/master/examples/createChar/createChar.pde - - This example code is in the public domain. - - https://docs.arduino.cc/learn/electronics/lcd-displays#custom-character - https://github.com/arduino-libraries/LiquidCrystal - - - Also useful: - https://maxpromer.github.io/LCD-Character-Creator/ - -*/ - -// include the library code: -#include - -// initialize the library by associating any needed LCD interface pin -// with the Arduino pin number it is connected to -const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; -LiquidCrystal lcd(rs, en, d4, d5, d6, d7); - -// make some custom characters: -byte heart[8] = { - 0b00000, - 0b01010, - 0b11111, - 0b11111, - 0b11111, - 0b01110, - 0b00100, - 0b00000 -}; - -byte smiley[8] = { - 0b00000, - 0b00000, - 0b01010, - 0b00000, - 0b00000, - 0b10001, - 0b01110, - 0b00000 -}; - -byte frownie[8] = { - 0b00000, - 0b00000, - 0b01010, - 0b00000, - 0b00000, - 0b00000, - 0b01110, - 0b10001 -}; - -byte armsDown[8] = { - 0b00100, - 0b01010, - 0b00100, - 0b00100, - 0b01110, - 0b10101, - 0b00100, - 0b01010 -}; - -byte armsUp[8] = { - 0b00100, - 0b01010, - 0b00100, - 0b10101, - 0b01110, - 0b00100, - 0b00100, - 0b01010 -}; - -void setup() { - // initialize LCD and set up the number of columns and rows: - lcd.begin(16, 2); - - // create a new character - lcd.createChar(0, heart); - // create a new character - lcd.createChar(1, smiley); - // create a new character - lcd.createChar(2, frownie); - // create a new character - lcd.createChar(3, armsDown); - // create a new character - lcd.createChar(4, armsUp); - - // set the cursor to the top left - lcd.setCursor(0, 0); - - // Print a message to the LCD. - lcd.print("I "); - lcd.write(byte(0)); // when calling lcd.write() '0' must be cast as a byte - lcd.print(" Arduino! "); - lcd.write((byte)1); - -} - -void loop() { - // read the potentiometer on A0: - int sensorReading = analogRead(A0); - // map the result to 200 - 1000: - int delayTime = map(sensorReading, 0, 1023, 200, 1000); - // set the cursor to the bottom row, 5th position: - lcd.setCursor(4, 1); - // draw the little man, arms down: - lcd.write(3); - delay(delayTime); - lcd.setCursor(4, 1); - // draw him arms up: - lcd.write(4); - delay(delayTime); -} diff --git a/examples/CustomChars_I2C/CustomChars_I2C.ino b/examples/CustomChars_I2C/CustomChars_I2C.ino deleted file mode 100644 index e341000..0000000 --- a/examples/CustomChars_I2C/CustomChars_I2C.ino +++ /dev/null @@ -1,70 +0,0 @@ -//YWROBOT -//Compatible with the Arduino IDE 1.0 -//Library version:1.1 -#include -#include - -#if defined(ARDUINO) && ARDUINO >= 100 -#define printByte(args) write(args); -#else -#define printByte(args) print(args,BYTE); -#endif - -uint8_t bell[8] = {0x4,0xe,0xe,0xe,0x1f,0x0,0x4}; -uint8_t note[8] = {0x2,0x3,0x2,0xe,0x1e,0xc,0x0}; -uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0}; -uint8_t heart[8] = {0x0,0xa,0x1f,0x1f,0xe,0x4,0x0}; -uint8_t duck[8] = {0x0,0xc,0x1d,0xf,0xf,0x6,0x0}; -uint8_t check[8] = {0x0,0x1,0x3,0x16,0x1c,0x8,0x0}; -uint8_t cross[8] = {0x0,0x1b,0xe,0x4,0xe,0x1b,0x0}; -uint8_t retarrow[8] = { 0x1,0x1,0x5,0x9,0x1f,0x8,0x4}; - -LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display - -void setup() -{ - lcd.init(); // initialize the lcd - lcd.backlight(); - - lcd.createChar(0, bell); - lcd.createChar(1, note); - lcd.createChar(2, clock); - lcd.createChar(3, heart); - lcd.createChar(4, duck); - lcd.createChar(5, check); - lcd.createChar(6, cross); - lcd.createChar(7, retarrow); - lcd.home(); - - lcd.print("Hello world..."); - lcd.setCursor(0, 1); - lcd.print(" i "); - lcd.printByte(3); - lcd.print(" arduinos!"); - delay(5000); - displayKeyCodes(); - -} - -// display all keycodes -void displayKeyCodes(void) { - uint8_t i = 0; - while (1) { - lcd.clear(); - lcd.print("Codes 0x"); lcd.print(i, HEX); - lcd.print("-0x"); lcd.print(i+15, HEX); - lcd.setCursor(0, 1); - for (int j=0; j<16; j++) { - lcd.printByte(i+j); - } - i+=16; - - delay(4000); - } -} - -void loop() -{ - -} - diff --git a/examples/HelloWorld/HelloWorld.ino b/examples/HelloWorld/HelloWorld.ino deleted file mode 100644 index 42c51ee..0000000 --- a/examples/HelloWorld/HelloWorld.ino +++ /dev/null @@ -1,66 +0,0 @@ -/* - LiquidCrystal Library - Hello World - - Demonstrates the use of a 16x2 LCD display. The LiquidCrystal - library works with all LCD displays that are compatible with the - Hitachi HD44780 driver. There are many of them out there, and you - can usually tell them by the 16-pin interface. - - This sketch prints "hello, world!" to the LCD - and shows the time. - - The circuit: - * LCD RS pin to digital pin 12 - * LCD Enable pin to digital pin 11 - * LCD D4 pin to digital pin 5 - * LCD D5 pin to digital pin 4 - * LCD D6 pin to digital pin 3 - * LCD D7 pin to digital pin 2 - * LCD R/W pin to ground - * LCD VSS pin to ground - * LCD VCC pin to 5V - * 10K or 100K potentiometer: - * ends to +5V and ground - * wiper to LCD VO pin (pin 3) - - Library originally added 18 Apr 2008 - by David A. Mellis - library modified 5 Jul 2009 - by Limor Fried (http://www.ladyada.net) - example added 9 Jul 2009 - by Tom Igoe - modified 22 Nov 2010 - by Tom Igoe - modified 7 Nov 2016 - by Arturo Guadalupi - - This example code is in the public domain. - - See https://docs.arduino.cc/learn/electronics/lcd-displays#hello-world-example - - Code maintained at https://github.com/arduino-libraries/LiquidCrystal - -*/ - -// include the library code: -#include - -// initialize the library by associating any needed LCD interface pin -// with the Arduino pin number it is connected to -const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; -LiquidCrystal lcd(rs, en, d4, d5, d6, d7); - -void setup() { - // set up the LCD's number of columns and rows: - lcd.begin(16, 2); - // Print a message to the LCD. - lcd.print("hello, world!"); -} - -void loop() { - // set the cursor to column 0, line 1 - // (note: line 1 is the second row, since counting begins with 0): - lcd.setCursor(0, 1); - // print the number of seconds since reset: - lcd.print(millis() / 1000); -} diff --git a/examples/HelloWorld_I2C/HelloWorld_I2C.ino b/examples/HelloWorld_I2C/HelloWorld_I2C.ino deleted file mode 100644 index a6b4cba..0000000 --- a/examples/HelloWorld_I2C/HelloWorld_I2C.ino +++ /dev/null @@ -1,26 +0,0 @@ -//YWROBOT -//Compatible with the Arduino IDE 1.0 -//Library version:1.1 -#include - -LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 for a 16 chars and 2 line display - -void setup() -{ - lcd.init(); // initialize the lcd - // Print a message to the LCD. - lcd.backlight(); - lcd.setCursor(3,0); - lcd.print("Hello, world!"); - lcd.setCursor(2,1); - lcd.print("Ywrobot Arduino!"); - lcd.setCursor(0,2); - lcd.print("Arduino LCM IIC 2004"); - lcd.setCursor(2,3); - lcd.print("Power By Ec-yuan!"); -} - - -void loop() -{ -} diff --git a/examples/Scroll/Scroll.ino b/examples/Scroll/Scroll.ino deleted file mode 100644 index ce53532..0000000 --- a/examples/Scroll/Scroll.ino +++ /dev/null @@ -1,89 +0,0 @@ -/* - LiquidCrystal Library - scrollDisplayLeft() and scrollDisplayRight() - - Demonstrates the use of a 16x2 LCD display. The LiquidCrystal - library works with all LCD displays that are compatible with the - Hitachi HD44780 driver. There are many of them out there, and you - can usually tell them by the 16-pin interface. - - This sketch prints "hello, world!" to the LCD and uses the - scrollDisplayLeft() and scrollDisplayRight() methods to scroll - the text. - - The circuit: - * LCD RS pin to digital pin 12 - * LCD Enable pin to digital pin 11 - * LCD D4 pin to digital pin 5 - * LCD D5 pin to digital pin 4 - * LCD D6 pin to digital pin 3 - * LCD D7 pin to digital pin 2 - * LCD R/W pin to ground - * 10K or 100K potentiometer: - * ends to +5V and ground - * wiper to LCD VO pin (pin 3) - - Library originally added 18 Apr 2008 - by David A. Mellis - library modified 5 Jul 2009 - by Limor Fried (http://www.ladyada.net) - example added 9 Jul 2009 - by Tom Igoe - modified 22 Nov 2010 - by Tom Igoe - modified 7 Nov 2016 - by Arturo Guadalupi - - This example code is in the public domain. - - https://docs.arduino.cc/learn/electronics/lcd-displays#scroll-example - https://github.com/arduino-libraries/LiquidCrystal - -*/ - -// include the library code: -#include - -// initialize the library by associating any needed LCD interface pin -// with the Arduino pin number it is connected to -const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; -LiquidCrystal lcd(rs, en, d4, d5, d6, d7); - -void setup() { - // set up the LCD's number of columns and rows: - lcd.begin(16, 2); - // Print a message to the LCD. - lcd.print("hello, world!"); - delay(1000); -} - -void loop() { - // scroll 13 positions (string length) to the left - // to move it offscreen left: - for (int positionCounter = 0; positionCounter < 13; positionCounter++) { - // scroll one position left: - lcd.scrollDisplayLeft(); - // wait a bit: - delay(150); - } - - // scroll 29 positions (string length + display length) to the right - // to move it offscreen right: - for (int positionCounter = 0; positionCounter < 29; positionCounter++) { - // scroll one position right: - lcd.scrollDisplayRight(); - // wait a bit: - delay(150); - } - - // scroll 16 positions (display length + string length) to the left - // to move it back to center: - for (int positionCounter = 0; positionCounter < 16; positionCounter++) { - // scroll one position left: - lcd.scrollDisplayLeft(); - // wait a bit: - delay(150); - } - - // delay at the end of the full loop: - delay(1000); -} diff --git a/examples/setCursor/setCursor.ino b/examples/setCursor/setCursor.ino deleted file mode 100644 index c6ca2ef..0000000 --- a/examples/setCursor/setCursor.ino +++ /dev/null @@ -1,75 +0,0 @@ -/* - LiquidCrystal Library - setCursor - - Demonstrates the use of a 16x2 LCD display. The LiquidCrystal - library works with all LCD displays that are compatible with the - Hitachi HD44780 driver. There are many of them out there, and you - can usually tell them by the 16-pin interface. - - This sketch prints to all the positions of the LCD using the - setCursor() method: - - The circuit: - * LCD RS pin to digital pin 12 - * LCD Enable pin to digital pin 11 - * LCD D4 pin to digital pin 5 - * LCD D5 pin to digital pin 4 - * LCD D6 pin to digital pin 3 - * LCD D7 pin to digital pin 2 - * LCD R/W pin to ground - * 10K or 100K potentiometer: - * ends to +5V and ground - * wiper to LCD VO pin (pin 3) - - Library originally added 18 Apr 2008 - by David A. Mellis - library modified 5 Jul 2009 - by Limor Fried (http://www.ladyada.net) - example added 9 Jul 2009 - by Tom Igoe - modified 22 Nov 2010 - by Tom Igoe - modified 7 Nov 2016 - by Arturo Guadalupi - - This example code is in the public domain. - - https://docs.arduino.cc/learn/electronics/lcd-displays#cursor - https://github.com/arduino-libraries/LiquidCrystal - -*/ - -// include the library code: -#include - -// initialize the library by associating any needed LCD interface pin -// with the Arduino pin number it is connected to -const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; -LiquidCrystal lcd(rs, en, d4, d5, d6, d7); - -// these constants won't change. But you can change the size of -// your LCD using them: -const int numRows = 2; -const int numCols = 16; - -void setup() { - // set up the LCD's number of columns and rows: - lcd.begin(numCols, numRows); -} - -void loop() { - // loop from ASCII 'a' to ASCII 'z': - for (int thisLetter = 'a'; thisLetter <= 'z'; thisLetter++) { - // loop over the columns: - for (int thisRow = 0; thisRow < numRows; thisRow++) { - // loop over the rows: - for (int thisCol = 0; thisCol < numCols; thisCol++) { - // set the cursor position: - lcd.setCursor(thisCol, thisRow); - // print the letter: - lcd.write(thisLetter); - delay(200); - } - } - } -} diff --git a/keywords.txt b/keywords.txt index 76e4fa8..77a7b92 100644 --- a/keywords.txt +++ b/keywords.txt @@ -48,7 +48,7 @@ printstr KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### - +LIQUIDCRYSTAL_I2C_VERSION LITERAL1 LCD_CLEARDISPLAY LITERAL1 LCD_RETURNHOME LITERAL1 LCD_ENTRYMODESET LITERAL1 diff --git a/src/LiquidCrystal_Base.h b/src/LiquidCrystal_Base.h index 394af8d..e579594 100644 --- a/src/LiquidCrystal_Base.h +++ b/src/LiquidCrystal_Base.h @@ -1,96 +1,11 @@ -#ifndef LiquidCrystal_Base_h -#define LiquidCrystal_Base_h -#include +#pragma once #include -#include -// commands -#define LCD_CLEARDISPLAY 0x01 -#define LCD_RETURNHOME 0x02 -#define LCD_ENTRYMODESET 0x04 -#define LCD_DISPLAYCONTROL 0x08 -#define LCD_CURSORSHIFT 0x10 -#define LCD_FUNCTIONSET 0x20 -#define LCD_SETCGRAMADDR 0x40 -#define LCD_SETDDRAMADDR 0x80 +#define LIQUIDCRYSTAL_BASE_VERSION "1.2.0" -// flags for display entry mode -#define LCD_ENTRYRIGHT 0x00 -#define LCD_ENTRYLEFT 0x02 -#define LCD_ENTRYSHIFTINCREMENT 0x01 -#define LCD_ENTRYSHIFTDECREMENT 0x00 +#include "coreLCD/LCD_defs.h" +#include "coreLCD/LiquidCrystal_Base.h" +#include "coreLCD/LiquidCrystal.h" +#include "coreLCD/LiquidCrystal_I2C.h" -// flags for display on/off control -#define LCD_DISPLAYON 0x04 -#define LCD_DISPLAYOFF 0x00 -#define LCD_CURSORON 0x02 -#define LCD_CURSOROFF 0x00 -#define LCD_BLINKON 0x01 -#define LCD_BLINKOFF 0x00 - -// flags for display/cursor shift -#define LCD_DISPLAYMOVE 0x08 -#define LCD_CURSORMOVE 0x00 -#define LCD_MOVERIGHT 0x04 -#define LCD_MOVELEFT 0x00 - -// flags for function set -#define LCD_8BITMODE 0x10 -#define LCD_4BITMODE 0x00 -#define LCD_2LINE 0x08 -#define LCD_1LINE 0x00 -#define LCD_5x10DOTS 0x04 -#define LCD_5x8DOTS 0x00 - -#define LCD_DEFAULT_COLS 20 -#define LCD_DEFAULT_ROWS 4 - -#define COMMAND 0 -#define DATA 1 -#define INIT_MODE 2 - -class LiquidCrystal_Base : public Print -{ -public: - virtual void init(uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize = LCD_5x8DOTS); - virtual void init(uint8_t mode = LCD_4BITMODE); - virtual void begin(); - virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) = 0; - void clear(); - void home(); - void noDisplay(); - void display(); - void noBlink(); - void blink(); - void noCursor(); - void cursor(); - void scrollDisplayLeft(); - void scrollDisplayRight(); - void leftToRight(); - void rightToLeft(); - void autoscroll(); - void noAutoscroll(); - void createChar(uint8_t, uint8_t[]); - void setCursor(uint8_t col, uint8_t row, uint8_t offsets[]); - void printstr(const char[]); - - virtual void setCursor(uint8_t col, uint8_t row); - virtual void command(uint8_t value); - virtual size_t write(uint8_t); //=0 - virtual void write4bits(uint8_t value) = 0; - // virtual void write8bits(uint8_t value); - virtual void send(uint8_t value, uint8_t mode) = 0; - // using Print::write; - uint8_t _displayfunction; - uint8_t _displaycontrol; - uint8_t _displaymode; - - uint8_t _cols = LCD_DEFAULT_COLS; - uint8_t _rows = LCD_DEFAULT_ROWS; - -private: - //virtual void send(uint8_t, uint8_t); -}; - -#endif \ No newline at end of file diff --git a/src/coreLCD/LCD_defs.h b/src/coreLCD/LCD_defs.h new file mode 100644 index 0000000..353d3eb --- /dev/null +++ b/src/coreLCD/LCD_defs.h @@ -0,0 +1,54 @@ +#ifndef LCD_DEFS_H +#define LCD_DEFS_H + +// commands +#define LCD_CLEARDISPLAY 0x01 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_FUNCTIONSET 0x20 +#define LCD_SETCGRAMADDR 0x40 +#define LCD_SETDDRAMADDR 0x80 + +// flags for display entry mode +#define LCD_ENTRYRIGHT 0x00 +#define LCD_ENTRYLEFT 0x02 +#define LCD_ENTRYSHIFTINCREMENT 0x01 +#define LCD_ENTRYSHIFTDECREMENT 0x00 + +// flags for display on/off control +#define LCD_DISPLAYON 0x04 +#define LCD_DISPLAYOFF 0x00 +#define LCD_CURSORON 0x02 +#define LCD_CURSOROFF 0x00 +#define LCD_BLINKON 0x01 +#define LCD_BLINKOFF 0x00 + +// flags for display/cursor shift +#define LCD_DISPLAYMOVE 0x08 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 + +// flags for function set +#define LCD_8BITMODE 0x10 +#define LCD_4BITMODE 0x00 +#define LCD_2LINE 0x08 +#define LCD_1LINE 0x00 +#define LCD_5x10DOTS 0x04 +#define LCD_5x8DOTS 0x00 + +#define COMMAND 0 +#define DATA 1 +#define INIT_MODE 2 + + +#if (ARDUINO < 100) +#define SIZE_OF_ROW_OFFSETS (int)(sizeof(_row_offsets) / sizeof(*_row_offsets)) +#else +#define SIZE_OF_ROW_OFFSETS (size_t)(sizeof(_row_offsets) / sizeof(*_row_offsets)) +#endif + + +#endif \ No newline at end of file diff --git a/src/LiquidCrystal.cpp b/src/coreLCD/LiquidCrystal.cpp similarity index 65% rename from src/LiquidCrystal.cpp rename to src/coreLCD/LiquidCrystal.cpp index 42a3cbe..13d4b76 100644 --- a/src/LiquidCrystal.cpp +++ b/src/coreLCD/LiquidCrystal.cpp @@ -5,31 +5,47 @@ LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, - uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_8BITMODE) { - init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); + LiquidCrystal_Base::init(cols, rows, charsize); //1 + init(mode, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); } LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, - uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_8BITMODE) { - init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); + LiquidCrystal_Base::init(cols, rows, charsize); + init(mode, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); } LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, - uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) { - init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); + LiquidCrystal_Base::init(cols, rows, charsize); + init(mode, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); } LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, - uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) +{ + LiquidCrystal_Base::init(cols, rows, charsize); + init(mode, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); +} + +LiquidCrystal::~LiquidCrystal() { - init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); } -void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, +void LiquidCrystal::init(uint8_t mode, uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { @@ -46,18 +62,22 @@ void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t en _data_pins[6] = d6; _data_pins[7] = d7; - if (fourbitmode) - _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; - else - _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; + LiquidCrystal_Base::init(mode); //2 } -void LiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) +void LiquidCrystal::init(uint8_t lcd_cols = LCD_DEFAULT_COLS, uint8_t lcd_rows=LCD_DEFAULT_ROWS, uint8_t charsize = LCD_5x8DOTS) { - LiquidCrystal_Base::init(cols, rows, charsize); + LiquidCrystal_Base::init(lcd_cols, lcd_rows, charsize); + + LiquidCrystal_Base::init(getMode() ? LCD_8BITMODE : LCD_4BITMODE); + + setRowOffsets(0x00, 0x40, 0x00 + lcd_cols, 0x40 + lcd_cols); - setRowOffsets(0x00, 0x40, 0x00 + cols, 0x40 + cols); + begin(); +} +void LiquidCrystal::begin() +{ pinMode(_rs_pin, OUTPUT); // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# if (_rw_pin != 255) @@ -67,7 +87,7 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8 pinMode(_enable_pin, OUTPUT); // Do these once, instead of every time a character is drawn for speed reasons. - for (int i = 0; i < ((_displayfunction & LCD_8BITMODE) ? 8 : 4); ++i) + for (int i = 0; i < (getMode() ? 8 : 4); ++i) { pinMode(_data_pins[i], OUTPUT); } @@ -75,7 +95,7 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! // according to datasheet, we need at least 40 ms after power rises above 2.7 V // before sending commands. Arduino can turn on way before 4.5 V so we'll wait 50 - delayMicroseconds(50000); + delayMicroseconds(5000); // Now we pull both RS and R/W low to begin commands digitalWrite(_rs_pin, LOW); digitalWrite(_enable_pin, LOW); @@ -84,16 +104,16 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8 digitalWrite(_rw_pin, LOW); } - // uint8_t _mode = LCD_4BITMODE; - // if ( _displayfunction & LCD_8BITMODE) - // { - // _mode = LCD_8BITMODE; - // } - - //LiquidCrystal_Base::init(_mode); LiquidCrystal_Base::begin(); } +void LiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) +{ + LiquidCrystal_Base::init(cols, rows, charsize); + setRowOffsets(0x00, 0x40, 0x00 + cols, 0x40 + cols); + begin(); +} + void LiquidCrystal::setRowOffsets(int row0, int row1, int row2, int row3) { _row_offsets[0] = row0; @@ -106,7 +126,7 @@ void LiquidCrystal::setRowOffsets(int row0, int row1, int row2, int row3) void LiquidCrystal::setCursor(uint8_t col, uint8_t row) { - const size_t max_lines = sizeof(_row_offsets) / sizeof(*_row_offsets); + const size_t max_lines = SIZE_OF_ROW_OFFSETS; if (row >= max_lines) { row = max_lines - 1; // we count rows starting w/ 0 @@ -115,20 +135,6 @@ void LiquidCrystal::setCursor(uint8_t col, uint8_t row) LiquidCrystal_Base::setCursor(col, row, _row_offsets); } -/*********** mid level commands, for sending data/cmds */ - -void LiquidCrystal::command(uint8_t value) -{ - send(value, COMMAND); -} - -//todo move write to LiquidCrystal_Base - -inline size_t LiquidCrystal::write(uint8_t value) -{ - send(value, DATA); - return 1; // assume success -} /************ low level data pushing commands **********/ @@ -149,7 +155,8 @@ void LiquidCrystal::send(uint8_t value, uint8_t mode) digitalWrite(_rw_pin, LOW); } - if (_displayfunction & LCD_8BITMODE) + // if (_displayfunction & LCD_8BITMODE) + if (getMode()) { write8bits(value); } diff --git a/src/LiquidCrystal.h b/src/coreLCD/LiquidCrystal.h similarity index 51% rename from src/LiquidCrystal.h rename to src/coreLCD/LiquidCrystal.h index 4f2a709..b0ecd17 100644 --- a/src/LiquidCrystal.h +++ b/src/coreLCD/LiquidCrystal.h @@ -8,27 +8,41 @@ class LiquidCrystal : public LiquidCrystal_Base public: LiquidCrystal(uint8_t rs, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, - uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_8BITMODE); + LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, - uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS,uint8_t mode = LCD_8BITMODE); + LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, - uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE); + LiquidCrystal(uint8_t rs, uint8_t enable, - uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); + uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, + uint8_t cols=LCD_DEFAULT_COLS, uint8_t rows=LCD_DEFAULT_ROWS, + uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE); + - virtual void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, + ~LiquidCrystal(); + virtual void init(uint8_t lcd_cols = LCD_DEFAULT_COLS, uint8_t lcd_rows=LCD_DEFAULT_ROWS, uint8_t charsize = LCD_5x8DOTS); + virtual void init(uint8_t mode, uint8_t rs, uint8_t rw, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); + virtual void begin(); + virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE); void setCursor(uint8_t col, uint8_t row); void setRowOffsets(int row1, int row2, int row3, int row4); - virtual size_t write(uint8_t value); - virtual void command(uint8_t value); virtual void write4bits(uint8_t value); using Print::write; @@ -42,8 +56,8 @@ class LiquidCrystal : public LiquidCrystal_Base uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD. uint8_t _enable_pin; // activated by a HIGH pulse. uint8_t _data_pins[8]; - // uint8_t _initialized; uint8_t _row_offsets[4]; + // uint8_t _initialized; }; #endif diff --git a/src/LiquidCrystal_Base.cpp b/src/coreLCD/LiquidCrystal_Base.cpp similarity index 73% rename from src/LiquidCrystal_Base.cpp rename to src/coreLCD/LiquidCrystal_Base.cpp index e5eefa7..c8ed2ac 100644 --- a/src/LiquidCrystal_Base.cpp +++ b/src/coreLCD/LiquidCrystal_Base.cpp @@ -1,22 +1,20 @@ #include "LiquidCrystal_Base.h" -#if (defined TYPE_LCD) && (defined TYPE_LCD_I2C) -#error "Only one type of LCD can be defined" -#endif - void LiquidCrystal_Base::init(uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize) { _cols = lcd_cols; _rows = lcd_rows; + _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; + if (_rows > 1) { - _displayfunction |= LCD_2LINE; + setBitFlag(_displayfunction, LCD_2LINE); } if ((charsize != LCD_5x8DOTS) && (_rows == 1)) { - _displayfunction |= LCD_5x10DOTS; + setBitFlag(_displayfunction, LCD_5x10DOTS); } } @@ -24,24 +22,18 @@ void LiquidCrystal_Base::init(uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsi void LiquidCrystal_Base::init(uint8_t mode = LCD_4BITMODE) { uint8_t charsize = LCD_5x8DOTS; - if (_displayfunction & LCD_5x10DOTS) + + // if (_displayfunction & LCD_5x10DOTS) + if(checkBitFlag(_displayfunction, LCD_5x10DOTS)) { charsize = LCD_5x10DOTS; } - if (mode == LCD_8BITMODE) - { - _displayfunction = LCD_8BITMODE | LCD_1LINE | charsize; - } - else - { - // we default to 4 bit mode - _displayfunction = LCD_4BITMODE | LCD_1LINE | charsize; - } + _displayfunction = mode | LCD_1LINE | charsize; if (_rows > 1) { - _displayfunction |= LCD_2LINE; + setBitFlag(_displayfunction, LCD_2LINE); } // _displayfunction = mode | ((_rows > 1) ? LCD_2LINE : LCD_1LINE) | charsize; @@ -51,7 +43,8 @@ void LiquidCrystal_Base::init(uint8_t mode = LCD_4BITMODE) void LiquidCrystal_Base::begin() { // put the LCD into 4 bit or 8 bit mode - if (! (_displayfunction & LCD_8BITMODE)) + // if (! (_displayfunction & LCD_8BITMODE)) + if(!checkBitFlag(_displayfunction, LCD_8BITMODE)) { // this is according to the Hitachi HD44780 datasheet @@ -97,7 +90,7 @@ void LiquidCrystal_Base::begin() _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; display(); clear(); - + // Initialize to default text direction (for romance languages) _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; // set the entry mode @@ -113,6 +106,19 @@ void LiquidCrystal_Base::clear() delayMicroseconds(2000); // this command takes a long time! } +// Clear particular segment of a row +void LiquidCrystal_Base::clear(uint8_t rowStart, uint8_t colStart, uint8_t colCnt) { + // Maintain input parameters + rowStart = constrain(rowStart, 0, _rows - 1); + colStart = constrain(colStart, 0, _cols - 1); + colCnt = constrain(colCnt, 0, _cols - colStart); + // Clear segment + setCursor(colStart, rowStart); + for (uint8_t i = 0; i < colCnt; i++) write(' '); + // Go to segment start + setCursor(colStart, rowStart); +} + void LiquidCrystal_Base::home() { command(LCD_RETURNHOME); // set cursor position to zero @@ -121,36 +127,36 @@ void LiquidCrystal_Base::home() // Turn the display on/off (quickly) void LiquidCrystal_Base::noDisplay() { - _displaycontrol &= ~LCD_DISPLAYON; + clearBitFlag(_displaycontrol, LCD_DISPLAYON); command(LCD_DISPLAYCONTROL | _displaycontrol); } void LiquidCrystal_Base::display() { - _displaycontrol |= LCD_DISPLAYON; + setBitFlag(_displaycontrol, LCD_DISPLAYON); command(LCD_DISPLAYCONTROL | _displaycontrol); } // Turns the underline cursor on/off void LiquidCrystal_Base::noCursor() { - _displaycontrol &= ~LCD_CURSORON; + clearBitFlag(_displaycontrol, LCD_CURSORON); command(LCD_DISPLAYCONTROL | _displaycontrol); } void LiquidCrystal_Base::cursor() { - _displaycontrol |= LCD_CURSORON; + setBitFlag(_displaycontrol, LCD_CURSORON); command(LCD_DISPLAYCONTROL | _displaycontrol); } // Turn on and off the blinking cursor void LiquidCrystal_Base::noBlink() { - _displaycontrol &= ~LCD_BLINKON; + clearBitFlag(_displaycontrol, LCD_BLINKON); command(LCD_DISPLAYCONTROL | _displaycontrol); } void LiquidCrystal_Base::blink() { - _displaycontrol |= LCD_BLINKON; + setBitFlag(_displaycontrol, LCD_BLINKON); command(LCD_DISPLAYCONTROL | _displaycontrol); } @@ -167,28 +173,28 @@ void LiquidCrystal_Base::scrollDisplayRight(void) // This is for text that flows Left to Right void LiquidCrystal_Base::leftToRight(void) { - _displaymode |= LCD_ENTRYLEFT; + setBitFlag(_displaymode, LCD_ENTRYLEFT); command(LCD_ENTRYMODESET | _displaymode); } // This is for text that flows Right to Left void LiquidCrystal_Base::rightToLeft(void) { - _displaymode &= ~LCD_ENTRYLEFT; + clearBitFlag(_displaymode, LCD_ENTRYLEFT); command(LCD_ENTRYMODESET | _displaymode); } // This will 'right justify' text from the cursor void LiquidCrystal_Base::autoscroll(void) { - _displaymode |= LCD_ENTRYSHIFTINCREMENT; + setBitFlag(_displaymode, LCD_ENTRYSHIFTINCREMENT); command(LCD_ENTRYMODESET | _displaymode); } // This will 'left justify' text from the cursor void LiquidCrystal_Base::noAutoscroll(void) { - _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; + clearBitFlag(_displaymode, LCD_ENTRYSHIFTINCREMENT); command(LCD_ENTRYMODESET | _displaymode); } @@ -220,7 +226,15 @@ void LiquidCrystal_Base::printstr(const char c[]) print(c); } -// inline void LiquidCrystal_Base::command(uint8_t value) -// { -// send(value, COMMAND); -// } \ No newline at end of file +/*********** mid level commands, for sending data/cmds */ + +void LiquidCrystal_Base::command(uint8_t value) +{ + this->send(value, COMMAND); +} + +size_t LiquidCrystal_Base::write(uint8_t value) +{ + this->send(value, DATA); + return 1; // assume success +} \ No newline at end of file diff --git a/src/coreLCD/LiquidCrystal_Base.h b/src/coreLCD/LiquidCrystal_Base.h new file mode 100644 index 0000000..14a9d7c --- /dev/null +++ b/src/coreLCD/LiquidCrystal_Base.h @@ -0,0 +1,138 @@ +#ifndef LiquidCrystal_Base_h +#define LiquidCrystal_Base_h + +#if (ARDUINO < 100) +#include +#else +#include +#endif + +#ifdef __AVR__ + #include +// #define FAST_MODE +#endif + +#include +#include + +#include "LCD_defs.h" + +#define LCD_DEFAULT_COLS 16 +#define LCD_DEFAULT_ROWS 2 + +class LiquidCrystal_Base : public Print +{ +public: + ~LiquidCrystal_Base() = default; + virtual void init(uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize = LCD_5x8DOTS); + virtual void init(uint8_t mode = LCD_4BITMODE); + virtual void begin(); +#if (ARDUINO < 100) + virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE){}; +#else + virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) = 0; +#endif + + void clear(); + void clear(uint8_t rowStart, uint8_t colStart = 0, uint8_t colCnt = 255); + void home(); + void noDisplay(); + void display(); + // void display(lcd_mode_t mode); + void noBlink(); + void blink(); + void noCursor(); + void cursor(); + void scrollDisplayLeft(); + void scrollDisplayRight(); + void leftToRight(); + void rightToLeft(); + void autoscroll(); + void noAutoscroll(); + void createChar(uint8_t, uint8_t[]); +#ifdef __AVR__ + void createChar(uint8_t location, const char *charmap); +#endif + void setCursor(uint8_t col, uint8_t row, uint8_t offsets[]); + void printstr(const char[]); + + virtual void setCursor(uint8_t col, uint8_t row); + virtual void command(uint8_t value); + +#if (ARDUINO < 100) + virtual void write(uint8_t value); +#else + virtual size_t write(uint8_t value); +#endif + +#if (ARDUINO < 100) + virtual void write4bits(uint8_t value){}; + virtual void send(uint8_t value, uint8_t mode){}; +#else + virtual void write4bits(uint8_t value) = 0; + virtual void send(uint8_t value, uint8_t mode) = 0; +#endif + + bool getMode() { return readBitFlag(_displayfunction, LCD_8BITMODE); } + +protected: + + uint8_t _cols = LCD_DEFAULT_COLS; + uint8_t _rows = LCD_DEFAULT_ROWS; + + uint8_t _displayfunction; + uint8_t _displaycontrol; + uint8_t _displaymode; + + ////Unsupported API functions (not implemented in this library) + // void setContrast(uint8_t new_val); + // void setDelay(int,int); //for asynchroneous, no delay funcrion + // uint8_t init_bargraph(uint8_t graphtype); + // void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); + // void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); + + inline uint8_t status() { return _displayfunction; } + inline void on(){ display(); } + inline void off() { noDisplay(); } + inline void blink_on() { blink(); } + inline void blink_off() { noBlink(); } + inline void cursor_on() { cursor(); } + inline void cursor_off() { noCursor(); } + inline void printLeft() { rightToLeft(); } + inline void printRight() { leftToRight(); } + inline void shiftIncrement() { autoscroll(); } + inline void shiftDecrement() { noAutoscroll(); } + // virtual void write8bits(uint8_t value); + // void writeNbits(uint8_t value, uint8_t numBits); +private: + inline void setBitFlag(uint8_t& flagsGroup, const uint8_t& bitToSet) __attribute__((always_inline)) { + flagsGroup |= bitToSet; + } + + inline void clearBitFlag(uint8_t& flagsGroup, const uint8_t& bitToClear) __attribute__((always_inline)) { + flagsGroup &= ~bitToClear; + } + + inline bool readBitFlag(uint8_t& flagsGroup, const uint8_t& bitToRead) __attribute__((always_inline)) { + return flagsGroup & bitToRead; + } + + inline void writeBitFlag(uint8_t& flagsGroup, const uint8_t& bitToSet, const bool& flagValue) __attribute__((always_inline)) { + if (flagValue) setBitFlag(flagsGroup, bitToSet); + else clearBitFlag(flagsGroup, bitToSet); + } + + inline bool checkBitFlag(uint8_t& flagsGroup, const uint8_t& bitToCheck) __attribute__((always_inline)) { + return (flagsGroup & (1 << bitToCheck)) ? true : false; + } + +}; + +#endif + +// #define LCD_BRIGHT100 0x00 +// #define LCD_BRIGHT75 0x01 +// #define LCD_BRIGHT50 0x02 +// #define LCD_BRIGHT25 0x03 +//void bright (uint8_t brg) { command (LCD_FUNCTIONSET | _displayfunction | brg); } +// lcd.print(F("Cursor")); diff --git a/src/LiquidCrystal_I2C.cpp b/src/coreLCD/LiquidCrystal_I2C.cpp similarity index 86% rename from src/LiquidCrystal_I2C.cpp rename to src/coreLCD/LiquidCrystal_I2C.cpp index c815002..b241774 100644 --- a/src/LiquidCrystal_I2C.cpp +++ b/src/coreLCD/LiquidCrystal_I2C.cpp @@ -7,15 +7,20 @@ LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t this->init(lcd_addr, lcd_cols, lcd_rows, charsize); } +LiquidCrystal_I2C::~LiquidCrystal_I2C() +{ +} + +//calls firts void LiquidCrystal_I2C::init(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize = LCD_5x8DOTS) { _addr = lcd_addr; _backlightval = LCD_NOBACKLIGHT; - _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; //todo move LiquidCrystal_Base::init(lcd_cols, lcd_rows, charsize); } +//calls second void LiquidCrystal_I2C::init(uint8_t mode = LCD_4BITMODE) { _backlightval = LCD_NOBACKLIGHT; @@ -23,6 +28,7 @@ void LiquidCrystal_I2C::init(uint8_t mode = LCD_4BITMODE) begin(); } +//last void LiquidCrystal_I2C::begin() { Wire.begin(); @@ -30,6 +36,10 @@ void LiquidCrystal_I2C::begin() // according to datasheet, we need at least 40ms after power rises above 2.7V // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 delay(50); + + // wire->beginTransmission(_LCDSlaveAddresI2C); + // I2CReturnCode = wire->endTransmission(); + // if (I2CReturnCode!= 0) // Now we pull both RS and R/W low to begin commands expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1) @@ -39,6 +49,7 @@ void LiquidCrystal_I2C::begin() backlight(); } +//calls 1 and 2 inits void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS, uint8_t mode = LCD_4BITMODE) { init(_addr, cols, rows, charsize); @@ -71,19 +82,6 @@ bool LiquidCrystal_I2C::getBacklight() return _backlightval == LCD_BACKLIGHT; } -/*********** mid level commands, for sending data/cmds */ - -void LiquidCrystal_I2C::command(uint8_t value) -{ - send(value, COMMAND); -} - -//todo move write to LiquidCrystal_Base -inline size_t LiquidCrystal_I2C::write(uint8_t value) -{ - send(value, DATA); - return 1; -} /************ low level data pushing commands **********/ @@ -119,9 +117,17 @@ void LiquidCrystal_I2C::write4bits(uint8_t value) void LiquidCrystal_I2C::expanderWrite(uint8_t _data) { + uint8_t status = 0; + Wire.beginTransmission(_addr); - Wire.write(_data | _backlightval); // Wire.write((int)(_data) | _backlightval); - Wire.endTransmission(); +#if (ARDUINO < 100) + Wire.send(_data | _backlightval); +#else + Wire.write(_data | _backlightval); // Wire.write((int)(_data) | _backlightval); +#endif + status = Wire.endTransmission(); + // return ((status == 0)); + // return (ret == 0) ? true : false; //false if error } void LiquidCrystal_I2C::pulseEnable(uint8_t _data) diff --git a/src/LiquidCrystal_I2C.h b/src/coreLCD/LiquidCrystal_I2C.h similarity index 61% rename from src/LiquidCrystal_I2C.h rename to src/coreLCD/LiquidCrystal_I2C.h index 2f19beb..bd9ef23 100644 --- a/src/LiquidCrystal_I2C.h +++ b/src/coreLCD/LiquidCrystal_I2C.h @@ -1,7 +1,11 @@ #ifndef LIQUID_CRYSTAL_I2C_h #define LIQUID_CRYSTAL_I2C_h +#if (ARDUINO < 10000) +#include <../Wire/Wire.h> +#else #include +#endif #include "LiquidCrystal_Base.h" // flags for backlight control @@ -18,8 +22,10 @@ class LiquidCrystal_I2C : public LiquidCrystal_Base { public: LiquidCrystal_I2C()=default; - LiquidCrystal_I2C(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize = LCD_5x8DOTS); + + ~LiquidCrystal_I2C(); + virtual void init(uint8_t mode = LCD_4BITMODE); virtual void init(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize = LCD_5x8DOTS); virtual void begin(); @@ -35,37 +41,13 @@ class LiquidCrystal_I2C : public LiquidCrystal_Base { void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar() void printstr(const char[]); - // inline void blink_on() { blink(); } - // inline void blink_off() { noBlink(); } - // inline void cursor_on() { cursor(); } - // inline void cursor_off() { noCursor(); } - - // inline void printLeft() { rightToLeft(); } - // inline void printRight() { leftToRight(); } - // inline void shiftIncrement() { autoscroll(); } - // inline void shiftDecrement() { noAutoscroll(); } - - virtual size_t write(uint8_t value); - virtual void command(uint8_t value); virtual void write4bits(uint8_t value); - //using Print::write; -protected: - ////Unsupported API functions (not implemented in this library) - // uint8_t status(); - // void setContrast(uint8_t new_val); - // uint8_t keypad(); - // void setDelay(int,int); - // void on(); - // void off(); - // uint8_t init_bargraph(uint8_t graphtype); - // void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); - // void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); private: void send(uint8_t value, uint8_t mode); void expanderWrite(uint8_t _data); void pulseEnable(uint8_t _data); - uint8_t _addr; + uint8_t _addr = LCD_DEFAULT_ADDR; uint8_t _backlightval = LCD_NOBACKLIGHT; };