Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of AdaFruit_RGBLCDShield by
AdaFruit_RGBLCDShield.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 #include "Adafruit_RGBLCDShield.h" 00017 00018 #include <stdio.h> 00019 #include <string.h> 00020 #include <inttypes.h> 00021 00022 // New MBED code to handle porting 00023 #define OUTPUT DIR_OUTPUT 00024 #define INPUT DIR_INPUT 00025 00026 #define LOW 0 00027 #define HIGH 1 00028 00029 #define delayMicroseconds(a) wait(a / 1000000) 00030 00031 /* MBED TURNED OFF 00032 00033 Arduino i2c (wire) interface 00034 00035 #include <Wire.h> 00036 #ifdef __AVR__ 00037 #define WIRE Wire 00038 #else // Arduino Due 00039 #define WIRE Wire1 00040 #endif 00041 00042 #if ARDUINO >= 100 00043 #include "Arduino.h" 00044 #else 00045 #include "WProgram.h" 00046 #endif 00047 */ 00048 00049 // When the display powers up, it is configured as follows: 00050 // 00051 // 1. Display clear 00052 // 2. Function set: 00053 // DL = 1; 8-bit interface data 00054 // N = 0; 1-line display 00055 // F = 0; 5x8 dot character font 00056 // 3. Display on/off control: 00057 // D = 0; Display off 00058 // C = 0; Cursor off 00059 // B = 0; Blinking off 00060 // 4. Entry mode set: 00061 // I/D = 1; Increment by 1 00062 // S = 0; No shift 00063 // 00064 // Note, however, that resetting the Arduino doesn't reset the LCD, so we 00065 // can't assume that its in that state when a sketch starts (and the 00066 // RGBLCDShield constructor is called). 00067 00068 // MBED - wired in serial 00069 // MBED - wired in _i2c 00070 Adafruit_RGBLCDShield::Adafruit_RGBLCDShield(MCP23017 & inMCP) 00071 : Serial(USBTX, USBRX) 00072 , _i2c(inMCP) 00073 { 00074 _i2cAddr = 0; 00075 00076 _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 00077 00078 // the I/O expander pinout 00079 _rs_pin = 15; 00080 _rw_pin = 14; 00081 _enable_pin = 13; 00082 _data_pins[0] = 12; // really d4 00083 _data_pins[1] = 11; // really d5 00084 _data_pins[2] = 10; // really d6 00085 _data_pins[3] = 9; // really d7 00086 00087 _button_pins[0] = 0; 00088 _button_pins[1] = 1; 00089 _button_pins[2] = 2; 00090 _button_pins[3] = 3; 00091 _button_pins[4] = 4; 00092 // we can't begin() yet :( 00093 } 00094 00095 Adafruit_RGBLCDShield::Adafruit_RGBLCDShield 00096 ( 00097 MCP23017 & inMCP, 00098 uint8_t inRs, 00099 uint8_t inRw, 00100 uint8_t inEn, 00101 uint8_t inD4, 00102 uint8_t inD5, 00103 uint8_t inD6, 00104 uint8_t inD7 00105 ) 00106 : Serial(USBTX, USBRX) 00107 , _i2c(inMCP) 00108 { 00109 _i2cAddr = 0; 00110 00111 _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 00112 00113 // the I/O expander pinout 00114 _rs_pin = inRs; 00115 _rw_pin = inRw; 00116 _enable_pin = inEn; 00117 _data_pins[0] = inD4; // really d4 00118 _data_pins[1] = inD5; // really d5 00119 _data_pins[2] = inD6; // really d6 00120 _data_pins[3] = inD7; // really d7 00121 00122 // we can't begin() yet :( 00123 } 00124 00125 void Adafruit_RGBLCDShield::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, 00126 uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, 00127 uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) 00128 { 00129 _rs_pin = rs; 00130 _rw_pin = rw; 00131 _enable_pin = enable; 00132 00133 _data_pins[0] = d0; 00134 _data_pins[1] = d1; 00135 _data_pins[2] = d2; 00136 _data_pins[3] = d3; 00137 _data_pins[4] = d4; 00138 _data_pins[5] = d5; 00139 _data_pins[6] = d6; 00140 _data_pins[7] = d7; 00141 00142 _i2cAddr = 255; 00143 00144 _pinMode(_rs_pin, OUTPUT); 00145 // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# 00146 if (_rw_pin != 255) { 00147 _pinMode(_rw_pin, OUTPUT); 00148 } 00149 _pinMode(_enable_pin, OUTPUT); 00150 00151 00152 if (fourbitmode) 00153 _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 00154 else 00155 _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; 00156 00157 begin(16, 1); 00158 } 00159 00160 void Adafruit_RGBLCDShield::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { 00161 // check if i2c 00162 if (_i2cAddr != 255) { 00163 //_i2c.begin(_i2cAddr); 00164 //WIRE.begin(); 00165 00166 _i2c.reset(); 00167 00168 _i2c.pinMode(8, OUTPUT); 00169 _i2c.pinMode(6, OUTPUT); 00170 _i2c.pinMode(7, OUTPUT); 00171 00172 // setBacklight(0x7); 00173 setBacklight(0x2); 00174 00175 00176 if (_rw_pin) 00177 _i2c.pinMode(_rw_pin, OUTPUT); 00178 00179 _i2c.pinMode(_rs_pin, OUTPUT); 00180 _i2c.pinMode(_enable_pin, OUTPUT); 00181 for (uint8_t i=0; i<4; i++) 00182 _i2c.pinMode(_data_pins[i], OUTPUT); 00183 00184 unsigned short nPullups = 0; 00185 for (uint8_t i=0; i<5; i++) { 00186 _i2c.pinMode(_button_pins[i], INPUT); 00187 nPullups |= (1 << _button_pins[i]); 00188 //_i2c.pullUp(_button_pins[i], 1); 00189 } 00190 00191 _i2c.internalPullupMask(nPullups); 00192 } 00193 00194 if (lines > 1) { 00195 _displayfunction |= LCD_2LINE; 00196 } 00197 _numlines = lines; 00198 _currline = 0; 00199 00200 // for some 1 line displays you can select a 10 pixel high font 00201 if ((dotsize != 0) && (lines == 1)) { 00202 _displayfunction |= LCD_5x10DOTS; 00203 } 00204 00205 // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 00206 // according to datasheet, we need at least 40ms after power rises above 2.7V 00207 // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 00208 delayMicroseconds(50000); 00209 // Now we pull both RS and R/W low to begin commands 00210 _digitalWrite(_rs_pin, LOW); 00211 _digitalWrite(_enable_pin, LOW); 00212 if (_rw_pin != 255) { 00213 _digitalWrite(_rw_pin, LOW); 00214 } 00215 00216 //put the LCD into 4 bit or 8 bit mode 00217 if (! (_displayfunction & LCD_8BITMODE)) { 00218 // this is according to the hitachi HD44780 datasheet 00219 // figure 24, pg 46 00220 00221 // we start in 8bit mode, try to set 4 bit mode 00222 write4bits(0x03); 00223 delayMicroseconds(4500); // wait min 4.1ms 00224 00225 // second try 00226 write4bits(0x03); 00227 delayMicroseconds(4500); // wait min 4.1ms 00228 00229 // third go! 00230 write4bits(0x03); 00231 delayMicroseconds(150); 00232 00233 // finally, set to 8-bit interface 00234 write4bits(0x02); 00235 } else { 00236 // this is according to the hitachi HD44780 datasheet 00237 // page 45 figure 23 00238 00239 // Send function set command sequence 00240 command(LCD_FUNCTIONSET | _displayfunction); 00241 delayMicroseconds(4500); // wait more than 4.1ms 00242 00243 // second try 00244 command(LCD_FUNCTIONSET | _displayfunction); 00245 delayMicroseconds(150); 00246 00247 // third go 00248 command(LCD_FUNCTIONSET | _displayfunction); 00249 } 00250 00251 // finally, set # lines, font size, etc. 00252 command(LCD_FUNCTIONSET | _displayfunction); 00253 00254 // turn the display on with no cursor or blinking default 00255 _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 00256 display(); 00257 00258 // clear it off 00259 clear(); 00260 00261 // Initialize to default text direction (for romance languages) 00262 _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 00263 // set the entry mode 00264 command(LCD_ENTRYMODESET | _displaymode); 00265 } 00266 00267 /********** high level commands, for the user! */ 00268 void Adafruit_RGBLCDShield::clear() 00269 { 00270 command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 00271 delayMicroseconds(2000); // this command takes a long time! 00272 } 00273 00274 void Adafruit_RGBLCDShield::home() 00275 { 00276 command(LCD_RETURNHOME); // set cursor position to zero 00277 delayMicroseconds(2000); // this command takes a long time! 00278 } 00279 00280 uint8_t Adafruit_RGBLCDShield::lines() 00281 { 00282 return _numlines; 00283 } 00284 00285 void Adafruit_RGBLCDShield::setCursor(uint8_t col, uint8_t row) 00286 { 00287 int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 00288 if ( row > _numlines ) { 00289 row = _numlines-1; // we count rows starting w/0 00290 } 00291 00292 command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 00293 } 00294 00295 // Turn the display on/off (quickly) 00296 void Adafruit_RGBLCDShield::noDisplay() { 00297 _displaycontrol &= ~LCD_DISPLAYON; 00298 command(LCD_DISPLAYCONTROL | _displaycontrol); 00299 } 00300 void Adafruit_RGBLCDShield::display() { 00301 _displaycontrol |= LCD_DISPLAYON; 00302 command(LCD_DISPLAYCONTROL | _displaycontrol); 00303 } 00304 00305 // Turns the underline cursor on/off 00306 void Adafruit_RGBLCDShield::noCursor() { 00307 _displaycontrol &= ~LCD_CURSORON; 00308 command(LCD_DISPLAYCONTROL | _displaycontrol); 00309 } 00310 void Adafruit_RGBLCDShield::cursor() { 00311 _displaycontrol |= LCD_CURSORON; 00312 command(LCD_DISPLAYCONTROL | _displaycontrol); 00313 } 00314 00315 // Turn on and off the blinking cursor 00316 void Adafruit_RGBLCDShield::noBlink() { 00317 _displaycontrol &= ~LCD_BLINKON; 00318 command(LCD_DISPLAYCONTROL | _displaycontrol); 00319 } 00320 void Adafruit_RGBLCDShield::blink() { 00321 _displaycontrol |= LCD_BLINKON; 00322 command(LCD_DISPLAYCONTROL | _displaycontrol); 00323 } 00324 00325 // These commands scroll the display without changing the RAM 00326 void Adafruit_RGBLCDShield::scrollDisplayLeft(void) { 00327 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 00328 } 00329 void Adafruit_RGBLCDShield::scrollDisplayRight(void) { 00330 command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 00331 } 00332 00333 // This is for text that flows Left to Right 00334 void Adafruit_RGBLCDShield::leftToRight(void) { 00335 _displaymode |= LCD_ENTRYLEFT; 00336 command(LCD_ENTRYMODESET | _displaymode); 00337 } 00338 00339 // This is for text that flows Right to Left 00340 void Adafruit_RGBLCDShield::rightToLeft(void) { 00341 _displaymode &= ~LCD_ENTRYLEFT; 00342 command(LCD_ENTRYMODESET | _displaymode); 00343 } 00344 00345 // This will 'right justify' text from the cursor 00346 void Adafruit_RGBLCDShield::autoscroll(void) { 00347 _displaymode |= LCD_ENTRYSHIFTINCREMENT; 00348 command(LCD_ENTRYMODESET | _displaymode); 00349 } 00350 00351 // This will 'left justify' text from the cursor 00352 void Adafruit_RGBLCDShield::noAutoscroll(void) { 00353 _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 00354 command(LCD_ENTRYMODESET | _displaymode); 00355 } 00356 00357 // Allows us to fill the first 8 CGRAM locations 00358 // with custom characters 00359 void Adafruit_RGBLCDShield::createChar(uint8_t location, uint8_t charmap[]) { 00360 location &= 0x7; // we only have 8 locations 0-7 00361 command(LCD_SETCGRAMADDR | (location << 3)); 00362 for (int i=0; i<8; i++) { 00363 _putc(charmap[i]); 00364 } 00365 command(LCD_SETDDRAMADDR); // unfortunately resets the location to 0,0 00366 } 00367 00368 /*********** mid level commands, for sending data/cmds */ 00369 00370 inline void Adafruit_RGBLCDShield::command(uint8_t value) { 00371 send(value, LOW); 00372 } 00373 00374 #if ARDUINO >= 100 00375 inline size_t Adafruit_RGBLCDShield::write(uint8_t value) { 00376 send(value, HIGH); 00377 return 1; 00378 } 00379 #else 00380 //inline void Adafruit_RGBLCDShield::write(uint8_t value) { 00381 int Adafruit_RGBLCDShield::_putc(int value) { 00382 send(value, HIGH); 00383 return 1; 00384 } 00385 #endif 00386 00387 /************ low level data pushing commands **********/ 00388 00389 // little wrapper for i/o writes 00390 void Adafruit_RGBLCDShield::_digitalWrite(uint8_t p, uint8_t d) { 00391 if (_i2cAddr != 255) { 00392 // an i2c command 00393 _i2c.digitalWrite(p, d); 00394 } else { 00395 // straightup IO 00396 // MBED TURNED OFF 00397 //digitalWrite(p, d); 00398 } 00399 } 00400 00401 // Allows to set the backlight, if the LCD backpack is used 00402 void Adafruit_RGBLCDShield::setBacklight(uint8_t status) { 00403 // check if i2c or SPI 00404 _i2c.digitalWrite(8, ~(status >> 2) & 0x1); 00405 _i2c.digitalWrite(7, ~(status >> 1) & 0x1); 00406 _i2c.digitalWrite(6, ~status & 0x1); 00407 } 00408 00409 // little wrapper for i/o directions 00410 void Adafruit_RGBLCDShield::_pinMode(uint8_t p, uint8_t d) { 00411 if (_i2cAddr != 255) { 00412 // an i2c command 00413 _i2c.pinMode(p, d); 00414 } else { 00415 // straightup IO 00416 // MBED TURNED OFF 00417 //pinMode(p, d); 00418 } 00419 } 00420 00421 // write either command or data, with automatic 4/8-bit selection 00422 void Adafruit_RGBLCDShield::send(uint8_t value, uint8_t mode) { 00423 _digitalWrite(_rs_pin, mode); 00424 00425 // if there is a RW pin indicated, set it low to Write 00426 if (_rw_pin != 255) { 00427 _digitalWrite(_rw_pin, LOW); 00428 } 00429 00430 if (_displayfunction & LCD_8BITMODE) { 00431 write8bits(value); 00432 } else { 00433 write4bits(value>>4); 00434 write4bits(value); 00435 } 00436 } 00437 00438 void Adafruit_RGBLCDShield::pulseEnable(void) { 00439 _digitalWrite(_enable_pin, LOW); 00440 delayMicroseconds(1); 00441 _digitalWrite(_enable_pin, HIGH); 00442 delayMicroseconds(1); // enable pulse must be >450ns 00443 _digitalWrite(_enable_pin, LOW); 00444 delayMicroseconds(100); // commands need > 37us to settle 00445 } 00446 00447 void Adafruit_RGBLCDShield::write4bits(uint8_t value) { 00448 if (_i2cAddr != 255) { 00449 uint16_t out = 0; 00450 00451 //out = _i2c.readGPIOAB(); 00452 out = _i2c.digitalWordRead(); 00453 00454 // speed up for i2c since its sluggish 00455 for (int i = 0; i < 4; i++) { 00456 out &= ~(1 << _data_pins[i]); 00457 out |= ((value >> i) & 0x1) << _data_pins[i]; 00458 } 00459 00460 // make sure enable is low 00461 out &= ~(1 << _enable_pin); 00462 00463 //_i2c.writeGPIOAB(out); 00464 _i2c.digitalWordWrite(out); 00465 00466 // pulse enable 00467 delayMicroseconds(1); 00468 out |= (1 << _enable_pin); 00469 //_i2c.writeGPIOAB(out); 00470 _i2c.digitalWordWrite(out); 00471 00472 delayMicroseconds(1); 00473 out &= ~(1 << _enable_pin); 00474 00475 //_i2c.writeGPIOAB(out); 00476 _i2c.digitalWordWrite(out); 00477 00478 delayMicroseconds(100); 00479 00480 } else { 00481 for (int i = 0; i < 4; i++) { 00482 _pinMode(_data_pins[i], OUTPUT); 00483 _digitalWrite(_data_pins[i], (value >> i) & 0x01); 00484 } 00485 pulseEnable(); 00486 } 00487 } 00488 00489 void Adafruit_RGBLCDShield::write8bits(uint8_t value) { 00490 for (int i = 0; i < 8; i++) { 00491 _pinMode(_data_pins[i], OUTPUT); 00492 _digitalWrite(_data_pins[i], (value >> i) & 0x01); 00493 } 00494 00495 pulseEnable(); 00496 } 00497 00498 uint8_t Adafruit_RGBLCDShield::readButtons(void) { 00499 uint8_t reply = 0x1F; 00500 00501 for (uint8_t i=0; i<5; i++) { 00502 reply &= ~((_i2c.digitalRead(_button_pins[i])) << i); 00503 } 00504 return reply; 00505 }
Generated on Wed Jul 13 2022 17:31:40 by
1.7.2
