├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── githubci.yml ├── Adafruit_RGBLCDShield.cpp ├── Adafruit_RGBLCDShield.h ├── README.md ├── examples └── HelloWorld │ └── HelloWorld.ino ├── keywords.txt ├── library.properties ├── license.txt └── utility ├── Adafruit_MCP23017.cpp └── Adafruit_MCP23017.h /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py main_platforms 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit RGB LCD Shield Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /Adafruit_RGBLCDShield.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_RGBLCDShield.cpp 3 | * 4 | * @mainpage Adafruit RGB LCD Shield Library 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * This is a library for the Adafruit RGB 16x2 LCD Shield 9 | * Pick one up at the Adafruit shop! 10 | * ---------> http://http://www.adafruit.com/products/714 11 | * 12 | * The shield uses I2C to communicate, 2 pins are required to 13 | * interface 14 | * Adafruit invests time and resources providing this open source code, 15 | * please support Adafruit and open-source hardware by purchasing 16 | * products from Adafruit! 17 | * 18 | * @section author Author 19 | * 20 | * Written by Limor Fried/Ladyada for Adafruit Industries. 21 | * @section license License 22 | * 23 | * BSD license, all text above must be included in any redistribution 24 | */ 25 | 26 | #include "Adafruit_RGBLCDShield.h" 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #ifdef __SAM3X8E__ // Arduino Due 33 | #define WIRE Wire1 34 | #else 35 | #define WIRE Wire //!< Specifies which name to use for the I2C bus 36 | #endif 37 | 38 | #if ARDUINO >= 100 39 | #include "Arduino.h" 40 | #else 41 | #include "WProgram.h" 42 | #endif 43 | 44 | // When the display powers up, it is configured as follows: 45 | // 46 | // 1. Display clear 47 | // 2. Function set: 48 | // DL = 1; 8-bit interface data 49 | // N = 0; 1-line display 50 | // F = 0; 5x8 dot character font 51 | // 3. Display on/off control: 52 | // D = 0; Display off 53 | // C = 0; Cursor off 54 | // B = 0; Blinking off 55 | // 4. Entry mode set: 56 | // I/D = 1; Increment by 1 57 | // S = 0; No shift 58 | // 59 | // Note, however, that resetting the Arduino doesn't reset the LCD, so we 60 | // can't assume that its in that state when a sketch starts (and the 61 | // RGBLCDShield constructor is called). 62 | 63 | Adafruit_RGBLCDShield::Adafruit_RGBLCDShield() { 64 | _i2cAddr = 0; 65 | 66 | _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 67 | 68 | // the I/O expander pinout 69 | _rs_pin = 15; 70 | _rw_pin = 14; 71 | _enable_pin = 13; 72 | _data_pins[0] = 12; // really d4 73 | _data_pins[1] = 11; // really d5 74 | _data_pins[2] = 10; // really d6 75 | _data_pins[3] = 9; // really d7 76 | 77 | _button_pins[0] = 0; 78 | _button_pins[1] = 1; 79 | _button_pins[2] = 2; 80 | _button_pins[3] = 3; 81 | _button_pins[4] = 4; 82 | // we can't begin() yet :( 83 | } 84 | 85 | void Adafruit_RGBLCDShield::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, 86 | uint8_t enable, uint8_t d0, uint8_t d1, 87 | uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, 88 | uint8_t d6, uint8_t d7) { 89 | _rs_pin = rs; 90 | _rw_pin = rw; 91 | _enable_pin = enable; 92 | 93 | _data_pins[0] = d0; 94 | _data_pins[1] = d1; 95 | _data_pins[2] = d2; 96 | _data_pins[3] = d3; 97 | _data_pins[4] = d4; 98 | _data_pins[5] = d5; 99 | _data_pins[6] = d6; 100 | _data_pins[7] = d7; 101 | 102 | _i2cAddr = 255; 103 | 104 | _pinMode(_rs_pin, OUTPUT); 105 | // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin# 106 | if (_rw_pin != 255) { 107 | _pinMode(_rw_pin, OUTPUT); 108 | } 109 | _pinMode(_enable_pin, OUTPUT); 110 | 111 | if (fourbitmode) 112 | _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 113 | else 114 | _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; 115 | 116 | begin(16, 1); 117 | } 118 | 119 | void Adafruit_RGBLCDShield::begin(uint8_t cols, uint8_t lines, 120 | uint8_t dotsize) { 121 | // check if i2c 122 | if (_i2cAddr != 255) { 123 | //_i2c.begin(_i2cAddr); 124 | WIRE.begin(); 125 | _i2c.begin(); 126 | 127 | _i2c.pinMode(8, OUTPUT); 128 | _i2c.pinMode(6, OUTPUT); 129 | _i2c.pinMode(7, OUTPUT); 130 | setBacklight(0x7); 131 | 132 | if (_rw_pin) 133 | _i2c.pinMode(_rw_pin, OUTPUT); 134 | 135 | _i2c.pinMode(_rs_pin, OUTPUT); 136 | _i2c.pinMode(_enable_pin, OUTPUT); 137 | for (uint8_t i = 0; i < 4; i++) 138 | _i2c.pinMode(_data_pins[i], OUTPUT); 139 | 140 | for (uint8_t i = 0; i < 5; i++) { 141 | _i2c.pinMode(_button_pins[i], INPUT); 142 | _i2c.pullUp(_button_pins[i], 1); 143 | } 144 | } 145 | 146 | if (lines > 1) { 147 | _displayfunction |= LCD_2LINE; 148 | } 149 | _numlines = lines; 150 | _currline = 0; 151 | 152 | // for some 1 line displays you can select a 10 pixel high font 153 | if ((dotsize != 0) && (lines == 1)) { 154 | _displayfunction |= LCD_5x10DOTS; 155 | } 156 | 157 | // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 158 | // according to datasheet, we need at least 40ms after power rises above 2.7V 159 | // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 160 | // 50 161 | delayMicroseconds(50000); 162 | // Now we pull both RS and R/W low to begin commands 163 | _digitalWrite(_rs_pin, LOW); 164 | _digitalWrite(_enable_pin, LOW); 165 | if (_rw_pin != 255) { 166 | _digitalWrite(_rw_pin, LOW); 167 | } 168 | 169 | // put the LCD into 4 bit or 8 bit mode 170 | if (!(_displayfunction & LCD_8BITMODE)) { 171 | // this is according to the hitachi HD44780 datasheet 172 | // figure 24, pg 46 173 | 174 | // we start in 8bit mode, try to set 4 bit mode 175 | write4bits(0x03); 176 | delayMicroseconds(4500); // wait min 4.1ms 177 | 178 | // second try 179 | write4bits(0x03); 180 | delayMicroseconds(4500); // wait min 4.1ms 181 | 182 | // third go! 183 | write4bits(0x03); 184 | delayMicroseconds(150); 185 | 186 | // finally, set to 8-bit interface 187 | write4bits(0x02); 188 | } else { 189 | // this is according to the hitachi HD44780 datasheet 190 | // page 45 figure 23 191 | 192 | // Send function set command sequence 193 | command(LCD_FUNCTIONSET | _displayfunction); 194 | delayMicroseconds(4500); // wait more than 4.1ms 195 | 196 | // second try 197 | command(LCD_FUNCTIONSET | _displayfunction); 198 | delayMicroseconds(150); 199 | 200 | // third go 201 | command(LCD_FUNCTIONSET | _displayfunction); 202 | } 203 | 204 | // finally, set # lines, font size, etc. 205 | command(LCD_FUNCTIONSET | _displayfunction); 206 | 207 | // turn the display on with no cursor or blinking default 208 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 209 | display(); 210 | 211 | // clear it off 212 | clear(); 213 | 214 | // Initialize to default text direction (for romance languages) 215 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 216 | // set the entry mode 217 | command(LCD_ENTRYMODESET | _displaymode); 218 | } 219 | 220 | /********** high level commands, for the user! */ 221 | void Adafruit_RGBLCDShield::clear() { 222 | command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 223 | delayMicroseconds(2000); // this command takes a long time! 224 | } 225 | 226 | void Adafruit_RGBLCDShield::home() { 227 | command(LCD_RETURNHOME); // set cursor position to zero 228 | delayMicroseconds(2000); // this command takes a long time! 229 | } 230 | 231 | void Adafruit_RGBLCDShield::setCursor(uint8_t col, uint8_t row) { 232 | int row_offsets[] = {0x00, 0x40, 0x14, 0x54}; 233 | if (row > _numlines) { 234 | row = _numlines - 1; // we count rows starting w/0 235 | } 236 | 237 | command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 238 | } 239 | 240 | // Turn the display on/off (quickly) 241 | void Adafruit_RGBLCDShield::noDisplay() { 242 | _displaycontrol &= ~LCD_DISPLAYON; 243 | command(LCD_DISPLAYCONTROL | _displaycontrol); 244 | } 245 | void Adafruit_RGBLCDShield::display() { 246 | _displaycontrol |= LCD_DISPLAYON; 247 | command(LCD_DISPLAYCONTROL | _displaycontrol); 248 | } 249 | 250 | // Turns the underline cursor on/off 251 | void Adafruit_RGBLCDShield::noCursor() { 252 | _displaycontrol &= ~LCD_CURSORON; 253 | command(LCD_DISPLAYCONTROL | _displaycontrol); 254 | } 255 | void Adafruit_RGBLCDShield::cursor() { 256 | _displaycontrol |= LCD_CURSORON; 257 | command(LCD_DISPLAYCONTROL | _displaycontrol); 258 | } 259 | 260 | // Turn on and off the blinking cursor 261 | void Adafruit_RGBLCDShield::noBlink() { 262 | _displaycontrol &= ~LCD_BLINKON; 263 | command(LCD_DISPLAYCONTROL | _displaycontrol); 264 | } 265 | void Adafruit_RGBLCDShield::blink() { 266 | _displaycontrol |= LCD_BLINKON; 267 | command(LCD_DISPLAYCONTROL | _displaycontrol); 268 | } 269 | 270 | // These commands scroll the display without changing the RAM 271 | void Adafruit_RGBLCDShield::scrollDisplayLeft(void) { 272 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 273 | } 274 | void Adafruit_RGBLCDShield::scrollDisplayRight(void) { 275 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 276 | } 277 | 278 | // This is for text that flows Left to Right 279 | void Adafruit_RGBLCDShield::leftToRight(void) { 280 | _displaymode |= LCD_ENTRYLEFT; 281 | command(LCD_ENTRYMODESET | _displaymode); 282 | } 283 | 284 | // This is for text that flows Right to Left 285 | void Adafruit_RGBLCDShield::rightToLeft(void) { 286 | _displaymode &= ~LCD_ENTRYLEFT; 287 | command(LCD_ENTRYMODESET | _displaymode); 288 | } 289 | 290 | // This will 'right justify' text from the cursor 291 | void Adafruit_RGBLCDShield::autoscroll(void) { 292 | _displaymode |= LCD_ENTRYSHIFTINCREMENT; 293 | command(LCD_ENTRYMODESET | _displaymode); 294 | } 295 | 296 | // This will 'left justify' text from the cursor 297 | void Adafruit_RGBLCDShield::noAutoscroll(void) { 298 | _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 299 | command(LCD_ENTRYMODESET | _displaymode); 300 | } 301 | 302 | // Allows us to fill the first 8 CGRAM locations 303 | // with custom characters 304 | void Adafruit_RGBLCDShield::createChar(uint8_t location, uint8_t charmap[]) { 305 | location &= 0x7; // we only have 8 locations 0-7 306 | command(LCD_SETCGRAMADDR | (location << 3)); 307 | for (int i = 0; i < 8; i++) { 308 | write(charmap[i]); 309 | } 310 | command(LCD_SETDDRAMADDR); // unfortunately resets the location to 0,0 311 | } 312 | 313 | /*********** mid level commands, for sending data/cmds */ 314 | 315 | inline void Adafruit_RGBLCDShield::command(uint8_t value) { send(value, LOW); } 316 | 317 | #if ARDUINO >= 100 318 | inline size_t Adafruit_RGBLCDShield::write(uint8_t value) { 319 | send(value, HIGH); 320 | return 1; 321 | } 322 | #else 323 | inline void Adafruit_RGBLCDShield::write(uint8_t value) { send(value, HIGH); } 324 | #endif 325 | 326 | /************ low level data pushing commands **********/ 327 | 328 | // little wrapper for i/o writes 329 | void Adafruit_RGBLCDShield::_digitalWrite(uint8_t p, uint8_t d) { 330 | if (_i2cAddr != 255) { 331 | // an i2c command 332 | _i2c.digitalWrite(p, d); 333 | } else { 334 | // straightup IO 335 | digitalWrite(p, d); 336 | } 337 | } 338 | 339 | // Allows to set the backlight, if the LCD backpack is used 340 | void Adafruit_RGBLCDShield::setBacklight(uint8_t status) { 341 | // check if i2c or SPI 342 | _i2c.digitalWrite(8, ~(status >> 2) & 0x1); 343 | _i2c.digitalWrite(7, ~(status >> 1) & 0x1); 344 | _i2c.digitalWrite(6, ~status & 0x1); 345 | } 346 | 347 | // little wrapper for i/o directions 348 | void Adafruit_RGBLCDShield::_pinMode(uint8_t p, uint8_t d) { 349 | if (_i2cAddr != 255) { 350 | // an i2c command 351 | _i2c.pinMode(p, d); 352 | } else { 353 | // straightup IO 354 | pinMode(p, d); 355 | } 356 | } 357 | 358 | // write either command or data, with automatic 4/8-bit selection 359 | void Adafruit_RGBLCDShield::send(uint8_t value, uint8_t mode) { 360 | _digitalWrite(_rs_pin, mode); 361 | 362 | // if there is a RW pin indicated, set it low to Write 363 | if (_rw_pin != 255) { 364 | _digitalWrite(_rw_pin, LOW); 365 | } 366 | 367 | if (_displayfunction & LCD_8BITMODE) { 368 | write8bits(value); 369 | } else { 370 | write4bits(value >> 4); 371 | write4bits(value); 372 | } 373 | } 374 | 375 | void Adafruit_RGBLCDShield::pulseEnable(void) { 376 | _digitalWrite(_enable_pin, LOW); 377 | delayMicroseconds(1); 378 | _digitalWrite(_enable_pin, HIGH); 379 | delayMicroseconds(1); // enable pulse must be >450ns 380 | _digitalWrite(_enable_pin, LOW); 381 | delayMicroseconds(100); // commands need > 37us to settle 382 | } 383 | 384 | void Adafruit_RGBLCDShield::write4bits(uint8_t value) { 385 | if (_i2cAddr != 255) { 386 | uint16_t out = 0; 387 | 388 | out = _i2c.readGPIOAB(); 389 | 390 | // speed up for i2c since its sluggish 391 | for (int i = 0; i < 4; i++) { 392 | out &= ~(1 << _data_pins[i]); 393 | out |= ((value >> i) & 0x1) << _data_pins[i]; 394 | } 395 | 396 | // make sure enable is low 397 | out &= ~(1 << _enable_pin); 398 | 399 | _i2c.writeGPIOAB(out); 400 | 401 | // pulse enable 402 | delayMicroseconds(1); 403 | out |= (1 << _enable_pin); 404 | _i2c.writeGPIOAB(out); 405 | delayMicroseconds(1); 406 | out &= ~(1 << _enable_pin); 407 | _i2c.writeGPIOAB(out); 408 | delayMicroseconds(100); 409 | 410 | } else { 411 | for (int i = 0; i < 4; i++) { 412 | _pinMode(_data_pins[i], OUTPUT); 413 | _digitalWrite(_data_pins[i], (value >> i) & 0x01); 414 | } 415 | pulseEnable(); 416 | } 417 | } 418 | 419 | void Adafruit_RGBLCDShield::write8bits(uint8_t value) { 420 | for (int i = 0; i < 8; i++) { 421 | _pinMode(_data_pins[i], OUTPUT); 422 | _digitalWrite(_data_pins[i], (value >> i) & 0x01); 423 | } 424 | 425 | pulseEnable(); 426 | } 427 | 428 | uint8_t Adafruit_RGBLCDShield::readButtons(void) { 429 | uint8_t reply = 0x1F; 430 | 431 | for (uint8_t i = 0; i < 5; i++) { 432 | reply &= ~((_i2c.digitalRead(_button_pins[i])) << i); 433 | } 434 | return reply; 435 | } 436 | -------------------------------------------------------------------------------- /Adafruit_RGBLCDShield.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_RGBLCDShield.h 3 | */ 4 | 5 | #ifndef Adafruit_RGBLCDShield_h 6 | #define Adafruit_RGBLCDShield_h 7 | 8 | #include "Print.h" 9 | #include 10 | #include 11 | 12 | // commands 13 | #define LCD_CLEARDISPLAY 0x01 //!< Clear display, set cursor position to zero 14 | #define LCD_RETURNHOME 0x02 //!< Set cursor position to zero 15 | #define LCD_ENTRYMODESET 0x04 //!< Sets the entry mode 16 | #define LCD_DISPLAYCONTROL \ 17 | 0x08 //!< Controls the display; allows you to do stuff like turn it on and off 18 | #define LCD_CURSORSHIFT 0x10 //!< Lets you move the cursor 19 | #define LCD_FUNCTIONSET 0x20 //!< Used to send the function set to the display 20 | #define LCD_SETCGRAMADDR \ 21 | 0x40 //!< Used to set the CGRAM (character generator RAM) 22 | #define LCD_SETDDRAMADDR 0x80 //!< Used to set the DDRAM (display data RAM) 23 | 24 | // flags for display entry mode 25 | #define LCD_ENTRYRIGHT 0x00 //!< Used to set text to flow from right to left 26 | #define LCD_ENTRYLEFT 0x02 //!< Used to set text to flow from left to right 27 | #define LCD_ENTRYSHIFTINCREMENT \ 28 | 0x01 //!< Used to 'right justify' text from the cursor 29 | #define LCD_ENTRYSHIFTDECREMENT \ 30 | 0x00 //!< USed to 'left justify' text from the cursor 31 | 32 | // flags for display on/off control 33 | #define LCD_DISPLAYON 0x04 //!< Turns the display on 34 | #define LCD_DISPLAYOFF 0x00 //!< Turns the display off 35 | #define LCD_CURSORON 0x02 //!< Turns the cursor on 36 | #define LCD_CURSOROFF 0x00 //!< Turns the cursor off 37 | #define LCD_BLINKON 0x01 //!< Turns on the blinking cursor 38 | #define LCD_BLINKOFF 0x00 //!< Turns off the blinking cursor 39 | 40 | // flags for display/cursor shift 41 | #define LCD_DISPLAYMOVE 0x08 //!< Flag for moving the display 42 | #define LCD_CURSORMOVE 0x00 //!< Flag for moving the cursor 43 | #define LCD_MOVERIGHT 0x04 //!< Flag for moving right 44 | #define LCD_MOVELEFT 0x00 //!< Flag for moving left 45 | 46 | // flags for function set 47 | #define LCD_8BITMODE 0x10 //!< LCD 8 bit mode 48 | #define LCD_4BITMODE 0x00 //!< LCD 4 bit mode 49 | #define LCD_2LINE 0x08 //!< LCD 2 line mode 50 | #define LCD_1LINE 0x00 //!< LCD 1 line mode 51 | #define LCD_5x10DOTS 0x04 //!< 10 pixel high font mode 52 | #define LCD_5x8DOTS 0x00 //!< 8 pixel high font mode 53 | 54 | #define BUTTON_UP 0x08 //!< Up button 55 | #define BUTTON_DOWN 0x04 //!< Down button 56 | #define BUTTON_LEFT 0x10 //!< Left button 57 | #define BUTTON_RIGHT 0x02 //!< Right button 58 | #define BUTTON_SELECT 0x01 //!< Select button 59 | 60 | #ifdef ARDUINO_ARCH_MEGAAVR 61 | using namespace arduino; //!< MEGA AVR architecture uses the arduino namespace 62 | #endif //!< but AVR arch does not 63 | 64 | /*! 65 | * @brief Base class for RGB LCD shield 66 | */ 67 | class Adafruit_RGBLCDShield : public Print { 68 | public: 69 | Adafruit_RGBLCDShield(); 70 | 71 | /*! 72 | * @brief RGB LCD shield constructor 73 | * @param fourbitmode Sets the mode of the display, either 4 bit or 8 bit 74 | * @param rs The reset data line 75 | * @param rw The read write pin 76 | * @param enable The enable data line 77 | * @param d0 The data line 0 78 | * @param d1 The data line 1 79 | * @param d2 The data line 2 80 | * @param d3 The data line 3 81 | * @param d4 The data line 4 82 | * @param d5 The data line 5 83 | * @param d6 The data line 6 84 | * @param d7 The data line 7 85 | */ 86 | void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, 87 | uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, 88 | uint8_t d5, uint8_t d6, uint8_t d7); 89 | 90 | /*! 91 | * @brief Starts I2C connection with display 92 | * @param cols Sets the number of columns 93 | * @param rows Sets the number of rows 94 | * @param charsize Sets the character size 95 | * @return Returns true if the connection was successful 96 | */ 97 | void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); 98 | 99 | /*! 100 | * @brief High-level command to clear the display 101 | */ 102 | void clear(); 103 | /*! 104 | * @brief High-level command to set the cursor position to zero 105 | */ 106 | void home(); 107 | 108 | /*! 109 | * @brief High-level command to turn the display off 110 | */ 111 | void noDisplay(); 112 | /*! 113 | * @brief High-level command to turn the display on 114 | */ 115 | void display(); 116 | /*! 117 | * @brief High-level command to turn off the blinking cursor off 118 | */ 119 | void noBlink(); 120 | /*! 121 | * @brief High-level command to turn on the blinking cursor 122 | */ 123 | void blink(); 124 | /*! 125 | * @brief High-level command to turn the underline cursor off 126 | */ 127 | void noCursor(); 128 | /*! 129 | * @brief High-level command to turn the underline cursor on 130 | */ 131 | void cursor(); 132 | /*! 133 | * @brief High-level command to scroll display left without changing the RAM 134 | */ 135 | void scrollDisplayLeft(); 136 | /*! 137 | * @brief High-level command to scroll display right without changing the RAM 138 | */ 139 | void scrollDisplayRight(); 140 | /*! 141 | * @brief High-level command to make text flow right to left 142 | */ 143 | void leftToRight(); 144 | /*! 145 | * @brief High-level command to make text flow left to right 146 | */ 147 | void rightToLeft(); 148 | /*! 149 | * @brief High-level command to 'right justify' text from cursor 150 | */ 151 | void autoscroll(); 152 | /*! 153 | * @brief High-level command to 'left justify' text from cursor 154 | */ 155 | void noAutoscroll(); 156 | 157 | /*! 158 | * @brief High-level command to set the backlight, only if the LCD backpack is 159 | * used 160 | * @param status Status to set the backlight 161 | */ 162 | void setBacklight(uint8_t status); 163 | 164 | /*! 165 | * @brief High-level command that creates custom characters in CGRAM 166 | * @param location Location in cgram to fill 167 | * @param charmap[] Character map to use 168 | */ 169 | void createChar(uint8_t, uint8_t[]); 170 | /*! 171 | * @brief High-level command that sets the location of the cursor 172 | * @param col Column to put the cursor in 173 | * @param row Row to put the cursor in 174 | */ 175 | void setCursor(uint8_t, uint8_t); 176 | #if ARDUINO >= 100 177 | virtual size_t write(uint8_t); 178 | #else 179 | /*! 180 | * @brief Mid-level command that sends data to the display 181 | * @param value Data to send to the display 182 | */ 183 | virtual void write(uint8_t); 184 | #endif 185 | /*! 186 | * @brief Sends command to display 187 | * @param value Command to send 188 | */ 189 | void command(uint8_t); 190 | /*! 191 | * @brief reads the buttons from the shield 192 | * @return Returns what buttons have been pressed 193 | */ 194 | uint8_t readButtons(); 195 | 196 | private: 197 | void send(uint8_t, uint8_t); 198 | void write4bits(uint8_t); 199 | void write8bits(uint8_t); 200 | void pulseEnable(); 201 | void _digitalWrite(uint8_t, uint8_t); 202 | void _pinMode(uint8_t, uint8_t); 203 | 204 | uint8_t _rs_pin; // LOW: command. HIGH: character. 205 | uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD. 206 | uint8_t _enable_pin; // activated by a HIGH pulse. 207 | uint8_t _data_pins[8]; 208 | uint8_t _button_pins[5]; 209 | uint8_t _displayfunction; 210 | uint8_t _displaycontrol; 211 | uint8_t _displaymode; 212 | 213 | uint8_t _initialized; 214 | 215 | uint8_t _numlines, _currline; 216 | 217 | uint8_t _i2cAddr; 218 | Adafruit_MCP23017 _i2c; 219 | }; 220 | 221 | #endif 222 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit RGB LCD Shield Library [![Build Status](https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit-RGB-LCD-Shield-Library/html/index.html) 2 | 3 | This is a library for the Adafruit RGB 16x2 LCD Shield 4 | 5 | Pick one up at the Adafruit shop! 6 | ---------> https://www.adafruit.com/products/714 7 | 8 | This new Adafruit shield makes it easy to use a 16x2 Character LCD. We really like the range of LCDs we stock in the shop, such as our classic blue & white as well as the fancy RGB negative and RGB positive. Unfortunately, these LCDs do require quite a few digital pins, 6 to control the LCD and then perhaps another 3 to control the RGB backlight for a total of 9 pins. That's half of the pins available on a classic Arduino! 9 | 10 | With this in mind, we wanted to make it easier for people to get these LCD into their projects so we devised a shield that lets you control a 16x2 Character LCD, up to 3 backlight pins AND 5 keypad pins using only the two I2C pins on the Arduino! The best part is you don't really lose those two pins either, since you can stick i2c-based sensors, RTCs, etc and have them share the I2C bus. This is a super slick way to add a display without all the wiring hassle. 11 | 12 |
13 | 14 | Adafruit invests time and resources providing this open source code, 15 | please support Adafruit and open-source hardware by purchasing 16 | products from Adafruit! 17 | 18 | Written by Limor Fried/Ladyada for Adafruit Industries. 19 | BSD license, check license.txt for more information 20 | All text above must be included in any redistribution 21 | 22 | To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_RGBLCDShield. Check that the Adafruit_RGBLCDShield folder contains Adafruit_RGBLCDShield.cpp and Adafruit_RGBLCDShield.h 23 | 24 | Place the Adafruit_RGBLCDShield library folder your /libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE. 25 | -------------------------------------------------------------------------------- /examples/HelloWorld/HelloWorld.ino: -------------------------------------------------------------------------------- 1 | /********************* 2 | 3 | Example code for the Adafruit RGB Character LCD Shield and Library 4 | 5 | This code displays text on the shield, and also reads the buttons on the keypad. 6 | When a button is pressed, the backlight changes color. 7 | 8 | **********************/ 9 | 10 | // include the library code: 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | // The shield uses the I2C SCL and SDA pins. On classic Arduinos 17 | // this is Analog 4 and 5 so you can't use those for analogRead() anymore 18 | // However, you can connect other I2C sensors to the I2C bus and share 19 | // the I2C bus. 20 | Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield(); 21 | 22 | // These #defines make it easy to set the backlight color 23 | #define RED 0x1 24 | #define YELLOW 0x3 25 | #define GREEN 0x2 26 | #define TEAL 0x6 27 | #define BLUE 0x4 28 | #define VIOLET 0x5 29 | #define WHITE 0x7 30 | 31 | void setup() { 32 | // Debugging output 33 | Serial.begin(9600); 34 | // set up the LCD's number of columns and rows: 35 | lcd.begin(16, 2); 36 | 37 | // Print a message to the LCD. We track how long it takes since 38 | // this library has been optimized a bit and we're proud of it :) 39 | int time = millis(); 40 | lcd.print("Hello, world!"); 41 | time = millis() - time; 42 | Serial.print("Took "); Serial.print(time); Serial.println(" ms"); 43 | lcd.setBacklight(WHITE); 44 | } 45 | 46 | uint8_t i=0; 47 | void loop() { 48 | // set the cursor to column 0, line 1 49 | // (note: line 1 is the second row, since counting begins with 0): 50 | lcd.setCursor(0, 1); 51 | // print the number of seconds since reset: 52 | lcd.print(millis()/1000); 53 | 54 | uint8_t buttons = lcd.readButtons(); 55 | 56 | if (buttons) { 57 | lcd.clear(); 58 | lcd.setCursor(0,0); 59 | if (buttons & BUTTON_UP) { 60 | lcd.print("UP "); 61 | lcd.setBacklight(RED); 62 | } 63 | if (buttons & BUTTON_DOWN) { 64 | lcd.print("DOWN "); 65 | lcd.setBacklight(YELLOW); 66 | } 67 | if (buttons & BUTTON_LEFT) { 68 | lcd.print("LEFT "); 69 | lcd.setBacklight(GREEN); 70 | } 71 | if (buttons & BUTTON_RIGHT) { 72 | lcd.print("RIGHT "); 73 | lcd.setBacklight(TEAL); 74 | } 75 | if (buttons & BUTTON_SELECT) { 76 | lcd.print("SELECT "); 77 | lcd.setBacklight(VIOLET); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For LiquidCrystal 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | LiquidCrystal KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | clear KEYWORD2 17 | home KEYWORD2 18 | print KEYWORD2 19 | setCursor KEYWORD2 20 | cursor KEYWORD2 21 | noCursor KEYWORD2 22 | blink KEYWORD2 23 | noBlink KEYWORD2 24 | display KEYWORD2 25 | noDisplay KEYWORD2 26 | autoscroll KEYWORD2 27 | noAutoscroll KEYWORD2 28 | leftToRight KEYWORD2 29 | rightToLeft KEYWORD2 30 | scrollDisplayLeft KEYWORD2 31 | scrollDisplayRight KEYWORD2 32 | createChar KEYWORD2 33 | setBacklight KEYWORD2 34 | 35 | ####################################### 36 | # Constants (LITERAL1) 37 | ####################################### 38 | 39 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit RGB LCD Shield Library 2 | version=1.2.2 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Library for the Adafruit RGB 16x2 LCD Shield. 6 | paragraph=Library for the Adafruit RGB 16x2 LCD Shield. 7 | category=Display 8 | url=https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2012, Adafruit Industries 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of the copyright holders nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /utility/Adafruit_MCP23017.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for the MCP23017 i2c port expander 3 | 4 | These displays use I2C to communicate, 2 pins are required to 5 | interface 6 | Adafruit invests time and resources providing this open source code, 7 | please support Adafruit and open-source hardware by purchasing 8 | products from Adafruit! 9 | 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | #include 15 | #ifdef __AVR 16 | #include 17 | #elif defined(ESP8266) 18 | #include 19 | #endif 20 | #include "Adafruit_MCP23017.h" 21 | #ifdef __SAM3X8E__ // Arduino Due 22 | #define WIRE Wire1 23 | #else 24 | #define WIRE Wire 25 | #endif 26 | 27 | #if ARDUINO >= 100 28 | #include "Arduino.h" 29 | #else 30 | #include "WProgram.h" 31 | #endif 32 | 33 | // minihelper 34 | static inline void wiresend(uint8_t x) { 35 | #if ARDUINO >= 100 36 | WIRE.write((uint8_t)x); 37 | #else 38 | WIRE.send(x); 39 | #endif 40 | } 41 | 42 | static inline uint8_t wirerecv(void) { 43 | #if ARDUINO >= 100 44 | return WIRE.read(); 45 | #else 46 | return WIRE.receive(); 47 | #endif 48 | } 49 | 50 | //////////////////////////////////////////////////////////////////////////////// 51 | 52 | void Adafruit_MCP23017::begin(uint8_t addr) { 53 | if (addr > 7) { 54 | addr = 7; 55 | } 56 | i2caddr = addr; 57 | 58 | WIRE.begin(); 59 | 60 | // set defaults! 61 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 62 | wiresend(MCP23017_IODIRA); 63 | wiresend(0xFF); // all inputs on port A 64 | WIRE.endTransmission(); 65 | 66 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 67 | wiresend(MCP23017_IODIRB); 68 | wiresend(0xFF); // all inputs on port B 69 | WIRE.endTransmission(); 70 | } 71 | 72 | void Adafruit_MCP23017::begin(void) { begin(0); } 73 | 74 | void Adafruit_MCP23017::pinMode(uint8_t p, uint8_t d) { 75 | uint8_t iodir; 76 | uint8_t iodiraddr; 77 | 78 | // only 16 bits! 79 | if (p > 15) 80 | return; 81 | 82 | if (p < 8) 83 | iodiraddr = MCP23017_IODIRA; 84 | else { 85 | iodiraddr = MCP23017_IODIRB; 86 | p -= 8; 87 | } 88 | 89 | // read the current IODIR 90 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 91 | wiresend(iodiraddr); 92 | WIRE.endTransmission(); 93 | 94 | WIRE.requestFrom(MCP23017_ADDRESS | i2caddr, 1); 95 | iodir = wirerecv(); 96 | 97 | // set the pin and direction 98 | if (d == INPUT) { 99 | iodir |= 1 << p; 100 | } else { 101 | iodir &= ~(1 << p); 102 | } 103 | 104 | // write the new IODIR 105 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 106 | wiresend(iodiraddr); 107 | wiresend(iodir); 108 | WIRE.endTransmission(); 109 | } 110 | 111 | uint16_t Adafruit_MCP23017::readGPIOAB() { 112 | uint16_t ba = 0; 113 | uint8_t a; 114 | 115 | // read the current GPIO output latches 116 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 117 | wiresend(MCP23017_GPIOA); 118 | WIRE.endTransmission(); 119 | 120 | WIRE.requestFrom(MCP23017_ADDRESS | i2caddr, 2); 121 | a = wirerecv(); 122 | ba = wirerecv(); 123 | ba <<= 8; 124 | ba |= a; 125 | 126 | return ba; 127 | } 128 | 129 | void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) { 130 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 131 | wiresend(MCP23017_GPIOA); 132 | wiresend(ba & 0xFF); 133 | wiresend(ba >> 8); 134 | WIRE.endTransmission(); 135 | } 136 | 137 | void Adafruit_MCP23017::digitalWrite(uint8_t p, uint8_t d) { 138 | uint8_t gpio; 139 | uint8_t gpioaddr, olataddr; 140 | 141 | // only 16 bits! 142 | if (p > 15) 143 | return; 144 | 145 | if (p < 8) { 146 | olataddr = MCP23017_OLATA; 147 | gpioaddr = MCP23017_GPIOA; 148 | } else { 149 | olataddr = MCP23017_OLATB; 150 | gpioaddr = MCP23017_GPIOB; 151 | p -= 8; 152 | } 153 | 154 | // read the current GPIO output latches 155 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 156 | wiresend(olataddr); 157 | WIRE.endTransmission(); 158 | 159 | WIRE.requestFrom(MCP23017_ADDRESS | i2caddr, 1); 160 | gpio = wirerecv(); 161 | 162 | // set the pin and direction 163 | if (d == HIGH) { 164 | gpio |= 1 << p; 165 | } else { 166 | gpio &= ~(1 << p); 167 | } 168 | 169 | // write the new GPIO 170 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 171 | wiresend(gpioaddr); 172 | wiresend(gpio); 173 | WIRE.endTransmission(); 174 | } 175 | 176 | void Adafruit_MCP23017::pullUp(uint8_t p, uint8_t d) { 177 | uint8_t gppu; 178 | uint8_t gppuaddr; 179 | 180 | // only 16 bits! 181 | if (p > 15) 182 | return; 183 | 184 | if (p < 8) 185 | gppuaddr = MCP23017_GPPUA; 186 | else { 187 | gppuaddr = MCP23017_GPPUB; 188 | p -= 8; 189 | } 190 | 191 | // read the current pullup resistor set 192 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 193 | wiresend(gppuaddr); 194 | WIRE.endTransmission(); 195 | 196 | WIRE.requestFrom(MCP23017_ADDRESS | i2caddr, 1); 197 | gppu = wirerecv(); 198 | 199 | // set the pin and direction 200 | if (d == HIGH) { 201 | gppu |= 1 << p; 202 | } else { 203 | gppu &= ~(1 << p); 204 | } 205 | 206 | // write the new GPIO 207 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 208 | wiresend(gppuaddr); 209 | wiresend(gppu); 210 | WIRE.endTransmission(); 211 | } 212 | 213 | uint8_t Adafruit_MCP23017::digitalRead(uint8_t p) { 214 | uint8_t gpioaddr; 215 | 216 | // only 16 bits! 217 | if (p > 15) 218 | return 0; 219 | 220 | if (p < 8) 221 | gpioaddr = MCP23017_GPIOA; 222 | else { 223 | gpioaddr = MCP23017_GPIOB; 224 | p -= 8; 225 | } 226 | 227 | // read the current GPIO 228 | WIRE.beginTransmission(MCP23017_ADDRESS | i2caddr); 229 | wiresend(gpioaddr); 230 | WIRE.endTransmission(); 231 | 232 | WIRE.requestFrom(MCP23017_ADDRESS | i2caddr, 1); 233 | return (wirerecv() >> p) & 0x1; 234 | } 235 | -------------------------------------------------------------------------------- /utility/Adafruit_MCP23017.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for the MCP23017 i2c port expander 3 | 4 | These displays use I2C to communicate, 2 pins are required to 5 | interface 6 | Adafruit invests time and resources providing this open source code, 7 | please support Adafruit and open-source hardware by purchasing 8 | products from Adafruit! 9 | 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | #ifndef _Adafruit_MCP23017_H_ 15 | #define _Adafruit_MCP23017_H_ 16 | 17 | // Don't forget the Wire library 18 | class Adafruit_MCP23017 { 19 | public: 20 | void begin(uint8_t addr); 21 | void begin(void); 22 | 23 | void pinMode(uint8_t p, uint8_t d); 24 | void digitalWrite(uint8_t p, uint8_t d); 25 | void pullUp(uint8_t p, uint8_t d); 26 | uint8_t digitalRead(uint8_t p); 27 | 28 | void writeGPIOAB(uint16_t); 29 | uint16_t readGPIOAB(); 30 | 31 | private: 32 | uint8_t i2caddr; 33 | }; 34 | 35 | #define MCP23017_ADDRESS 0x20 36 | 37 | // registers 38 | #define MCP23017_IODIRA 0x00 39 | #define MCP23017_IPOLA 0x02 40 | #define MCP23017_GPINTENA 0x04 41 | #define MCP23017_DEFVALA 0x06 42 | #define MCP23017_INTCONA 0x08 43 | #define MCP23017_IOCONA 0x0A 44 | #define MCP23017_GPPUA 0x0C 45 | #define MCP23017_INTFA 0x0E 46 | #define MCP23017_INTCAPA 0x10 47 | #define MCP23017_GPIOA 0x12 48 | #define MCP23017_OLATA 0x14 49 | 50 | #define MCP23017_IODIRB 0x01 51 | #define MCP23017_IPOLB 0x03 52 | #define MCP23017_GPINTENB 0x05 53 | #define MCP23017_DEFVALB 0x07 54 | #define MCP23017_INTCONB 0x09 55 | #define MCP23017_IOCONB 0x0B 56 | #define MCP23017_GPPUB 0x0D 57 | #define MCP23017_INTFB 0x0F 58 | #define MCP23017_INTCAPB 0x11 59 | #define MCP23017_GPIOB 0x13 60 | #define MCP23017_OLATB 0x15 61 | 62 | #endif 63 | --------------------------------------------------------------------------------