diff --git a/README.md b/README.md index 13726f8..ab2d77e 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ SparkFun SerLCD Library ![SparkFun SerLCD](https://cdn.sparkfun.com//assets/parts/1/1/9/2/7/14074-SparkFun_20x4_SerLCD_-_Black_on_RGB_3.3V-05.jpg) -[*SparkX 20x4 SerLCD - Black on RGB 3.3V (LCD-14074)*](https://www.sparkfun.com/products/14074) +[*SparkFun 20x4 SerLCD - Black on RGB 3.3V (LCD-14074)*](https://www.sparkfun.com/products/14074) -The SparkFun SerLCD is an AVR-based, serial enabled LCD that provides a simple and cost effective solution for adding a 20x4 Black on RGB Liquid Crystal Display into your project. We’ve overhauled the design to include an ATMega328P that handles all of the screen control, meaning a backpack is no longer needed! This display can now accept three different types of communication protocols: serial, I2C, and SPI. This simplifies the number of wires needed and allows your project to display all kinds of text and numbers. +The SparkFun SerLCD is an AVR-based, serial enabled LCD that provides a simple and cost effective solution for adding a 20x4 Black on RGB Liquid Crystal Display into your project. We’ve overhauled the design to include an ATmega328P that handles all of the screen control, meaning a backpack is no longer needed! This display can now accept three different types of communication protocols: serial, I2C, and SPI. This simplifies the number of wires needed and allows your project to display all kinds of text and numbers. The SerLCD is Qwiic compatible! We recommend adding a [Qwiic Adapter](https://www.sparkfun.com/products/14495) to the back of the SerLCD to get it onto the Qwiic bus. -The on-board ATMega328P AVR microcontroller utilizes 11.0592 MHz crystal for greater communication accuracy with adjustable baud rates of 1200 through 1000000 but is default set at 9600. The firmware for this SerLCD is fully opensource and allows for any customizations you may need. +The on-board ATmega328P AVR microcontroller utilizes 11.0592 MHz crystal for greater communication accuracy with adjustable baud rates of 1200 through 1000000 but is default set at 9600. The firmware for this SerLCD is fully opensource and allows for any customizations you may need. Library written by Gaston Williams and Nathan Seidle ([SparkFun](http://www.sparkfun.com)). diff --git a/examples/Example1-HelloWorld/Example1-HelloWorld.ino b/examples/Example1-HelloWorld/Example1-HelloWorld.ino index bbcf98f..90d5084 100644 --- a/examples/Example1-HelloWorld/Example1-HelloWorld.ino +++ b/examples/Example1-HelloWorld/Example1-HelloWorld.ino @@ -39,7 +39,12 @@ SerLCD lcd; // Initialize the library with default I2C address 0x72 void setup() { Wire.begin(); - lcd.begin(Wire); //Set up the LCD for I2C + lcd.begin(Wire); //Set up the LCD for I2C communication + + lcd.setBacklight(255, 255, 255); //Set backlight to bright white + lcd.setContrast(5); //Set contrast. Lower to 0 for higher contrast. + + lcd.clear(); //Clear the display - this moves the cursor to home position as well lcd.print("Hello, World!"); } @@ -50,4 +55,3 @@ void loop() { // Print the number of seconds since reset: lcd.print(millis() / 1000); } - diff --git a/examples/Example15-MessageEnable/Example15-MessageEnable.ino b/examples/Example15-MessageEnable/Example15-MessageEnable.ino new file mode 100644 index 0000000..5601fec --- /dev/null +++ b/examples/Example15-MessageEnable/Example15-MessageEnable.ino @@ -0,0 +1,69 @@ +/* + SerLCD Library - Control when system message are displayed + Nathan Seidle - February 16, 2019 + + This sketch demonstrates how to turn off the system messages displayed when + the user changes a setting. For instance 'Contrast: 5' or 'UART: 57600' is + no longer displays. + + Note - This example and the disableSystemMessages and enableSystemMessages() + commands are only supported on SerLCD v1.2 and above. + + The circuit: + SparkFun RGB OpenLCD Serial display connected through + a SparkFun Qwiic adpater to an Ardruino with a + Qwiic shield or a SparkFun Blackboard with Qwiic built in. + + The Qwiic adapter should be attached to the display as follows: + Display / Qwiic Cable Color + GND / Black + RAW / Red + SDA / Blue + SCL / Yellow + + Note: If you connect directly to a 5V Arduino instead, you *MUST* use + a level-shifter to convert the i2c voltage levels down to 3.3V for the display. + + This code is based on the LiquidCrystal code originally by David A. Mellis + and the OpenLCD code by Nathan Seidle at SparkFun. + + License: This example code is in the public domain. + + More info on Qwiic here: https://www.sparkfun.com/qwiic + + AVR-Based Serial Enabled LCDs Hookup Guide + https://learn.sparkfun.com/tutorials/avr-based-serial-enabled-lcds-hookup-guide +*/ + +#include + +#include //Click here to get the library: http://librarymanager/All#SparkFun_SerLCD +SerLCD lcd; // Initialize the library with default I2C address 0x72 + +void setup() { + Wire.begin(); + + lcd.begin(Wire); //Set up the LCD for I2C communication + + lcd.setBacklight(255, 255, 255); //Set backlight to bright white + lcd.setContrast(5); //Set contrast. Lower to 0 for higher contrast. + + lcd.clear(); //Clear the display - this moves the cursor to home position as well + lcd.print("Hello, World!"); + + lcd.disableSystemMessages(); //Now whenever you change a system setting like UART, or Contrast + //SerLCD will not display the setting. This makes changing the setting faster, and also + //invisible to the user. + + //lcd.enableSystemMessages(); //This will re-enable the printing of system messages + + lcd.setContrast(0); +} + +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/Example16-SetSplash/Example16-SetSplash.ino b/examples/Example16-SetSplash/Example16-SetSplash.ino new file mode 100644 index 0000000..4a302a3 --- /dev/null +++ b/examples/Example16-SetSplash/Example16-SetSplash.ino @@ -0,0 +1,70 @@ +/* + SerLCD Library - Control splash and system message + Nathan Seidle - February 16, 2019 + + This sketch demonstrates how to create your own custom splash screen. + + This is done by first writing the text you want as your splash to the display, + then 'saving' it as a splash screen. + + You can also disable or enable the displaying of the splash screen. + + Note - The disableSplash() and enableSplash() commands + are only supported on SerLCD v1.2 and above. But you can still use the + toggle splash command (Ctrl+i) to enable/disable the splash. + + The circuit: + SparkFun RGB OpenLCD Serial display connected through + a SparkFun Qwiic adpater to an Ardruino with a + Qwiic shield or a SparkFun Blackboard with Qwiic built in. + + The Qwiic adapter should be attached to the display as follows: + Display / Qwiic Cable Color + GND / Black + RAW / Red + SDA / Blue + SCL / Yellow + + Note: If you connect directly to a 5V Arduino instead, you *MUST* use + a level-shifter to convert the i2c voltage levels down to 3.3V for the display. + + This code is based on the LiquidCrystal code originally by David A. Mellis + and the OpenLCD code by Nathan Seidle at SparkFun. + + License: This example code is in the public domain. + + More info on Qwiic here: https://www.sparkfun.com/qwiic + + AVR-Based Serial Enabled LCDs Hookup Guide + https://learn.sparkfun.com/tutorials/avr-based-serial-enabled-lcds-hookup-guide +*/ + +#include + +#include //Click here to get the library: http://librarymanager/All#SparkFun_SerLCD +SerLCD lcd; // Initialize the library with default I2C address 0x72 + +void setup() { + Wire.begin(); + + lcd.begin(Wire); //Set up the LCD for I2C communication + + lcd.setBacklight(255, 255, 255); //Set backlight to bright white + lcd.setContrast(5); //Set contrast. Lower to 0 for higher contrast. + + lcd.clear(); //Clear the display - this moves the cursor to home position as well + lcd.print("Fozziwig's Chicken Factory!"); + + lcd.saveSplash(); //Save this current text as the splash screen at next power on + + lcd.enableSplash(); //This will cause the splash to be displayed at power on + //lcd.disableSplash(); //This will supress any splash from being displayed at power on +} + +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/Example17-ChangeI2cAddress/Example17-ChangeI2cAddress.ino b/examples/Example17-ChangeI2cAddress/Example17-ChangeI2cAddress.ino new file mode 100644 index 0000000..16d7b38 --- /dev/null +++ b/examples/Example17-ChangeI2cAddress/Example17-ChangeI2cAddress.ino @@ -0,0 +1,91 @@ +/* + SparkFun Electronics + SerLCD Library - Change I2C address + Pete Lewis - August 18, 2020 + + This example demonstrates how to change the i2c address on your LCD. + Note, once you change the address, then you will need to call ".begin()" again. + + There is a set range of available addresses from 0x07 to 0x78, so make sure your + chosen address falls within this range. + + The next thing to note is that when you change the address you'll + need to call .begin again to talk to that screen. + + Finally if for some reason you've forgotten your new address. No big deal, run a + hardware reset on your screen to get it back to the default address (0x72). + To cause a hardware reset, simply tie the RX pin LOW, and they cycle power + (while continuing to hold RX low). Then release RX, and cycle power again. + + The circuit: + SparkFun RGB OpenLCD Serial display connected through + a SparkFun Qwiic cable/adpater to an qwiic-enabled Arduino. + + The Qwiic adapter should be attached to the display as follows: + Display / Qwiic Cable Color + GND / Black + RAW / Red + SDA / Blue + SCL / Yellow + + Note: If you connect directly to a 5V Arduino instead, you *MUST* use + a level-shifter to convert the i2c voltage levels down to 3.3V for the display. + + This code is based on the LiquidCrystal code originally by David A. Mellis + and the OpenLCD code by Nathan Seidle at SparkFun. + + Also based off the original Arduino Library code with many contributions from + Gaston Williams - August 29, 2018 + + Some code/comments/ideas ported from the Qwiic Quad Relay Arduino Library + Written by Elias Santistevan, July 2019 + + License: This example code is in the public domain. + + More info on Qwiic here: https://www.sparkfun.com/qwiic + + AVR-Based Serial Enabled LCDs Hookup Guide + https://learn.sparkfun.com/tutorials/avr-based-serial-enabled-lcds-hookup-guide +*/ + +#include + +#include //Click here to get the library: http://librarymanager/All#SparkFun_SerLCD +SerLCD lcd; // Initialize the library with default I2C address 0x72 + +byte oldAddress = 0x72; // default 0x72 +byte newAddress = 0x71; // must be within 0x07 to 0x78, DEFAULT: 0x72 + +void setup() { + Wire.begin(); + Serial.begin(115200); + + Serial.print("Connecting to SerLCD at 0x"); + Serial.println(oldAddress, HEX); + lcd.begin(Wire, oldAddress); //Set up the LCD for I2C communication + Serial.println("Done\n\r"); + + lcd.setBacklight(255, 255, 255); //Set backlight to bright white + lcd.setContrast(5); //Set contrast. Lower to 0 for higher contrast. + + lcd.clear(); //Clear the display - this moves the cursor to home position as well + + // command to change address + // note this will also change class private variable "lcd._i2cAddr" + Serial.print("Changing address to 0x"); + Serial.println(newAddress, HEX); + lcd.setAddress(newAddress); + Serial.println("Done\n\r"); + + Serial.print("Connecting to SerLCD at 0x"); + Serial.println(newAddress, HEX); + lcd.begin(Wire); // note, new address argument is not needed. lcd._i2cAddr has been updated by ".setAddress()" + Serial.println("Done\n\r"); + + lcd.print("My new address: 0x"); // print it to the LCD for user victory experience + lcd.print(lcd.getAddress(), HEX); // note, we need to use public function to access private lcd._i2cAddr +} + +void loop() { + // do nothing +} \ No newline at end of file diff --git a/examples/Example2-Backlight/Example2-Backlight.ino b/examples/Example2-Backlight/Example2-Backlight.ino index 81b2aae..a1aeab9 100644 --- a/examples/Example2-Backlight/Example2-Backlight.ino +++ b/examples/Example2-Backlight/Example2-Backlight.ino @@ -40,7 +40,7 @@ void setup() { void loop() { lcd.setBacklight(0, 0, 0); //black is off - lcd.clear(); + lcd.clear(); //Clear the display - this moves the cursor to home position as well lcd.print("Black (off)"); delay(3000); diff --git a/examples/Serial/Example1-HelloWorld/Example1-HelloWorld.ino b/examples/Serial/Example1-HelloWorld/Example1-HelloWorld.ino new file mode 100644 index 0000000..82bb14a --- /dev/null +++ b/examples/Serial/Example1-HelloWorld/Example1-HelloWorld.ino @@ -0,0 +1,57 @@ +/* + SerLCD Library - Hello World + Gaston Williams - August 29, 2018 + + This sketch prints "Hello World!" to the LCD + and shows the time over I2C using the Qwiic system. + + The circuit: + SparkFun RGB OpenLCD Serial display connected through + a Sparkfun Qwiic adpater to an Ardruino with a + Qwiic shield or a Sparkfun Blackboard with Qwiic built in. + + The Qwiic adapter should be attached to the display as follows: + Display / Qwiic Cable Color + GND / Black + RAW / Red + SDA / Blue + SCL / Yellow + + Note: If you connect directly to a 5V Arduino instead, you *MUST* use + a level-shifter to convert the i2c voltage levels down to 3.3V for the display. + + This code is based on the LiquidCrystal code originally by David A. Mellis + and the OpenLCD code by Nathan Seidle at SparkFun. + + License: This example code is in the public domain. + + More info on Qwiic here: https://www.sparkfun.com/qwiic + + AVR-Based Serial Enabled LCDs Hookup Guide + https://learn.sparkfun.com/tutorials/avr-based-serial-enabled-lcds-hookup-guide +*/ + +#include + +#include //Click here to get the library: http://librarymanager/All#SparkFun_SerLCD +SerLCD lcd; // Initialize the library with default I2C address 0x72 + +void setup() { + Serial.begin(9600); + + lcd.begin(Serial); //Set up the LCD for Serial communication at 9600bps + + lcd.setBacklight(255, 255, 255); //Set backlight to bright white + lcd.setContrast(5); //Set contrast. Lower to 0 for higher contrast. + + lcd.clear(); //Clear the display - this moves the cursor to home position as well + 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/keywords.txt b/keywords.txt index 09f0a02..c28ab3c 100644 --- a/keywords.txt +++ b/keywords.txt @@ -39,6 +39,13 @@ setContrast KEYWORD2 setAddress KEYWORD2 command KEYWORD2 specialCommand KEYWORD2 +enableSystemMessages KEYWORD2 +disableSystemMessages KEYWORD2 +enableSplash KEYWORD2 +disableSplash KEYWORD2 +saveSplash KEYWORD2 +getAddress KEYWORD2 + ####################################### # Constants (LITERAL1) diff --git a/library.properties b/library.properties index a9109ac..404b410 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=SparkFun SerLCD Arduino Library -version=1.0.1 -author=Gaston R. Williams +version=1.0.9 +author=Gaston R. Williams and Nathan Seidle maintainer=SparkFun Electronics sentence=Library for I2C, SPI, and Serial Communication with SparkFun SerLCD Displays -paragraph=An Arduino Library to allow simple control of 16x2 and 16x2 character SerLCDs from SparkFun. Includes RGB backlight control, display scrolling, cursor movement, and custom characters all over I2C, SPI, or Serial. -category=Displays +paragraph=An Arduino Library to allow simple control of 16x2 and 20x4 character SerLCDs from SparkFun. Includes RGB backlight control, display scrolling, cursor movement, and custom characters all over I2C, SPI, or Serial. +category=Display url=https://github.com/sparkfun/SparkFun_SerLCD_Arduino_Library architectures=* diff --git a/src/SerLCD.cpp b/src/SerLCD.cpp index ee02577..83c901c 100644 --- a/src/SerLCD.cpp +++ b/src/SerLCD.cpp @@ -4,6 +4,7 @@ * * By: Gaston R. Williams * Date: August 22, 2018 + * Update: March 23, 2020 - fixed missing return value in write(uint8_t) * * License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). * @@ -74,6 +75,10 @@ * '+' / 43 / 0x2B - Set RGB backlight with three following bytes, 0-255 * ',' / 44 / 0x2C - Display current firmware version * '-' / 45 / 0x2D - Clear display. Move cursor to home position. + * '.' / 46 / 0x2E - Enable system messages (ie, display 'Contrast: 5' when changed) + * '/' / 47 / 0x2F - Disable system messages (ie, don't display 'Contrast: 5' when changed) + * '0' / 48 / 0x30 - Enable splash screen + * '1' / 49 / 0x31 - Disable splash screen * / 128-157 / 0x80-0x9D - Set the primary backlight brightness. 128 = Off, 157 = 100%. * / 158-187 / 0x9E-0xBB - Set the green backlight brightness. 158 = Off, 187 = 100%. * / 188-217 / 0xBC-0xD9 - Set the blue backlight brightness. 188 = Off, 217 = 100%. @@ -83,19 +88,23 @@ #include "SerLCD.h" //<> setup using defaults -SerLCD::SerLCD(){ +SerLCD::SerLCD() +{ } //<> -SerLCD::~SerLCD(){/*nothing to destruct*/} +SerLCD::~SerLCD() +{ /*nothing to destruct*/ +} /* * Set up the i2c communication with the SerLCD. * wirePort - TwoWire port * ic2_addr - I2C address */ -void SerLCD::begin(TwoWire &wirePort, byte i2c_addr) { - _i2cAddr = i2c_addr; +void SerLCD::begin(TwoWire &wirePort, byte i2c_addr) +{ + _i2cAddr = i2c_addr; begin(wirePort); } // begin @@ -103,14 +112,11 @@ void SerLCD::begin(TwoWire &wirePort, byte i2c_addr) { /* * Set up the i2c communication with the SerLCD. */ -void SerLCD::begin(TwoWire &wirePort) { +void SerLCD::begin(TwoWire &wirePort) +{ _i2cPort = &wirePort; //Grab which port the user wants us to use - _serialPort = NULL; //Set to null to be safe - _spiPort = NULL; //Set to null to be safe - - //We expect caller to begin their I2C port, with the speed of their choice external to the library - //But if they forget, we start the hardware here. - _i2cPort->begin(); + _serialPort = NULL; //Set to null to be safe + _spiPort = NULL; //Set to null to be safe //Call init function since display may have been left in unknown state init(); @@ -119,10 +125,11 @@ void SerLCD::begin(TwoWire &wirePort) { /* * Set up the serial communication with the SerLCD. */ -void SerLCD::begin(Stream &serialPort) { +void SerLCD::begin(Stream &serialPort) +{ _serialPort = &serialPort; //Grab which port the user wants us to use - _i2cPort = NULL; //Set to null to be safe - _spiPort = NULL; //Set to null to be safe + _i2cPort = NULL; //Set to null to be safe + _spiPort = NULL; //Set to null to be safe //Call init function since display may have been left in unknown state init(); @@ -137,7 +144,8 @@ void SerLCD::begin(Stream &serialPort) { * transactions create the settings object in the function call, and that only * works if the function passes the object by value. */ -void SerLCD::begin(SPIClass &spiPort, byte csPin, SPISettings spiSettings) { +void SerLCD::begin(SPIClass &spiPort, byte csPin, SPISettings spiSettings) +{ _spiSettings = spiSettings; _spiTransaction = true; @@ -148,15 +156,16 @@ void SerLCD::begin(SPIClass &spiPort, byte csPin, SPISettings spiSettings) { /* * Set up the SPI communication with the SerLCD. */ -void SerLCD::begin(SPIClass &spiPort, byte csPin) { +void SerLCD::begin(SPIClass &spiPort, byte csPin) +{ _csPin = csPin; - pinMode(csPin, OUTPUT); //set pin to output, in case user forgot + pinMode(csPin, OUTPUT); //set pin to output, in case user forgot digitalWrite(csPin, HIGH); //deselect dispaly, in case user forgot _spiPort = &spiPort; //Grab the port the user wants us to use - _i2cPort = NULL; //Set to null to be safe - _serialPort = NULL; //Set to null to be safe + _i2cPort = NULL; //Set to null to be safe + _serialPort = NULL; //Set to null to be safe _spiPort->begin(); //call begin, in case the user forgot @@ -168,19 +177,24 @@ void SerLCD::begin(SPIClass &spiPort, byte csPin) { /* * Begin transmission to the device */ -void SerLCD::beginTransmission() { - //do nothing if using serialPort - if (_i2cPort) { - _i2cPort->beginTransmission(_i2cAddr); // transmit to device - } else if (_spiPort) { +void SerLCD::beginTransmission() +{ + //do nothing if using serialPort + if (_i2cPort) + { + _i2cPort->beginTransmission(_i2cAddr); // transmit to device + } + else if (_spiPort) + { #ifdef SPI_HAS_TRANSACTION - if (_spiTransaction) { - _spiPort->beginTransaction(_spiSettings); //gain control of the SPI bus - } //if _spiSettings + if (_spiTransaction) + { + _spiPort->beginTransaction(_spiSettings); //gain control of the SPI bus + } //if _spiSettings #endif - digitalWrite(_csPin, LOW); - delay(10); //wait a bit for display to enable - } // if-else + digitalWrite(_csPin, LOW); + delay(10); //wait a bit for display to enable + } // if-else } //beginTransmission /* @@ -188,63 +202,76 @@ void SerLCD::beginTransmission() { * * data - byte to send */ - void SerLCD::transmit(uint8_t data) { - if (_i2cPort) { - _i2cPort->write(data); // transmit to device - } else if (_serialPort){ - _serialPort->write(data); - } else if (_spiPort) { - _spiPort->transfer(data); - } // if-else - } //transmit +void SerLCD::transmit(uint8_t data) +{ + if (_i2cPort) + { + _i2cPort->write(data); // transmit to device + } + else if (_serialPort) + { + _serialPort->write(data); + } + else if (_spiPort) + { + _spiPort->transfer(data); + } // if-else +} //transmit /* * Begin transmission to the device */ -void SerLCD::endTransmission() { - //do nothing if using Serial port - if (_i2cPort) { - _i2cPort->endTransmission(); // transmit to device - } else if (_spiPort) { - digitalWrite(_csPin, HIGH); //disable display +void SerLCD::endTransmission() +{ + //do nothing if using Serial port + if (_i2cPort) + { + _i2cPort->endTransmission(); // transmit to device + } + else if (_spiPort) + { + digitalWrite(_csPin, HIGH); //disable display #ifdef SPI_HAS_TRANSACTION - if (_spiTransaction) { - _spiPort->endTransaction(); //let go of the SPI bus - } //if _spiSettings + if (_spiTransaction) + { + _spiPort->endTransaction(); //let go of the SPI bus + } //if _spiSettings #endif - delay(10); //wait a bit for display to disable - } // if-else + delay(10); //wait a bit for display to disable + } // if-else } //beginTransmission /* * Initialize the display * */ -void SerLCD::init() { +void SerLCD::init() +{ beginTransmission(); - transmit(SPECIAL_COMMAND); //Send special command character + transmit(SPECIAL_COMMAND); //Send special command character transmit(LCD_DISPLAYCONTROL | _displayControl); //Send the display command - transmit(SPECIAL_COMMAND); //Send special command character - transmit(LCD_ENTRYMODESET | _displayMode); //Send the entry mode command - transmit(SETTING_COMMAND); //Put LCD into setting mode - transmit(CLEAR_COMMAND); //Send clear display command - endTransmission(); //Stop transmission - delay(50); //let things settle a bit - } //init + transmit(SPECIAL_COMMAND); //Send special command character + transmit(LCD_ENTRYMODESET | _displayMode); //Send the entry mode command + transmit(SETTING_COMMAND); //Put LCD into setting mode + transmit(CLEAR_COMMAND); //Send clear display command + endTransmission(); //Stop transmission + delay(50); //let things settle a bit +} //init - /* +/* * Send a command to the display. * Used by other functions. * * byte command to send */ - void SerLCD::command(byte command) { - beginTransmission(); // transmit to device - transmit(SETTING_COMMAND); //Put LCD into setting mode - transmit(command); //Send the command code - endTransmission(); //Stop transmission +void SerLCD::command(byte command) +{ + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Put LCD into setting mode + transmit(command); //Send the command code + endTransmission(); //Stop transmission - delay(10); //Hang out for a bit + delay(10); //Hang out for a bit } /* @@ -252,11 +279,12 @@ void SerLCD::init() { * * byte command to send */ -void SerLCD::specialCommand(byte command) { - beginTransmission(); // transmit to device +void SerLCD::specialCommand(byte command) +{ + beginTransmission(); // transmit to device transmit(SPECIAL_COMMAND); //Send special command character - transmit(command); //Send the command code - endTransmission(); //Stop transmission + transmit(command); //Send the command code + endTransmission(); //Stop transmission delay(50); //Wait a bit longer for special display commands } @@ -268,14 +296,16 @@ void SerLCD::specialCommand(byte command) { * byte command to send * byte count number of times to send */ -void SerLCD::specialCommand(byte command, byte count) { +void SerLCD::specialCommand(byte command, byte count) +{ beginTransmission(); // transmit to device - for (int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) + { transmit(SPECIAL_COMMAND); //Send special command character - transmit(command); //Send command code - } // for - endTransmission(); //Stop transmission + transmit(command); //Send command code + } // for + endTransmission(); //Stop transmission delay(50); //Wait a bit longer for special display commands } @@ -285,9 +315,10 @@ void SerLCD::specialCommand(byte command, byte count) { * display and forces the cursor to return to the beginning * of the display. */ -void SerLCD::clear() { +void SerLCD::clear() +{ command(CLEAR_COMMAND); - delay(10); // a little extra delay after clear + delay(10); // a little extra delay after clear } /* @@ -295,8 +326,9 @@ void SerLCD::clear() { * to return to the beginning of the display, without clearing * the display. */ -void SerLCD::home() { - specialCommand(LCD_RETURNHOME); +void SerLCD::home() +{ + specialCommand(LCD_RETURNHOME); } /* @@ -305,14 +337,13 @@ void SerLCD::home() { * column - byte 0 to 19 * row - byte 0 to 3 * - * returns: boolean true if cursor set. */ -void SerLCD::setCursor(byte col, byte row) { - int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; +void SerLCD::setCursor(byte col, byte row) +{ + int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; //kepp variables in bounds - row = max(0, row); //row cannot be less than 0 - row = min(row, MAX_ROWS-1); //row cannot be greater than max rows + row = min(row, (byte)(MAX_ROWS - 1)); //row cannot be greater than max rows //send the command specialCommand(LCD_SETDDRAMADDR | (col + row_offsets[row])); @@ -323,17 +354,19 @@ void SerLCD::setCursor(byte col, byte row) { * byte location - character number 0 to 7 * byte[] charmap - byte array for character */ -void SerLCD::createChar(byte location, byte charmap[]) { +void SerLCD::createChar(byte location, byte charmap[]) +{ location &= 0x7; // we only have 8 locations 0-7 beginTransmission(); //Send request to create a customer character transmit(SETTING_COMMAND); //Put LCD into setting mode transmit(27 + location); - for (int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) + { transmit(charmap[i]); } // for endTransmission(); - delay(50); //This takes a bit longer + delay(50); //This takes a bit longer } /* @@ -341,7 +374,8 @@ void SerLCD::createChar(byte location, byte charmap[]) { * * byte location - character number 0 to 7 */ -void SerLCD::writeChar(byte location) { +void SerLCD::writeChar(byte location) +{ location &= 0x7; // we only have 8 locations 0-7 command(35 + location); @@ -351,26 +385,30 @@ void SerLCD::writeChar(byte location) { * Write a byte to the display. * Required for Print. */ -size_t SerLCD::write(uint8_t b) { +size_t SerLCD::write(uint8_t b) +{ beginTransmission(); // transmit to device transmit(b); endTransmission(); //Stop transmission - delay(10); // wait a bit - } // write + delay(10); // wait a bit + return 1; +} // write - /* +/* * Write a character buffer to the display. * Required for Print. */ -size_t SerLCD::write(const uint8_t *buffer, size_t size) { +size_t SerLCD::write(const uint8_t *buffer, size_t size) +{ size_t n = 0; beginTransmission(); // transmit to device - while (size--) { - transmit(*buffer++); - n++; - } //while + while (size--) + { + transmit(*buffer++); + n++; + } //while endTransmission(); //Stop transmission - delay(10); // + delay(10); // return n; } //write @@ -378,66 +416,75 @@ size_t SerLCD::write(const uint8_t *buffer, size_t size) { * Write a string to the display. * Required for Print. */ - size_t SerLCD::write(const char *str) { - if (str == NULL) return 0; - return write((const uint8_t *)str, strlen(str)); +size_t SerLCD::write(const char *str) +{ + if (str == NULL) + return 0; + return write((const uint8_t *)str, strlen(str)); } - /* +/* * Turn the display off quickly. */ - void SerLCD::noDisplay(){ +void SerLCD::noDisplay() +{ _displayControl &= ~LCD_DISPLAYON; specialCommand(LCD_DISPLAYCONTROL | _displayControl); - } // noDisplay +} // noDisplay /* * Turn the display on quickly. */ -void SerLCD::display() { +void SerLCD::display() +{ _displayControl |= LCD_DISPLAYON; specialCommand(LCD_DISPLAYCONTROL | _displayControl); - } // display - - /* +} // display + +/* * Turn the underline cursor off. */ - void SerLCD::noCursor(){ +void SerLCD::noCursor() +{ _displayControl &= ~LCD_CURSORON; specialCommand(LCD_DISPLAYCONTROL | _displayControl); - } // noCursor +} // noCursor /* * Turn the underline cursor on. */ -void SerLCD::cursor() { +void SerLCD::cursor() +{ _displayControl |= LCD_CURSORON; specialCommand(LCD_DISPLAYCONTROL | _displayControl); - } // cursor +} // cursor - /* +/* * Turn the blink cursor off. */ - void SerLCD::noBlink(){ +void SerLCD::noBlink() +{ _displayControl &= ~LCD_BLINKON; specialCommand(LCD_DISPLAYCONTROL | _displayControl); - } // noBlink +} // noBlink /* * Turn the blink cursor on. */ -void SerLCD::blink() { +void SerLCD::blink() +{ _displayControl |= LCD_BLINKON; specialCommand(LCD_DISPLAYCONTROL | _displayControl); - } // blink +} // blink /* * Scroll the display one character to the left, without * changing the text */ -void SerLCD::scrollDisplayLeft() { +void SerLCD::scrollDisplayLeft() +{ specialCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); - } // scrollDisplayLeft +} // scrollDisplayLeft /* * Scroll the display multiple characters to the left, without @@ -445,17 +492,19 @@ void SerLCD::scrollDisplayLeft() { * * count byte - number of characters to scroll */ -void SerLCD::scrollDisplayLeft(byte count) { +void SerLCD::scrollDisplayLeft(byte count) +{ specialCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT, count); - } // scrollDisplayLeft +} // scrollDisplayLeft /* * Scroll the display one character to the right, without * changing the text */ -void SerLCD::scrollDisplayRight() { +void SerLCD::scrollDisplayRight() +{ specialCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); - } // scrollDisplayRight +} // scrollDisplayRight /* * Scroll the display multiple characters to the right, without @@ -463,14 +512,16 @@ void SerLCD::scrollDisplayRight() { * * count byte - number of characters to scroll */ -void SerLCD::scrollDisplayRight(byte count) { +void SerLCD::scrollDisplayRight(byte count) +{ specialCommand(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT, count); - } // scrollDisplayRight +} // scrollDisplayRight /* * Move the cursor one character to the left. */ -void SerLCD::moveCursorLeft() { +void SerLCD::moveCursorLeft() +{ specialCommand(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVELEFT); } // moveCursorLeft @@ -479,14 +530,16 @@ void SerLCD::moveCursorLeft() { * * count byte - number of characters to move */ -void SerLCD::moveCursorLeft(byte count) { +void SerLCD::moveCursorLeft(byte count) +{ specialCommand(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVELEFT, count); } // moveCursorLeft /* * Move the cursor one character to the right. */ -void SerLCD::moveCursorRight() { +void SerLCD::moveCursorRight() +{ specialCommand(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVERIGHT); } // moveCursorRight @@ -495,7 +548,8 @@ void SerLCD::moveCursorRight() { * * count byte - number of characters to move */ -void SerLCD::moveCursorRight(byte count) { +void SerLCD::moveCursorRight(byte count) +{ specialCommand(LCD_CURSORSHIFT | LCD_CURSORMOVE | LCD_MOVERIGHT, count); } // moveCursorRight @@ -509,24 +563,26 @@ void SerLCD::moveCursorRight(byte count) { * * rgb - unsigned long hex encoded rgb value. */ -void SerLCD::setBacklight(unsigned long rgb) { +void SerLCD::setBacklight(unsigned long rgb) +{ // convert from hex triplet to byte values byte r = (rgb >> 16) & 0x0000FF; byte g = (rgb >> 8) & 0x0000FF; byte b = rgb & 0x0000FF; - setBacklight(r, g, b); + setBacklight(r, g, b); } /* * Uses a standard rgb byte triplit eg. (255, 0, 255) to * set the backlight color. */ -void SerLCD::setBacklight(byte r, byte g, byte b) { +void SerLCD::setBacklight(byte r, byte g, byte b) +{ // map the byte value range to backlight command range - byte red = 128 + map(r, 0, 255, 0, 29); + byte red = 128 + map(r, 0, 255, 0, 29); byte green = 158 + map(g, 0, 255, 0, 29); - byte blue = 188 + map(b, 0, 255, 0, 29); + byte blue = 188 + map(b, 0, 255, 0, 29); //send commands to the display to set backlights beginTransmission(); // transmit to device @@ -546,41 +602,97 @@ void SerLCD::setBacklight(byte r, byte g, byte b) { //Turn display back on and end _displayControl |= LCD_DISPLAYON; - transmit(SPECIAL_COMMAND); //Send special command character + transmit(SPECIAL_COMMAND); //Send special command character transmit(LCD_DISPLAYCONTROL | _displayControl); //Turn display on as before - endTransmission(); //Stop transmission - delay(50); //This one is a bit slow + endTransmission(); //Stop transmission + delay(50); //This one is a bit slow } // setBacklight // New backlight function -void SerLCD::setFastBacklight(unsigned long rgb) { +void SerLCD::setFastBacklight(unsigned long rgb) +{ // convert from hex triplet to byte values byte r = (rgb >> 16) & 0x0000FF; byte g = (rgb >> 8) & 0x0000FF; byte b = rgb & 0x0000FF; - setFastBacklight(r, g, b); + setFastBacklight(r, g, b); } //New command - set backlight with LCD messages or delays -void SerLCD::setFastBacklight(byte r, byte g, byte b) { - +void SerLCD::setFastBacklight(byte r, byte g, byte b) +{ //send commands to the display to set backlights - beginTransmission(); // transmit to device + beginTransmission(); // transmit to device transmit(SETTING_COMMAND); //Send special command character transmit(SET_RGB_COMMAND); //Send the set RGB character '+' or plus - transmit(r); //Send the red value - transmit(g); //Send the green value - transmit(b); //Send the blue value - endTransmission(); //Stop transmission + transmit(r); //Send the red value + transmit(g); //Send the green value + transmit(b); //Send the blue value + endTransmission(); //Stop transmission delay(10); - } // setFastBacklight +} // setFastBacklight + +//Enable system messages +//This allows user to see printing messages like 'UART: 57600' and 'Contrast: 5' +void SerLCD::enableSystemMessages() +{ + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Send special command character + transmit(ENABLE_SYSTEM_MESSAGE_DISPLAY); //Send the set '.' character + endTransmission(); //Stop transmission + delay(10); +} + +//Disable system messages +//This allows user to disable printing messages like 'UART: 57600' and 'Contrast: 5' +void SerLCD::disableSystemMessages() +{ + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Send special command character + transmit(DISABLE_SYSTEM_MESSAGE_DISPLAY); //Send the set '.' character + endTransmission(); //Stop transmission + delay(10); +} + +//Enable splash screen at power on +void SerLCD::enableSplash() +{ + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Send special command character + transmit(ENABLE_SPLASH_DISPLAY); //Send the set '.' character + endTransmission(); //Stop transmission + delay(10); +} + +//Disable splash screen at power on +void SerLCD::disableSplash() +{ + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Send special command character + transmit(DISABLE_SPLASH_DISPLAY); //Send the set '.' character + endTransmission(); //Stop transmission + delay(10); +} + +//Save the current display as the splash +void SerLCD::saveSplash() +{ + //Save whatever is currently being displayed into EEPROM + //This will be displayed at next power on as the splash screen + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Send special command character + transmit(SAVE_CURRENT_DISPLAY_AS_SPLASH); //Send the set Ctrl+j character + endTransmission(); //Stop transmission + delay(10); +} /* * Set the text to flow from left to right. This is the direction * that is common to most Western languages. */ -void SerLCD::leftToRight() { +void SerLCD::leftToRight() +{ _displayMode |= LCD_ENTRYLEFT; specialCommand(LCD_ENTRYMODESET | _displayMode); } // leftToRight @@ -588,7 +700,8 @@ void SerLCD::leftToRight() { /* * Set the text to flow from right to left. */ -void SerLCD::rightToLeft() { +void SerLCD::rightToLeft() +{ _displayMode &= ~LCD_ENTRYLEFT; specialCommand(LCD_ENTRYMODESET | _displayMode); } //rightToLeft @@ -597,7 +710,8 @@ void SerLCD::rightToLeft() { * Turn autoscrolling on. This will 'right justify' text from * the cursor. */ -void SerLCD::autoscroll() { +void SerLCD::autoscroll() +{ _displayMode |= LCD_ENTRYSHIFTINCREMENT; specialCommand(LCD_ENTRYMODESET | _displayMode); } //autoscroll @@ -605,7 +719,8 @@ void SerLCD::autoscroll() { /* * Turn autoscrolling off. */ -void SerLCD::noAutoscroll() { +void SerLCD::noAutoscroll() +{ _displayMode &= ~LCD_ENTRYSHIFTINCREMENT; specialCommand(LCD_ENTRYMODESET | _displayMode); } //noAutoscroll @@ -615,13 +730,14 @@ void SerLCD::noAutoscroll() { * * byte new_val - new contrast value */ -void SerLCD::setContrast(byte new_val) { +void SerLCD::setContrast(byte new_val) +{ //send commands to the display to set backlights - beginTransmission(); // transmit to device - transmit(SETTING_COMMAND); //Send contrast command + beginTransmission(); // transmit to device + transmit(SETTING_COMMAND); //Send contrast command transmit(CONTRAST_COMMAND); //0x18 - transmit(new_val); //Send new contrast value - endTransmission(); //Stop transmission + transmit(new_val); //Send new contrast value + endTransmission(); //Stop transmission delay(10); //Wait a little bit } //setContrast @@ -634,16 +750,27 @@ void SerLCD::setContrast(byte new_val) { * * byte new_addr - new i2c address */ -void SerLCD::setAddress(byte new_addr) { +void SerLCD::setAddress(byte new_addr) +{ //send commands to the display to set backlights - beginTransmission(); // transmit to device on old address + beginTransmission(); // transmit to device on old address transmit(SETTING_COMMAND); //Send contrast command - transmit(ADDRESS_COMMAND); //0x19 - transmit(new_addr); //Send new contrast value - endTransmission(); //Stop transmission + transmit(ADDRESS_COMMAND); //0x19 + transmit(new_addr); //Send new contrast value + endTransmission(); //Stop transmission //Update our own address so we can still talk to the display _i2cAddr = new_addr; delay(50); //This may take awhile -} //setContrast \ No newline at end of file +} //setAddress + +/* + * getAddress + * + * Returns private variable I2C address + */ +byte SerLCD::getAddress() +{ + return _i2cAddr; +} //getAddress diff --git a/src/SerLCD.h b/src/SerLCD.h index 5db77e6..86483c4 100644 --- a/src/SerLCD.h +++ b/src/SerLCD.h @@ -7,50 +7,55 @@ #include #define DISPLAY_ADDRESS1 0x72 //This is the default address of the OpenLCD -#define MAX_ROWS 4 -#define MAX_COLUMNS 20 +#define MAX_ROWS 4 +#define MAX_COLUMNS 20 //OpenLCD command characters -#define SPECIAL_COMMAND 254 //Magic number for sending a special command -#define SETTING_COMMAND 0x7C //124, |, the pipe character: The command to change settings: baud, lines, width, backlight, splash, etc +#define SPECIAL_COMMAND 254 //Magic number for sending a special command +#define SETTING_COMMAND 0x7C //124, |, the pipe character: The command to change settings: baud, lines, width, backlight, splash, etc //OpenLCD commands -#define CLEAR_COMMAND 0x2D //45, -, the dash character: command to clear and home the display -#define CONTRAST_COMMAND 0x18 //Command to change the contrast setting -#define ADDRESS_COMMAND 0x19 //Command to change the i2c address -#define SET_RGB_COMMAND 0x2B //43, +, the plus character: command to set backlight RGB value - +#define CLEAR_COMMAND 0x2D //45, -, the dash character: command to clear and home the display +#define CONTRAST_COMMAND 0x18 //Command to change the contrast setting +#define ADDRESS_COMMAND 0x19 //Command to change the i2c address +#define SET_RGB_COMMAND 0x2B //43, +, the plus character: command to set backlight RGB value +#define ENABLE_SYSTEM_MESSAGE_DISPLAY 0x2E //46, ., command to enable system messages being displayed +#define DISABLE_SYSTEM_MESSAGE_DISPLAY 0x2F //47, /, command to disable system messages being displayed +#define ENABLE_SPLASH_DISPLAY 0x30 //48, 0, command to enable splash screen at power on +#define DISABLE_SPLASH_DISPLAY 0x31 //49, 1, command to disable splash screen at power on +#define SAVE_CURRENT_DISPLAY_AS_SPLASH 0x0A //10, Ctrl+j, command to save current text on display as splash // special commands -#define LCD_RETURNHOME 0x02 -#define LCD_ENTRYMODESET 0x04 -#define LCD_DISPLAYCONTROL 0x08 -#define LCD_CURSORSHIFT 0x10 -#define LCD_SETDDRAMADDR 0x80 +#define LCD_RETURNHOME 0x02 +#define LCD_ENTRYMODESET 0x04 +#define LCD_DISPLAYCONTROL 0x08 +#define LCD_CURSORSHIFT 0x10 +#define LCD_SETDDRAMADDR 0x80 // flags for display entry mode -#define LCD_ENTRYRIGHT 0x00 -#define LCD_ENTRYLEFT 0x02 +#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 +#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 +#define LCD_CURSORMOVE 0x00 +#define LCD_MOVERIGHT 0x04 +#define LCD_MOVELEFT 0x00 -class SerLCD : public Print { +class SerLCD : public Print +{ -public: + public: SerLCD(); ~SerLCD(); void begin(TwoWire &wirePort); @@ -59,8 +64,8 @@ class SerLCD : public Print { void begin(SPIClass &spiPort, byte csPin); //Only available for Arduino 1.6 and greater #ifdef SPI_HAS_TRANSACTION - //pass SPISettings by value to allow settings object creation in fucntion call like examples - void begin(SPIClass &spiPort, byte csPin, SPISettings spiSettings); + //pass SPISettings by value to allow settings object creation in fucntion call like examples + void begin(SPIClass &spiPort, byte csPin, SPISettings spiSettings); #endif void clear(); void home(); @@ -69,7 +74,7 @@ class SerLCD : public Print { void writeChar(byte location); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buffer, size_t size); - virtual size_t write(const char *str); + virtual size_t write(const char *str); void noDisplay(); void display(); void noCursor(); @@ -96,25 +101,33 @@ class SerLCD : public Print { void setAddress(byte new_addr); void command(byte command); void specialCommand(byte command); - void specialCommand(byte command, byte count); -private: - TwoWire *_i2cPort = NULL; //The generic connection to user's chosen I2C hardware - Stream *_serialPort = NULL; //The generic connection to user's chosen serial hardware - SPIClass *_spiPort = NULL; //The generic connection to user's chosen spi hardware + void specialCommand(byte command, byte count); + + void enableSystemMessages(); + void disableSystemMessages(); + void enableSplash(); + void disableSplash(); + void saveSplash(); + byte getAddress(); + + private: + TwoWire *_i2cPort = NULL; //The generic connection to user's chosen I2C hardware + Stream *_serialPort = NULL; //The generic connection to user's chosen serial hardware + SPIClass *_spiPort = NULL; //The generic connection to user's chosen spi hardware //SPI transactions only available for Arduino 1.6 and later #ifdef SPI_HAS_TRANSACTION - SPISettings _spiSettings = SPISettings(100000, MSBFIRST, SPI_MODE0); - bool _spiTransaction = false; //since we pass by value, we need a flag + SPISettings _spiSettings = SPISettings(100000, MSBFIRST, SPI_MODE0); + bool _spiTransaction = false; //since we pass by value, we need a flag #endif - byte _csPin = 10; + byte _csPin = 10; byte _i2cAddr = DISPLAY_ADDRESS1; byte _displayControl = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; - byte _displayMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; - void init(); - void beginTransmission(); - void transmit(byte data); - void endTransmission(); + byte _displayMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; + void init(); + void beginTransmission(); + void transmit(byte data); + void endTransmission(); }; #endif \ No newline at end of file