Harry Cadena / Mbed 2 deprecated LiquidCrystal_I2C

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LiquidCrystal_I2C.cpp Source File

LiquidCrystal_I2C.cpp

00001 // Based on the work by DFRobot upgraded by DVSProductions
00002 #include "LiquidCrystal_I2C.h"
00003 #include <inttypes.h>
00004 /*********** mid level commands, for sending data/cmds */
00005 #define COMMAND(value) send(value, 0)
00006 #define printIIC(args) i2c->write(_Addr, args, 1)
00007 size_t LiquidCrystal_I2C::write(uint8_t value) {
00008     send(value, Rs);
00009     return 1;
00010 }
00011 
00012 inline void LiquidCrystal_I2C::command(uint8_t value) {
00013     send(value, 0);
00014 }
00015 
00016 // When the display powers up, it is configured as follows:
00017 //
00018 // 1. Display clear
00019 // 2. Function set:
00020 //    DL = 1; 8-bit interface data
00021 //    N = 0; 1-line display
00022 //    F = 0; 5x8 dot character font
00023 // 3. Display on/off control:
00024 //    D = 0; Display off
00025 //    C = 0; Cursor off
00026 //    B = 0; Blinking off
00027 // 4. Entry mode set:
00028 //    I/D = 1; Increment by 1
00029 //    S = 0; No shift
00030 //
00031 // Note, however, that resetting the Arduino doesn't reset the LCD, so we
00032 // can't assume that its in that state when a sketch starts (and the
00033 // LiquidCrystal constructor is called).
00034 
00035 /*!
00036 Creates a new LCD instance
00037 !*/
00038 LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows, PinName sda, PinName scl) {
00039     _Addr = lcd_Addr << 1;
00040     _cols = lcd_cols;
00041     _rows = lcd_rows;
00042     _backlightval = LCD_NOBACKLIGHT;
00043     i2c = new I2C(sda, scl);
00044     i2c->frequency(1000000);
00045 }
00046 
00047  void LiquidCrystal_I2C::init() {
00048     init_priv();
00049 }
00050 
00051  void LiquidCrystal_I2C::init_priv() {
00052     _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
00053     begin_priv();
00054 }
00055 void LiquidCrystal_I2C::begin_priv(uint8_t dotsize) {
00056     if (_rows > 1) {
00057         _displayfunction |= LCD_2LINE;
00058     }
00059     _numlines = _rows;
00060     // for some 1 line displays you can select a 10 pixel high font
00061     if ((dotsize != 0) && (_rows == 1)) {
00062         _displayfunction |= LCD_5x10DOTS;
00063     }
00064     // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
00065     // according to datasheet, we need at least 40ms after power rises above 2.7V
00066     // before sending commands. Nucleo can turn on way befer 4.5V so we'll wait
00067     // 50
00068     wait_ms(50);
00069     // Now we pull both RS and R/W low to begin commands
00070     expanderWrite(_backlightval); // reset expanderand turn backlight off (Bit 8 =1)
00071     wait_ms(1000);
00072     // put the LCD into 4 bit mode
00073     // this is according to the hitachi HD44780 datasheet
00074     // figure 24, pg 46
00075 
00076     // we start in 8bit mode, try to set 4 bit mode
00077     write4bits(0x03 << 4);
00078     wait_us(4100); // wait min 4.1ms
00079     // second try
00080     write4bits(0x03 << 4);
00081     wait_us(4100); // wait min 4.1ms
00082     // third go!
00083     write4bits(0x03 << 4);
00084     wait_us(150);
00085     // finally, set to 4-bit interface
00086     write4bits(0x02 << 4);
00087     // set # lines, font size, etc.
00088     COMMAND(LCD_FUNCTIONSET | _displayfunction);
00089     // turn the display on with no cursor or blinking default
00090     _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
00091     display();
00092     // clear it off
00093     clear();
00094     // Initialize to default text direction (for roman languages)
00095     _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
00096     // set the entry mode
00097     COMMAND(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
00098     home();
00099 }
00100 void LiquidCrystal_I2C::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
00101     _cols = cols;
00102     _rows = lines;
00103     begin_priv();
00104 }
00105 
00106 /********** high level commands, for the user! */
00107 void LiquidCrystal_I2C::clear() {
00108     COMMAND(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
00109     wait_us(2000);             // this command takes a long time!
00110 }
00111 
00112 void LiquidCrystal_I2C::home() {
00113     COMMAND(LCD_RETURNHOME); // set cursor position to zero
00114     wait_us(2000);           // this command takes a long time!
00115 }
00116 
00117 void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row) {
00118     int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
00119     if (row > _numlines)
00120         row = _numlines - 1; // we count rows starting w/0
00121     COMMAND(LCD_SETDDRAMADDR | (col + row_offsets[row]));
00122 }
00123 
00124 // Turn the display on/off (quickly)
00125 void LiquidCrystal_I2C::noDisplay() {
00126     _displaycontrol &= ~LCD_DISPLAYON;
00127     COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
00128 }
00129 void LiquidCrystal_I2C::display() {
00130     _displaycontrol |= LCD_DISPLAYON;
00131     COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
00132 }
00133 
00134 // Turns the underline cursor on/off
00135 void LiquidCrystal_I2C::noCursor() {
00136     _displaycontrol &= ~LCD_CURSORON;
00137     COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
00138 }
00139 void LiquidCrystal_I2C::cursor() {
00140     _displaycontrol |= LCD_CURSORON;
00141     COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
00142 }
00143 
00144 // Turn on and off the blinking cursor
00145 void LiquidCrystal_I2C::noBlink() {
00146     _displaycontrol &= ~LCD_BLINKON;
00147     COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
00148 }
00149 void LiquidCrystal_I2C::blink() {
00150     _displaycontrol |= LCD_BLINKON;
00151     COMMAND(LCD_DISPLAYCONTROL | _displaycontrol);
00152 }
00153 
00154 // These commands scroll the display without changing the RAM
00155 void LiquidCrystal_I2C::scrollDisplayLeft(void) {
00156     COMMAND(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
00157 }
00158 void LiquidCrystal_I2C::scrollDisplayRight(void) {
00159     COMMAND(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
00160 }
00161 
00162 // This is for text that flows Left to Right
00163 void LiquidCrystal_I2C::leftToRight(void) {
00164     _displaymode |= LCD_ENTRYLEFT;
00165     COMMAND(LCD_ENTRYMODESET | _displaymode);
00166 }
00167 
00168 // This is for text that flows Right to Left
00169 void LiquidCrystal_I2C::rightToLeft(void) {
00170     _displaymode &= ~LCD_ENTRYLEFT;
00171     COMMAND(LCD_ENTRYMODESET | _displaymode);
00172 }
00173 
00174 // This will 'right justify' text from the cursor
00175 void LiquidCrystal_I2C::autoscroll(void) {
00176     _displaymode |= LCD_ENTRYSHIFTINCREMENT;
00177     COMMAND(LCD_ENTRYMODESET | _displaymode);
00178 }
00179 
00180 // This will 'left justify' text from the cursor
00181 void LiquidCrystal_I2C::noAutoscroll(void) {
00182     _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
00183     COMMAND(LCD_ENTRYMODESET | _displaymode);
00184 }
00185 
00186 // Allows us to fill the first 8 CGRAM locations
00187 // with custom characters
00188 void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
00189     location &= 0x7; // we only have 8 locations 0-7
00190     COMMAND(LCD_SETCGRAMADDR | (location << 3));
00191     for (uint8_t i = 0; i != 8; i++)
00192         write(charmap[i]);
00193 }
00194 
00195 // Turn the (optional) backlight off/on
00196 void LiquidCrystal_I2C::noBacklight(void) {
00197     _backlightval = LCD_NOBACKLIGHT;
00198     expanderWrite(0);
00199 }
00200 
00201 void LiquidCrystal_I2C::backlight(void) {
00202     _backlightval = LCD_BACKLIGHT;
00203     expanderWrite(0);
00204 }
00205 
00206 /************ low level data pushing commands **********/
00207 
00208 // write either command or data
00209 void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
00210     uint8_t highnib = value & 0xf0;
00211     uint8_t lownib = (value << 4) & 0xf0;
00212     write4bits((highnib) | mode);
00213     write4bits((lownib) | mode);
00214 }
00215 
00216 void LiquidCrystal_I2C::write4bits(uint8_t value) {
00217     expanderWrite(value);
00218     pulseEnable(value);
00219 }
00220 char buff;
00221 inline void LiquidCrystal_I2C::expanderWrite(uint8_t _data) {
00222     buff = (_data) | _backlightval;
00223     printIIC(&buff);
00224 }
00225 
00226 void LiquidCrystal_I2C::pulseEnable(uint8_t _data) {
00227     expanderWrite(_data | En); // En high
00228     wait_us(1);                // enable pulse must be >450ns
00229 
00230     expanderWrite(_data & ~En); // En low
00231     wait_us(10);                // commands need > 37us to settle
00232 }
00233 
00234 // Alias functions
00235 
00236 inline void LiquidCrystal_I2C::cursor_on() {
00237     cursor();
00238 }
00239 
00240 inline void LiquidCrystal_I2C::cursor_off() {
00241     noCursor();
00242 }
00243 
00244 inline void LiquidCrystal_I2C::blink_on() {
00245     blink();
00246 }
00247 
00248 inline void LiquidCrystal_I2C::blink_off() {
00249     noBlink();
00250 }
00251 
00252 inline void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows) {
00253     createChar(char_num, rows);
00254 }
00255 
00256 void LiquidCrystal_I2C::setBacklight(uint8_t new_val) {
00257     if (new_val)
00258         backlight(); // turn backlight on
00259     else
00260         noBacklight(); // turn backlight off
00261 }
00262 
00263 void LiquidCrystal_I2C::printstr(const char c[]) {
00264     // This function is not identical to the function used for "real" I2C displays
00265     // it's here so the use sketch doesn't have to be changed
00266     print(c);
00267 }
00268 
00269 // unsupported API functions
00270 void LiquidCrystal_I2C::off() {
00271     noBacklight();
00272 }
00273 void LiquidCrystal_I2C::on() {
00274     begin_priv();
00275     backlight();
00276 }
00277 void LiquidCrystal_I2C::setDelay(int cmdDelay, int charDelay) {}
00278 uint8_t LiquidCrystal_I2C::status() {
00279     return 0;
00280 }
00281 uint8_t LiquidCrystal_I2C::keypad() {
00282     return 0;
00283 }
00284 uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype) {
00285     return 0;
00286 }
00287 void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column,
00288     uint8_t len,
00289     uint8_t pixel_col_end) {
00290 }
00291 void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column,
00292     uint8_t len,
00293     uint8_t pixel_row_end) {
00294 }
00295 void LiquidCrystal_I2C::setContrast(uint8_t new_val) {}