transplanted from the original URL : https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library
Embed:
(wiki syntax)
Show/hide line numbers
Adafruit_I2C_LCD.cpp
00001 /*************************************************** 00002 This is a library for the Adafruit RGB 16x2 LCD Shield 00003 Pick one up at the Adafruit shop! 00004 ---------> http://http://www.adafruit.com/products/714 00005 00006 The shield uses I2C to communicate, 2 pins are required to 00007 interface 00008 Adafruit invests time and resources providing this open source code, 00009 please support Adafruit and open-source hardware by purchasing 00010 products from Adafruit! 00011 00012 Written by Limor Fried/Ladyada for Adafruit Industries. 00013 BSD license, all text above must be included in any redistribution 00014 ****************************************************/ 00015 00016 00017 #include "Adafruit_I2C_LCD.h" 00018 00019 #include <stdio.h> 00020 #include <string.h> 00021 #include <inttypes.h> 00022 00023 // When the display powers up, it is configured as follows: 00024 // 00025 // 1. Display clear 00026 // 2. Function set: 00027 // DL = 1; 8-bit interface data 00028 // N = 0; 1-line display 00029 // F = 0; 5x8 dot character font 00030 // 3. Display on/off control: 00031 // D = 0; Display off 00032 // C = 0; Cursor off 00033 // B = 0; Blinking off 00034 // 4. Entry mode set: 00035 // I/D = 1; Increment by 1 00036 // S = 0; No shift 00037 // 00038 // Note, however, that resetting the Arduino doesn't reset the LCD, so we 00039 // can't assume that its in that state when a sketch starts (and the 00040 // RGBLCDShield constructor is called). 00041 00042 Adafruit_I2C_LCD::Adafruit_I2C_LCD(I2C *master, uint8_t cols, uint8_t lines, uint8_t dotsize) 00043 { 00044 _i2c = new Adafruit_MCP23017(master); 00045 _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 00046 00047 // the I/O expander pinout 00048 _rs_pin = 15; 00049 _rw_pin = 14; 00050 _enable_pin = 13; 00051 _data_pins[0] = 12; // really d4 00052 _data_pins[1] = 11; // really d5 00053 _data_pins[2] = 10; // really d6 00054 _data_pins[3] = 9; // really d7 00055 00056 _button_pins[0] = 0; 00057 _button_pins[1] = 1; 00058 _button_pins[2] = 2; 00059 _button_pins[3] = 3; 00060 _button_pins[4] = 4; 00061 00062 begin(cols, lines, dotsize); 00063 } 00064 00065 Adafruit_I2C_LCD::~Adafruit_I2C_LCD() 00066 { 00067 delete _i2c; 00068 } 00069 00070 /********** high level commands, for the user! */ 00071 void Adafruit_I2C_LCD::clear() 00072 { 00073 command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 00074 wait_us(2000); // this command takes a long time! 00075 } 00076 00077 void Adafruit_I2C_LCD::home() 00078 { 00079 command(LCD_RETURNHOME); // set cursor position to zero 00080 wait_us(2000); // this command takes a long time! 00081 } 00082 00083 void Adafruit_I2C_LCD::setCursor(uint8_t col, uint8_t row) 00084 { 00085 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 00086 if ( row > _numlines ) { 00087 row = _numlines-1; // we count rows starting w/0 00088 } 00089 00090 command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 00091 } 00092 00093 // Turn the display on/off (quickly) 00094 void Adafruit_I2C_LCD::noDisplay() 00095 { 00096 _displaycontrol &= ~LCD_DISPLAYON; 00097 command(LCD_DISPLAYCONTROL | _displaycontrol); 00098 } 00099 void Adafruit_I2C_LCD::display() 00100 { 00101 _displaycontrol |= LCD_DISPLAYON; 00102 command(LCD_DISPLAYCONTROL | _displaycontrol); 00103 } 00104 00105 // Turns the underline cursor on/off 00106 void Adafruit_I2C_LCD::noCursor() 00107 { 00108 _displaycontrol &= ~LCD_CURSORON; 00109 command(LCD_DISPLAYCONTROL | _displaycontrol); 00110 } 00111 void Adafruit_I2C_LCD::cursor() 00112 { 00113 _displaycontrol |= LCD_CURSORON; 00114 command(LCD_DISPLAYCONTROL | _displaycontrol); 00115 } 00116 00117 // Turn on and off the blinking cursor 00118 void Adafruit_I2C_LCD::noBlink() 00119 { 00120 _displaycontrol &= ~LCD_BLINKON; 00121 command(LCD_DISPLAYCONTROL | _displaycontrol); 00122 } 00123 void Adafruit_I2C_LCD::blink() 00124 { 00125 _displaycontrol |= LCD_BLINKON; 00126 command(LCD_DISPLAYCONTROL | _displaycontrol); 00127 } 00128 00129 // These commands scroll the display without changing the RAM 00130 void Adafruit_I2C_LCD::scrollDisplayLeft(void) 00131 { 00132 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 00133 } 00134 void Adafruit_I2C_LCD::scrollDisplayRight(void) 00135 { 00136 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 00137 } 00138 00139 // This is for text that flows Left to Right 00140 void Adafruit_I2C_LCD::leftToRight(void) 00141 { 00142 _displaymode |= LCD_ENTRYLEFT; 00143 command(LCD_ENTRYMODESET | _displaymode); 00144 } 00145 00146 // This is for text that flows Right to Left 00147 void Adafruit_I2C_LCD::rightToLeft(void) 00148 { 00149 _displaymode &= ~LCD_ENTRYLEFT; 00150 command(LCD_ENTRYMODESET | _displaymode); 00151 } 00152 00153 // This will 'right justify' text from the cursor 00154 void Adafruit_I2C_LCD::autoscroll(void) 00155 { 00156 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 00157 command(LCD_ENTRYMODESET | _displaymode); 00158 } 00159 00160 // This will 'left justify' text from the cursor 00161 void Adafruit_I2C_LCD::noAutoscroll(void) 00162 { 00163 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 00164 command(LCD_ENTRYMODESET | _displaymode); 00165 } 00166 00167 // Allows us to fill the first 8 CGRAM locations 00168 // with custom characters 00169 void Adafruit_I2C_LCD::createChar(uint8_t location, uint8_t charmap[]) 00170 { 00171 location &= 0x7; // we only have 8 locations 0-7 00172 command(LCD_SETCGRAMADDR | (location << 3)); 00173 for (int i=0; i<8; i++) { 00174 write(charmap[i]); 00175 } 00176 command(LCD_SETDDRAMADDR); // unfortunately resets the location to 0,0 00177 } 00178 00179 /*********** mid level commands, for sending data/cmds */ 00180 00181 void Adafruit_I2C_LCD::command(uint8_t value) 00182 { 00183 send(value, LOW); 00184 } 00185 00186 00187 void Adafruit_I2C_LCD::write(uint8_t value) 00188 { 00189 send(value, HIGH); 00190 } 00191 00192 void Adafruit_I2C_LCD::print(char *array, size_t array_size) 00193 { 00194 for(size_t i = 0; i < array_size; i++){ 00195 if(array[i] == '\0') 00196 break; 00197 send(array[i], HIGH); 00198 } 00199 } 00200 00201 /************ low level data pushing commands **********/ 00202 00203 // little wrapper for i/o writes 00204 void Adafruit_I2C_LCD::_digitalWrite(uint8_t p, uint8_t d) 00205 { 00206 _i2c->digitalWrite(p, d); 00207 } 00208 00209 // Allows to set the backlight, if the LCD backpack is used 00210 void Adafruit_I2C_LCD::setBacklight(uint8_t status) 00211 { 00212 // check if i2c or SPI 00213 _i2c->digitalWrite(8, ~(status >> 2) & 0x1); 00214 _i2c->digitalWrite(7, ~(status >> 1) & 0x1); 00215 _i2c->digitalWrite(6, ~status & 0x1); 00216 } 00217 00218 // little wrapper for i/o directions 00219 void Adafruit_I2C_LCD::_pinMode(uint8_t p, uint8_t d) 00220 { 00221 _i2c->pinMode(p, d); 00222 } 00223 00224 void Adafruit_I2C_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) 00225 { 00226 _i2c->pinMode(8, OUTPUT); 00227 _i2c->pinMode(6, OUTPUT); 00228 _i2c->pinMode(7, OUTPUT); 00229 setBacklight(0x7); 00230 00231 if (_rw_pin) 00232 _i2c->pinMode(_rw_pin, OUTPUT); 00233 00234 _i2c->pinMode(_rs_pin, OUTPUT); 00235 _i2c->pinMode(_enable_pin, OUTPUT); 00236 for (uint8_t i=0; i<4; i++) 00237 _i2c->pinMode(_data_pins[i], OUTPUT); 00238 00239 for (uint8_t i=0; i<5; i++) { 00240 _i2c->pinMode(_button_pins[i], INPUT); 00241 _i2c->pullUp(_button_pins[i], 1); 00242 } 00243 00244 if (lines > 1) { 00245 _displayfunction |= LCD_2LINE; 00246 } 00247 _numlines = lines; 00248 _currline = 0; 00249 00250 // for some 1 line displays you can select a 10 pixel high font 00251 if ((dotsize != 0) && (lines == 1)) { 00252 _displayfunction |= LCD_5x10DOTS; 00253 } 00254 00255 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 00256 // according to datasheet, we need at least 40ms after power rises above 2.7V 00257 // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 00258 wait_us(50000); 00259 // Now we pull both RS and R/W low to begin commands 00260 _digitalWrite(_rs_pin, LOW); 00261 _digitalWrite(_enable_pin, LOW); 00262 if (_rw_pin != 255) { 00263 _digitalWrite(_rw_pin, LOW); 00264 } 00265 00266 //put the LCD into 4 bit or 8 bit mode 00267 if (! (_displayfunction & LCD_8BITMODE)) { 00268 // this is according to the hitachi HD44780 datasheet 00269 // figure 24, pg 46 00270 00271 // we start in 8bit mode, try to set 4 bit mode 00272 write4bits(0x03); 00273 wait_us(4500); // wait min 4.1ms 00274 00275 // second try 00276 write4bits(0x03); 00277 wait_us(4500); // wait min 4.1ms 00278 00279 // third go! 00280 write4bits(0x03); 00281 wait_us(150); 00282 00283 // finally, set to 8-bit interface 00284 write4bits(0x02); 00285 } else { 00286 // this is according to the hitachi HD44780 datasheet 00287 // page 45 figure 23 00288 00289 // Send function set command sequence 00290 command(LCD_FUNCTIONSET | _displayfunction); 00291 wait_us(4500); // wait more than 4.1ms 00292 00293 // second try 00294 command(LCD_FUNCTIONSET | _displayfunction); 00295 wait_us(150); 00296 00297 // third go 00298 command(LCD_FUNCTIONSET | _displayfunction); 00299 } 00300 00301 // finally, set # lines, font size, etc. 00302 command(LCD_FUNCTIONSET | _displayfunction); 00303 00304 // turn the display on with no cursor or blinking default 00305 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 00306 display(); 00307 00308 // clear it off 00309 clear(); 00310 00311 // Initialize to default text direction (for romance languages) 00312 _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 00313 // set the entry mode 00314 command(LCD_ENTRYMODESET | _displaymode); 00315 00316 } 00317 00318 // write either command or data, with automatic 4/8-bit selection 00319 void Adafruit_I2C_LCD::send(uint8_t value, uint8_t mode) 00320 { 00321 _digitalWrite(_rs_pin, mode); 00322 00323 // if there is a RW pin indicated, set it low to Write 00324 if (_rw_pin != 255) { 00325 _digitalWrite(_rw_pin, LOW); 00326 } 00327 00328 if (_displayfunction & LCD_8BITMODE) { 00329 write8bits(value); 00330 } else { 00331 write4bits(value>>4); 00332 write4bits(value); 00333 } 00334 } 00335 00336 void Adafruit_I2C_LCD::pulseEnable(void) 00337 { 00338 _digitalWrite(_enable_pin, LOW); 00339 wait_us(1); 00340 _digitalWrite(_enable_pin, HIGH); 00341 wait_us(1); // enable pulse must be >450ns 00342 _digitalWrite(_enable_pin, LOW); 00343 wait_us(100); // commands need > 37us to settle 00344 } 00345 00346 void Adafruit_I2C_LCD::write4bits(uint8_t value) 00347 { 00348 //if (_i2cAddr != 255) { 00349 uint16_t out = 0; 00350 00351 out = _i2c->readGPIOAB(); 00352 00353 // speed up for i2c since its sluggish 00354 for (int i = 0; i < 4; i++) { 00355 out &= ~(1 << _data_pins[i]); 00356 out |= ((value >> i) & 0x1) << _data_pins[i]; 00357 } 00358 00359 // make sure enable is low 00360 out &= ~(1 << _enable_pin); 00361 00362 _i2c->writeGPIOAB(out); 00363 00364 // pulse enable 00365 wait_us(1); 00366 out |= (1 << _enable_pin); 00367 _i2c->writeGPIOAB(out); 00368 wait_us(1); 00369 out &= ~(1 << _enable_pin); 00370 _i2c->writeGPIOAB(out); 00371 wait_us(100); 00372 00373 //} else { 00374 //for (int i = 0; i < 4; i++) { 00375 // _pinMode(_data_pins[i], OUTPUT); 00376 // _digitalWrite(_data_pins[i], (value >> i) & 0x01); 00377 //} 00378 //pulseEnable(); 00379 //} 00380 } 00381 00382 void Adafruit_I2C_LCD::write8bits(uint8_t value) 00383 { 00384 for (int i = 0; i < 8; i++) { 00385 _pinMode(_data_pins[i], OUTPUT); 00386 _digitalWrite(_data_pins[i], (value >> i) & 0x01); 00387 } 00388 00389 pulseEnable(); 00390 } 00391 00392 uint8_t Adafruit_I2C_LCD::readButtons(void) 00393 { 00394 uint8_t reply = 0x1F; 00395 00396 for (uint8_t i=0; i<5; i++) { 00397 reply &= ~((_i2c->digitalRead(_button_pins[i])) << i); 00398 } 00399 return reply; 00400 } 00401
Generated on Mon Jul 18 2022 20:57:22 by 1.7.2