From 243766044c7ba52d3d911d10cec7df0494d6d9aa Mon Sep 17 00:00:00 2001 From: Vasily Davydov Date: Sun, 16 Oct 2022 11:26:59 +0300 Subject: [PATCH] lcd: add internal columns, rows --- LiquidCrystal/inc/LiquidCrystal.h | 67 +++--- LiquidCrystal/src/LiquidCrystal.cpp | 320 +++++++++++++++++----------- 2 files changed, 235 insertions(+), 152 deletions(-) diff --git a/LiquidCrystal/inc/LiquidCrystal.h b/LiquidCrystal/inc/LiquidCrystal.h index 89690b1..4f416e5 100644 --- a/LiquidCrystal/inc/LiquidCrystal.h +++ b/LiquidCrystal/inc/LiquidCrystal.h @@ -1,11 +1,11 @@ #ifndef LiquidCrystal_h #define LiquidCrystal_h - +#include "DigitalIoPin.h" +#include "chip.h" #include #include -#include "chip.h" -#include "DigitalIoPin.h" + // commands #define LCD_CLEARDISPLAY 0x01 @@ -45,43 +45,43 @@ #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 -class LiquidCrystal { +class LiquidCrystal +{ public: + LiquidCrystal (DigitalIoPin *rs, DigitalIoPin *enable, DigitalIoPin *d0, + DigitalIoPin *d1, DigitalIoPin *d2, DigitalIoPin *d3); - LiquidCrystal(DigitalIoPin *rs, DigitalIoPin *enable, - DigitalIoPin *d0, DigitalIoPin *d1, DigitalIoPin *d2, DigitalIoPin *d3); + void begin (uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); - void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); + void clear (); + void home (); - 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 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, uint8_t); - virtual size_t write(uint8_t); - void command(uint8_t); - void print(std::string const &s); - void print(const char *s); + void createChar (uint8_t, uint8_t[]); + void setCursor (uint8_t, uint8_t); + virtual size_t write (uint8_t); + void command (uint8_t); + void print (std::string const &s); + void print (const char *s); private: - void send(uint8_t, uint8_t); - void write4bits(uint8_t); - void pulseEnable(); + void send (uint8_t, uint8_t); + void write4bits (uint8_t); + void pulseEnable (); - DigitalIoPin *rs_pin; // LOW(false): command. HIGH(true): character. + DigitalIoPin *rs_pin; // LOW(false): command. HIGH(true): character. DigitalIoPin *enable_pin; // activated by a HIGH pulse. DigitalIoPin *data_pins[4]; @@ -91,7 +91,8 @@ private: uint8_t _initialized; - uint8_t _numlines,_currline; + uint8_t _numlines, _currline; + uint8_t rows, col; }; #endif diff --git a/LiquidCrystal/src/LiquidCrystal.cpp b/LiquidCrystal/src/LiquidCrystal.cpp index a90728c..a44748b 100644 --- a/LiquidCrystal/src/LiquidCrystal.cpp +++ b/LiquidCrystal/src/LiquidCrystal.cpp @@ -1,16 +1,39 @@ #include "LiquidCrystal.h" -#include #include "chip.h" +#include #define LOW 0 #define HIGH 1 - - -void delayMicroseconds(unsigned int us) +void +delayMicroseconds (unsigned int us) { - // implement with RIT + uint32_t reg; + // calculate compare value + uint64_t cmp = (Chip_Clock_GetSystemClockRate () / 1000000) + * us; // One cycle equals ~72 us, thus cycle * us + // disable RIT – compare value may only be changed when RIT is disabled + reg = LPC_RITIMER->CTRL & 0xF; + LPC_RITIMER->CTRL = reg & ~RIT_CTRL_TEN; + // set compare value to RIT + LPC_RITIMER->COMPVAL = (uint32_t)cmp; + LPC_RITIMER->COMPVAL_H = (uint32_t) (cmp >> 32); + // clear RIT counter (so that counting starts from zero) + LPC_RITIMER->COUNTER = (uint32_t)0; + LPC_RITIMER->COUNTER_H = (uint32_t) (0 >> 32); + // enable RIT + reg = LPC_RITIMER->CTRL & 0xF; + LPC_RITIMER->CTRL = reg | RIT_CTRL_TEN; + // wait until RIT Int flag is set + while (!(LPC_RITIMER->CTRL & RIT_CTRL_INT)) + ; + // disable RIT + reg = LPC_RITIMER->CTRL & 0xF; + LPC_RITIMER->CTRL = reg & ~RIT_CTRL_TEN; + // clear RIT Int flag + reg = LPC_RITIMER->CTRL & 0xF; + LPC_RITIMER->CTRL = reg | RIT_CTRL_INT; } // When the display powers up, it is configured as follows: @@ -32,11 +55,9 @@ void delayMicroseconds(unsigned int us) // can't assume that its in that state when a sketch starts (and the // LiquidCrystal constructor is called). - - - -LiquidCrystal::LiquidCrystal(DigitalIoPin *rs, DigitalIoPin *enable, - DigitalIoPin *d0, DigitalIoPin *d1, DigitalIoPin *d2, DigitalIoPin *d3) +LiquidCrystal::LiquidCrystal (DigitalIoPin *rs, DigitalIoPin *enable, + DigitalIoPin *d0, DigitalIoPin *d1, + DigitalIoPin *d2, DigitalIoPin *d3) { rs_pin = rs; enable_pin = enable; @@ -48,221 +69,282 @@ LiquidCrystal::LiquidCrystal(DigitalIoPin *rs, DigitalIoPin *enable, _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; - begin(16, 2); // default to 16x2 display + begin (16, 2); // default to 16x2 display } -void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { - if (lines > 1) { - _displayfunction |= LCD_2LINE; - } +void +LiquidCrystal::begin (uint8_t cols, uint8_t lines, uint8_t dotsize) +{ + this->rows = lines; + this->col = cols; + if (lines > 1) + { + _displayfunction |= LCD_2LINE; + } _numlines = lines; _currline = 0; // for some 1 line displays you can select a 10 pixel high font - if ((dotsize != 0) && (lines == 1)) { - _displayfunction |= LCD_5x10DOTS; - } + if ((dotsize != 0) && (lines == 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 - delayMicroseconds(50000); + // before sending commands. Arduino can turn on way befer 4.5V so we'll wait + // 50 + delayMicroseconds (50000); // Now we pull both RS and R/W low to begin commands - rs_pin->write(false); //digitalWrite(_rs_pin, LOW); - enable_pin->write(false); //digitalWrite(_enable_pin, LOW); + rs_pin->write (false); // digitalWrite(_rs_pin, LOW); + enable_pin->write (false); // digitalWrite(_enable_pin, LOW); // note: this port supports only 4 bit mode - //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 + // 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); - delayMicroseconds(4500); // wait min 4.1ms + // we start in 8bit mode, try to set 4 bit mode + write4bits (0x03); + delayMicroseconds (4500); // wait min 4.1ms - // second try - write4bits(0x03); - delayMicroseconds(4500); // wait min 4.1ms + // second try + write4bits (0x03); + delayMicroseconds (4500); // wait min 4.1ms - // third go! - write4bits(0x03); - delayMicroseconds(150); + // third go! + write4bits (0x03); + delayMicroseconds (150); - // finally, set to 4-bit interface - write4bits(0x02); - } else { - // this is according to the hitachi HD44780 datasheet - // page 45 figure 23 + // 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 + // Send function set command sequence + command (LCD_FUNCTIONSET | _displayfunction); + delayMicroseconds (4500); // wait more than 4.1ms - // second try - command(LCD_FUNCTIONSET | _displayfunction); - delayMicroseconds(150); + // second try + command (LCD_FUNCTIONSET | _displayfunction); + delayMicroseconds (150); - // third go - command(LCD_FUNCTIONSET | _displayfunction); - } + // third go + command (LCD_FUNCTIONSET | _displayfunction); + } // 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; - display(); + display (); // clear it off - clear(); + clear (); // Initialize to default text direction (for romance languages) _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; // set the entry mode - command(LCD_ENTRYMODESET | _displaymode); - + command (LCD_ENTRYMODESET | _displaymode); } /********** high level commands, for the user! */ -void LiquidCrystal::clear() +void +LiquidCrystal::clear () { - command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! + command (LCD_CLEARDISPLAY); // clear display, set cursor position to zero + delayMicroseconds (2000); // this command takes a long time! } -void LiquidCrystal::home() +void +LiquidCrystal::home () { - command(LCD_RETURNHOME); // set cursor position to zero - delayMicroseconds(2000); // this command takes a long time! + command (LCD_RETURNHOME); // set cursor position to zero + delayMicroseconds (2000); // this command takes a long time! } - -void LiquidCrystal::print(std::string const &s) +void +LiquidCrystal::print (std::string const &s) { + this->print (s.c_str ()); } -void LiquidCrystal::print(const char *s) +void +LiquidCrystal::print (const char *s) { + int char_counter = 0; + while (*s && char_counter < this->col) + { + send (*s, HIGH); + char_counter++; + s++; + } } -void LiquidCrystal::setCursor(uint8_t col, uint8_t row) +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 - } + if (row >= _numlines) + { + row = _numlines - 1; // we count rows starting w/0 + } - command(LCD_SETDDRAMADDR | (col + row_offsets[row])); + command (LCD_SETDDRAMADDR | (col + row_offsets[row])); } // Turn the display on/off (quickly) -void LiquidCrystal::noDisplay() { +void +LiquidCrystal::noDisplay () +{ _displaycontrol &= ~LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); + command (LCD_DISPLAYCONTROL | _displaycontrol); } -void LiquidCrystal::display() { +void +LiquidCrystal::display () +{ _displaycontrol |= LCD_DISPLAYON; - command(LCD_DISPLAYCONTROL | _displaycontrol); + command (LCD_DISPLAYCONTROL | _displaycontrol); } // Turns the underline cursor on/off -void LiquidCrystal::noCursor() { +void +LiquidCrystal::noCursor () +{ _displaycontrol &= ~LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); + command (LCD_DISPLAYCONTROL | _displaycontrol); } -void LiquidCrystal::cursor() { +void +LiquidCrystal::cursor () +{ _displaycontrol |= LCD_CURSORON; - command(LCD_DISPLAYCONTROL | _displaycontrol); + command (LCD_DISPLAYCONTROL | _displaycontrol); } // Turn on and off the blinking cursor -void LiquidCrystal::noBlink() { +void +LiquidCrystal::noBlink () +{ _displaycontrol &= ~LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); + command (LCD_DISPLAYCONTROL | _displaycontrol); } -void LiquidCrystal::blink() { +void +LiquidCrystal::blink () +{ _displaycontrol |= LCD_BLINKON; - command(LCD_DISPLAYCONTROL | _displaycontrol); + command (LCD_DISPLAYCONTROL | _displaycontrol); } // These commands scroll the display without changing the RAM -void LiquidCrystal::scrollDisplayLeft(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); +void +LiquidCrystal::scrollDisplayLeft (void) +{ + command (LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); } -void LiquidCrystal::scrollDisplayRight(void) { - command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); +void +LiquidCrystal::scrollDisplayRight (void) +{ + command (LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); } // This is for text that flows Left to Right -void LiquidCrystal::leftToRight(void) { +void +LiquidCrystal::leftToRight (void) +{ _displaymode |= LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); + command (LCD_ENTRYMODESET | _displaymode); } // This is for text that flows Right to Left -void LiquidCrystal::rightToLeft(void) { +void +LiquidCrystal::rightToLeft (void) +{ _displaymode &= ~LCD_ENTRYLEFT; - command(LCD_ENTRYMODESET | _displaymode); + command (LCD_ENTRYMODESET | _displaymode); } // This will 'right justify' text from the cursor -void LiquidCrystal::autoscroll(void) { +void +LiquidCrystal::autoscroll (void) +{ _displaymode |= LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); + command (LCD_ENTRYMODESET | _displaymode); } // This will 'left justify' text from the cursor -void LiquidCrystal::noAutoscroll(void) { +void +LiquidCrystal::noAutoscroll (void) +{ _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; - command(LCD_ENTRYMODESET | _displaymode); + command (LCD_ENTRYMODESET | _displaymode); } // Allows us to fill the first 8 CGRAM locations // with custom characters -void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) { +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]); - } + command (LCD_SETCGRAMADDR | (location << 3)); + for (int i = 0; i < 8; i++) + { + write (charmap[i]); + } } /*********** mid level commands, for sending data/cmds */ -inline void LiquidCrystal::command(uint8_t value) { - send(value, LOW); +inline void +LiquidCrystal::command (uint8_t value) +{ + send (value, LOW); } -inline size_t LiquidCrystal::write(uint8_t value) { - send(value, HIGH); +inline size_t +LiquidCrystal::write (uint8_t value) +{ + send (value, HIGH); return 1; // assume sucess } /************ low level data pushing commands **********/ // write either command or data -void LiquidCrystal::send(uint8_t value, uint8_t mode) { - rs_pin->write(mode); //digitalWrite(_rs_pin, mode); +void +LiquidCrystal::send (uint8_t value, uint8_t mode) +{ + rs_pin->write (mode); // digitalWrite(_rs_pin, mode); - write4bits(value>>4); - write4bits(value); + write4bits (value >> 4); + write4bits (value); } -void LiquidCrystal::pulseEnable(void) { - enable_pin->write(false); //digitalWrite(_enable_pin, LOW); - delayMicroseconds(1); - enable_pin->write(true); //digitalWrite(_enable_pin, HIGH); - delayMicroseconds(1); // enable pulse must be >450ns - enable_pin->write(false); //digitalWrite(_enable_pin, LOW); - delayMicroseconds(100); // commands need > 37us to settle +void +LiquidCrystal::pulseEnable (void) +{ + enable_pin->write (false); // digitalWrite(_enable_pin, LOW); + delayMicroseconds (1); + enable_pin->write (true); // digitalWrite(_enable_pin, HIGH); + delayMicroseconds (1); // enable pulse must be >450ns + enable_pin->write (false); // digitalWrite(_enable_pin, LOW); + delayMicroseconds (100); // commands need > 37us to settle } -void LiquidCrystal::write4bits(uint8_t value) { - for (int i = 0; i < 4; i++) { - data_pins[i]->write((value >> i) & 0x01); //digitalWrite(_data_pins[i], (value >> i) & 0x01); - } - - pulseEnable(); -} +void +LiquidCrystal::write4bits (uint8_t value) +{ + for (int i = 0; i < 4; i++) + { + data_pins[i]->write ( + (value >> i) + & 0x01); // digitalWrite(_data_pins[i], (value >> i) & 0x01); + } + pulseEnable (); +} \ No newline at end of file