From b2d23477f944d062dc2a2b34777c3308bca5253c Mon Sep 17 00:00:00 2001 From: Stefan Chisalita Date: Wed, 24 Jul 2013 16:08:31 +0300 Subject: [PATCH 1/2] Added read functions to the LiquidCrystal library Added functions to read data from LCD, to delete last character, to delete a character at specified position, get current position, get character from a position and get more characters at once, making it faster. --- libraries/LiquidCrystal/LiquidCrystal.cpp | 294 +++++++++++++++++++--- libraries/LiquidCrystal/LiquidCrystal.h | 16 +- libraries/LiquidCrystal/keywords.txt | 5 + 3 files changed, 276 insertions(+), 39 deletions(-) diff --git a/libraries/LiquidCrystal/LiquidCrystal.cpp b/libraries/LiquidCrystal/LiquidCrystal.cpp index 0653487d70c..6ef45886a4f 100644 --- a/libraries/LiquidCrystal/LiquidCrystal.cpp +++ b/libraries/LiquidCrystal/LiquidCrystal.cpp @@ -8,17 +8,17 @@ // When the display powers up, it is configured as follows: // // 1. Display clear -// 2. Function set: -// DL = 1; 8-bit interface data -// N = 0; 1-line display -// F = 0; 5x8 dot character font -// 3. Display on/off control: -// D = 0; Display off -// C = 0; Cursor off -// B = 0; Blinking off -// 4. Entry mode set: -// I/D = 1; Increment by 1 -// S = 0; No shift +// 2. Function set: +// DL = 1; 8-bit interface data +// N = 0; 1-line display +// F = 0; 5x8 dot character font +// 3. Display on/off control: +// D = 0; Display off +// C = 0; Cursor off +// B = 0; Blinking off +// 4. Entry mode set: +// I/D = 1; Increment by 1 +// S = 0; No shift // // Note, however, that resetting the Arduino doesn't reset the LCD, so we // can't assume that its in that state when a sketch starts (and the @@ -57,29 +57,29 @@ void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t en _rs_pin = rs; _rw_pin = rw; _enable_pin = enable; - + _data_pins[0] = d0; _data_pins[1] = d1; _data_pins[2] = d2; - _data_pins[3] = d3; + _data_pins[3] = d3; _data_pins[4] = d4; _data_pins[5] = d5; _data_pins[6] = d6; - _data_pins[7] = d7; + _data_pins[7] = d7; pinMode(_rs_pin, OUTPUT); // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# - if (_rw_pin != 255) { + if (_rw_pin != 255) { pinMode(_rw_pin, OUTPUT); } pinMode(_enable_pin, OUTPUT); - + if (fourbitmode) _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; - else + else _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; - - begin(16, 1); + + begin(16, 1); } void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { @@ -97,14 +97,14 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { // 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 - delayMicroseconds(50000); + 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) { + 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 @@ -117,13 +117,13 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { // second try write4bits(0x03); delayMicroseconds(4500); // wait min 4.1ms - + // third go! - write4bits(0x03); + write4bits(0x03); delayMicroseconds(150); // finally, set to 4-bit interface - write4bits(0x02); + write4bits(0x02); } else { // this is according to the hitachi HD44780 datasheet // page 45 figure 23 @@ -141,10 +141,10 @@ void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { } // finally, set # lines, font size, etc. - command(LCD_FUNCTIONSET | _displayfunction); + command(LCD_FUNCTIONSET | _displayfunction); // turn the display on with no cursor or blinking default - _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; + _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; display(); // clear it off @@ -176,7 +176,7 @@ void LiquidCrystal::setCursor(uint8_t col, uint8_t row) if ( row >= _numlines ) { row = _numlines-1; // we count rows starting w/0 } - + command(LCD_SETDDRAMADDR | (col + row_offsets[row])); } @@ -252,6 +252,153 @@ void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) { } } +// Get the current cursor position and put the information in the passed values +void LiquidCrystal::getCursorPos(int &col, int &row) { + uint8_t value = readBusyFlagAndAddress(); + + if(value >= 128) + { //get rid of the busy flag if it is set + value-=128; + } + row=0; + if(_numlines > 1) + { + //if there are 2 rows + if(value >= 64 )//it means it is on line 2 + { + value-=64; + row=1; + } + } + col = value; +} + +// Retrieves a number of characters starting from the specified position +char* LiquidCrystal::getChars(uint8_t col, uint8_t row, uint8_t chars) +{ + //much faster with more characters than calling getCharAt for each character + if (_rw_pin == 255) + {//if there is no rw pin just return NULL + return NULL; + } + + char *v= new char[chars]; //allocate space + + setCursor(col, row); + + digitalWrite(_rs_pin, HIGH); + digitalWrite(_rw_pin, HIGH); + delayMicroseconds(1); // tAS time + + if (_displayfunction & LCD_8BITMODE) + { + for(int i=0; i>4); write4bits(value); @@ -284,7 +459,7 @@ void LiquidCrystal::send(uint8_t value, uint8_t mode) { void LiquidCrystal::pulseEnable(void) { digitalWrite(_enable_pin, LOW); - delayMicroseconds(1); + delayMicroseconds(1); digitalWrite(_enable_pin, HIGH); delayMicroseconds(1); // enable pulse must be >450ns digitalWrite(_enable_pin, LOW); @@ -295,16 +470,63 @@ 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(); } - 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(); + +} + +// Reads data from the LCD in 4Bit Mode +uint8_t LiquidCrystal::read4bits() +{ + + digitalWrite(_enable_pin, HIGH); + delayMicroseconds(1); // tDDR time + + uint8_t value =0; + for(int i=3; i>=0; i--) + { + value= value<< 1; + + pinMode(_data_pins[i], INPUT); + if(digitalRead(_data_pins[i]) == HIGH) + { + value+=1; + } + + } + digitalWrite(_enable_pin, LOW); + delayMicroseconds(1); //tDHR time + + return value; +} + +// Reads data from the LCD in 8Bit Mode +uint8_t LiquidCrystal::read8bits() +{ + digitalWrite(_enable_pin, HIGH); + delayMicroseconds(1); // tDDR time + uint8_t value =0; + for(int i=7; i>=0; i--) + { + value= value<< 1; + + pinMode(_data_pins[i], INPUT); + if(digitalRead(_data_pins[i]) == HIGH) + { + value+=1; + } + + } + digitalWrite(_enable_pin, LOW); + delayMicroseconds(1); //tDHR time + return value; } diff --git a/libraries/LiquidCrystal/LiquidCrystal.h b/libraries/LiquidCrystal/LiquidCrystal.h index 24ec5afdf5b..6d0f76c5c02 100755 --- a/libraries/LiquidCrystal/LiquidCrystal.h +++ b/libraries/LiquidCrystal/LiquidCrystal.h @@ -58,7 +58,7 @@ class LiquidCrystal : public Print { 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); void clear(); @@ -78,15 +78,25 @@ class LiquidCrystal : public Print { void noAutoscroll(); void createChar(uint8_t, uint8_t[]); - void setCursor(uint8_t, uint8_t); + void setCursor(uint8_t, uint8_t); + void getCursorPos(int &col, int &row); + char getCharAt(uint8_t col, uint8_t row); + char getCharAt(uint8_t col, uint8_t row, uint8_t ret); + char* getChars(uint8_t col, uint8_t row, uint8_t chars); + void deleteLast(); + void deleteAt(uint8_t col, uint8_t row); virtual size_t write(uint8_t); void command(uint8_t); - + using Print::write; private: + + uint8_t readBusyFlagAndAddress(); void send(uint8_t, uint8_t); void write4bits(uint8_t); void write8bits(uint8_t); + uint8_t read4bits(); + uint8_t read8bits(); void pulseEnable(); uint8_t _rs_pin; // LOW: command. HIGH: character. diff --git a/libraries/LiquidCrystal/keywords.txt b/libraries/LiquidCrystal/keywords.txt index 132845cb651..aeb3eccfb7d 100755 --- a/libraries/LiquidCrystal/keywords.txt +++ b/libraries/LiquidCrystal/keywords.txt @@ -30,6 +30,11 @@ rightToLeft KEYWORD2 scrollDisplayLeft KEYWORD2 scrollDisplayRight KEYWORD2 createChar KEYWORD2 +getCursorPos KEYWORD2 +getCharAt KEYWORD2 +getChars KEYWORD2 +deleteLast KEYWORD2 +deleteAt KEYWORD2 ####################################### # Constants (LITERAL1) From 8c9e17d4f21a642be4b47ad0a55f4e8fffc99836 Mon Sep 17 00:00:00 2001 From: Chisalita Stefan Date: Mon, 15 Sep 2014 18:30:07 +0300 Subject: [PATCH 2/2] modified the commit in which I added reading Modified the commit in which I added reading functions, I used the suggestions from the comments to make it fit in the API style and improved the code a little --- libraries/LiquidCrystal/LiquidCrystal.cpp | 112 ++++++++++------------ libraries/LiquidCrystal/LiquidCrystal.h | 8 +- 2 files changed, 52 insertions(+), 68 deletions(-) diff --git a/libraries/LiquidCrystal/LiquidCrystal.cpp b/libraries/LiquidCrystal/LiquidCrystal.cpp index 6ef45886a4f..b76944e0393 100644 --- a/libraries/LiquidCrystal/LiquidCrystal.cpp +++ b/libraries/LiquidCrystal/LiquidCrystal.cpp @@ -255,11 +255,8 @@ void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) { // Get the current cursor position and put the information in the passed values void LiquidCrystal::getCursorPos(int &col, int &row) { uint8_t value = readBusyFlagAndAddress(); + value &= 0x7f; //get rid of the busy flag if it is set - if(value >= 128) - { //get rid of the busy flag if it is set - value-=128; - } row=0; if(_numlines > 1) { @@ -274,41 +271,32 @@ void LiquidCrystal::getCursorPos(int &col, int &row) { } // Retrieves a number of characters starting from the specified position -char* LiquidCrystal::getChars(uint8_t col, uint8_t row, uint8_t chars) +// and puts them into the buffer, the buffer is NOT null terminated. +// Returns 0 if it could not read or returns the length if it was successful. +// Much faster with more characters than calling getCharAt for each character. +uint8_t LiquidCrystal::getChars(uint8_t col, uint8_t row, char* buffer, uint8_t length) { - //much faster with more characters than calling getCharAt for each character + if (_rw_pin == 255) - {//if there is no rw pin just return NULL - return NULL; + {//if there is no rw pin just return 0 + return 0; } - char *v= new char[chars]; //allocate space + //save the last position to return to it when the function is finished + int prev_col, prev_row; + getCursorPos(prev_col, prev_row); setCursor(col, row); - digitalWrite(_rs_pin, HIGH); - digitalWrite(_rw_pin, HIGH); - delayMicroseconds(1); // tAS time - - if (_displayfunction & LCD_8BITMODE) - { - for(int i=0; i> i) & 0x01); - pulseEnable(); } + pulseEnable(); +} void LiquidCrystal::write8bits(uint8_t value) { for (int i = 0; i < 8; i++) { @@ -481,7 +465,6 @@ void LiquidCrystal::write8bits(uint8_t value) { } pulseEnable(); - } // Reads data from the LCD in 4Bit Mode @@ -530,3 +513,4 @@ uint8_t LiquidCrystal::read8bits() delayMicroseconds(1); //tDHR time return value; } + diff --git a/libraries/LiquidCrystal/LiquidCrystal.h b/libraries/LiquidCrystal/LiquidCrystal.h index 6d0f76c5c02..a9e40a8941e 100755 --- a/libraries/LiquidCrystal/LiquidCrystal.h +++ b/libraries/LiquidCrystal/LiquidCrystal.h @@ -79,20 +79,20 @@ 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); void getCursorPos(int &col, int &row); char getCharAt(uint8_t col, uint8_t row); char getCharAt(uint8_t col, uint8_t row, uint8_t ret); - char* getChars(uint8_t col, uint8_t row, uint8_t chars); + uint8_t getChars(uint8_t col, uint8_t row, char* buffer, uint8_t length); void deleteLast(); void deleteAt(uint8_t col, uint8_t row); - virtual size_t write(uint8_t); - void command(uint8_t); using Print::write; private: - uint8_t readBusyFlagAndAddress(); void send(uint8_t, uint8_t); + uint8_t receive(int rs_pin_mode); void write4bits(uint8_t); void write8bits(uint8_t); uint8_t read4bits();