Skip to content

Lcd oop extensions #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 50 additions & 85 deletions libraries/LiquidCrystal/LiquidCrystal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).

LiquidCrystal::LiquidCrystal()
{
// Not used but makes C++ happy when inherited
}

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)
Expand All @@ -39,15 +44,15 @@ LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable,
}

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)
{
init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
init(1, rs, rw, enable, 255, 255, 255, 255, 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)
{
init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
init(1, rs, 255, enable, 255, 255, 255, 255, d4, d5, d6, d7);
}

void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
Expand Down Expand Up @@ -78,66 +83,37 @@ void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t en
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
else
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;

begin(16, 1);
}

void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
void LiquidCrystal::begin(uint8_t cols, uint8_t rows, uint8_t dotsize) {
if (rows > 1) {
_displayfunction |= LCD_2LINE;
}
_numlines = lines;
_currline = 0;
_numrows = rows;
_numcols = cols;

// for some 1 line displays you can select a 10 pixel high font
if ((dotsize != 0) && (lines == 1)) {
if ((dotsize != 0) && (rows == 1)) {
_displayfunction |= LCD_5x10DOTS;
}

// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
// 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
// before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
delayMicroseconds(50000);
// Now we pull both RS and R/W low to begin commands
digitalWrite(_rs_pin, LOW);
digitalWrite(_enable_pin, LOW);
if (_rw_pin != 255) {
digitalWrite(_rw_pin, LOW);
}

//put the LCD into 4 bit or 8 bit mode
if (! (_displayfunction & LCD_8BITMODE)) {
// this is according to the hitachi HD44780 datasheet
// figure 24, pg 46

// we start in 8bit mode, try to set 4 bit mode
write4bits(0x03);
// we don't know which mode the LCD is in.
// maybe in the middle of a 4 bit mode transfer. force 8 bit mode.
for(int i = 0; i < 3; i++) {
// try to set 8 bit mode three times.
writebits(LCD_FUNCTIONSET | LCD_8BITMODE, LOW);
delayMicroseconds(4500); // wait min 4.1ms
}

// second try
write4bits(0x03);
delayMicroseconds(4500); // wait min 4.1ms

// third go!
write4bits(0x03);
delayMicroseconds(150);

// now put the LCD into 4 bit or 8 bit mode
if (! (_displayfunction & LCD_8BITMODE)) {
// finally, set to 4-bit interface
write4bits(0x02);
} else {
// this is according to the hitachi HD44780 datasheet
// page 45 figure 23

// Send function set command sequence
command(LCD_FUNCTIONSET | _displayfunction);
delayMicroseconds(4500); // wait more than 4.1ms

// second try
command(LCD_FUNCTIONSET | _displayfunction);
delayMicroseconds(150);

// third go
command(LCD_FUNCTIONSET | _displayfunction);
writebits(LCD_FUNCTIONSET, LOW);
}

// finally, set # lines, font size, etc.
Expand All @@ -151,7 +127,7 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
clear();

// Initialize to default text direction (for romance languages)
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDISABLE;
// set the entry mode
command(LCD_ENTRYMODESET | _displaymode);

Expand All @@ -172,9 +148,9 @@ void LiquidCrystal::home()

void LiquidCrystal::setCursor(uint8_t col, uint8_t row)
{
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if ( row >= _numlines ) {
row = _numlines-1; // we count rows starting w/0
int row_offsets[] = { 0x00, 0x40, _numcols, 0x40 + _numcols };
if ( row >= _numrows ) {
row = _numrows - 1; // we count rows starting w/0
}

command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
Expand Down Expand Up @@ -230,15 +206,15 @@ void LiquidCrystal::rightToLeft(void) {
command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'right justify' text from the cursor
// This will move the text on write, looks like a fixed cursor
void LiquidCrystal::autoscroll(void) {
_displaymode |= LCD_ENTRYSHIFTINCREMENT;
_displaymode |= LCD_ENTRYSHIFTENABLE;
command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'left justify' text from the cursor
// This will fix the text and moves the cursor on write
void LiquidCrystal::noAutoscroll(void) {
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
_displaymode &= ~LCD_ENTRYSHIFTENABLE;
command(LCD_ENTRYMODESET | _displaymode);
}

Expand All @@ -248,7 +224,7 @@ void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) {
location &= 0x7; // we only have 8 locations 0-7
command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++) {
write(charmap[i]);
send(charmap[i], HIGH);
}
}

Expand All @@ -267,44 +243,33 @@ inline size_t LiquidCrystal::write(uint8_t value) {

// write either command or data, with automatic 4/8-bit selection
void LiquidCrystal::send(uint8_t value, uint8_t mode) {
digitalWrite(_rs_pin, mode);
if (_displayfunction & LCD_8BITMODE) {
writebits(value, mode);
} else {
writebits(value, mode);
writebits(value<<4, mode);
}
delayMicroseconds(100); // commands and writes need > 37us to settle
}

void LiquidCrystal::writebits(uint8_t value, uint8_t mode) {
digitalWrite(_rs_pin, mode);
digitalWrite(_enable_pin, LOW);
// if there is a RW pin indicated, set it low to Write
if (_rw_pin != 255) {
digitalWrite(_rw_pin, LOW);
}

if (_displayfunction & LCD_8BITMODE) {
write8bits(value);
} else {
write4bits(value>>4);
write4bits(value);
for (int i = 0; i < 8; i++) {
uint8_t pin = _data_pins[i];
if (pin != 0xff) {
pinMode(pin, OUTPUT);
digitalWrite(pin, (value >> i) & 0x01);
}
}
}

void LiquidCrystal::pulseEnable(void) {
digitalWrite(_enable_pin, LOW);
delayMicroseconds(1);
digitalWrite(_enable_pin, HIGH);
delayMicroseconds(1); // enable pulse must be >450ns
digitalWrite(_enable_pin, LOW);
delayMicroseconds(100); // commands need > 37us to settle
}

void LiquidCrystal::write4bits(uint8_t value) {
for (int i = 0; i < 4; i++) {
pinMode(_data_pins[i], OUTPUT);
digitalWrite(_data_pins[i], (value >> i) & 0x01);
}

pulseEnable();
}

void LiquidCrystal::write8bits(uint8_t value) {
for (int i = 0; i < 8; i++) {
pinMode(_data_pins[i], OUTPUT);
digitalWrite(_data_pins[i], (value >> i) & 0x01);
}

pulseEnable();
}
30 changes: 15 additions & 15 deletions libraries/LiquidCrystal/LiquidCrystal.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00
#define LCD_ENTRYSHIFTENABLE 0x01
#define LCD_ENTRYSHIFTDISABLE 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
Expand Down Expand Up @@ -51,15 +51,15 @@ class LiquidCrystal : public Print {
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
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);
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);

void init(uint8_t fourbitmode, 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);

void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
virtual void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);

void clear();
void home();
Expand All @@ -80,14 +80,15 @@ class LiquidCrystal : public Print {
void createChar(uint8_t, uint8_t[]);
void setCursor(uint8_t, uint8_t);
virtual size_t write(uint8_t);
void command(uint8_t);
virtual void command(uint8_t);

inline LiquidCrystal& operator() (uint8_t x, uint8_t y) { setCursor(x,y); return *this;}; //use along w Streaming.h to support: lcd(col,line)<<"a="<<a;
using Print::write;
private:
void send(uint8_t, uint8_t);
void write4bits(uint8_t);
void write8bits(uint8_t);
void pulseEnable();
protected:
LiquidCrystal();

virtual void send(uint8_t, uint8_t);
virtual void writebits(uint8_t, uint8_t);

uint8_t _rs_pin; // LOW: command. HIGH: character.
uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD.
Expand All @@ -97,10 +98,9 @@ class LiquidCrystal : public Print {
uint8_t _displayfunction;
uint8_t _displaycontrol;
uint8_t _displaymode;

uint8_t _initialized;

uint8_t _numlines,_currline;

uint8_t _numcols;
uint8_t _numrows;
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ byte armsUp[8] = {
0b01010
};
void setup() {
// set up the lcd's number of columns and rows:
lcd.begin(16, 2);

// create a new character
lcd.createChar(0, heart);
// create a new character
Expand All @@ -108,8 +111,6 @@ void setup() {
// create a new character
lcd.createChar(4, armsUp);

// set up the lcd's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the lcd.
lcd.print("I ");
lcd.write(0);
Expand Down