├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── Adafruit_TFTLCD.cpp ├── Adafruit_TFTLCD.h ├── README.md ├── assets └── image.jpg ├── bitmaps ├── miniwoof.bmp ├── test.bmp └── woof.bmp ├── examples ├── graphicstest │ └── graphicstest.ino ├── rotationtest │ └── rotationtest.ino ├── tftbmp │ └── tftbmp.ino ├── tftbmp_shield │ └── tftbmp_shield.ino ├── tftpaint │ └── tftpaint.ino └── tftpaint_shield │ ├── glcdfont.c │ └── tftpaint_shield.ino ├── library.properties ├── pin_magic.h └── registers.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 | -------------------------------------------------------------------------------- /Adafruit_TFTLCD.cpp: -------------------------------------------------------------------------------- 1 | // IMPORTANT: LIBRARY MUST BE SPECIFICALLY CONFIGURED FOR EITHER TFT SHIELD 2 | // OR BREAKOUT BOARD USAGE. SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h 3 | 4 | // Graphics library by ladyada/adafruit with init code from Rossum 5 | // MIT license 6 | 7 | #if defined(__SAM3X8E__) 8 | #include 9 | #define PROGMEM 10 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 11 | #define pgm_read_word(addr) (*(const unsigned short *)(addr)) 12 | #endif 13 | #ifdef __AVR__ 14 | #include 15 | #endif 16 | #include "Adafruit_TFTLCD.h" 17 | #include "pin_magic.h" 18 | #include "pins_arduino.h" 19 | #include "wiring_private.h" 20 | 21 | //#define TFTWIDTH 320 22 | //#define TFTHEIGHT 480 23 | 24 | #define TFTWIDTH 240 25 | #define TFTHEIGHT 320 26 | 27 | // LCD controller chip identifiers 28 | #define ID_932X 0 29 | #define ID_7575 1 30 | #define ID_9341 2 31 | #define ID_HX8357D 3 32 | #define ID_UNKNOWN 0xFF 33 | 34 | #include "registers.h" 35 | 36 | // Constructor for breakout board (configurable LCD control lines). 37 | // Can still use this w/shield, but parameters are ignored. 38 | Adafruit_TFTLCD::Adafruit_TFTLCD(uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, 39 | uint8_t reset) 40 | : Adafruit_GFX(TFTWIDTH, TFTHEIGHT) { 41 | 42 | #ifndef USE_ADAFRUIT_SHIELD_PINOUT 43 | // Convert pin numbers to registers and bitmasks 44 | _reset = reset; 45 | #ifdef __AVR__ 46 | csPort = portOutputRegister(digitalPinToPort(cs)); 47 | cdPort = portOutputRegister(digitalPinToPort(cd)); 48 | wrPort = portOutputRegister(digitalPinToPort(wr)); 49 | rdPort = portOutputRegister(digitalPinToPort(rd)); 50 | #endif 51 | #if defined(__SAM3X8E__) 52 | csPort = digitalPinToPort(cs); 53 | cdPort = digitalPinToPort(cd); 54 | wrPort = digitalPinToPort(wr); 55 | rdPort = digitalPinToPort(rd); 56 | #endif 57 | csPinSet = digitalPinToBitMask(cs); 58 | cdPinSet = digitalPinToBitMask(cd); 59 | wrPinSet = digitalPinToBitMask(wr); 60 | rdPinSet = digitalPinToBitMask(rd); 61 | csPinUnset = ~csPinSet; 62 | cdPinUnset = ~cdPinSet; 63 | wrPinUnset = ~wrPinSet; 64 | rdPinUnset = ~rdPinSet; 65 | #ifdef __AVR__ 66 | *csPort |= csPinSet; // Set all control bits to HIGH (idle) 67 | *cdPort |= cdPinSet; // Signals are ACTIVE LOW 68 | *wrPort |= wrPinSet; 69 | *rdPort |= rdPinSet; 70 | #endif 71 | #if defined(__SAM3X8E__) 72 | csPort->PIO_SODR |= csPinSet; // Set all control bits to HIGH (idle) 73 | cdPort->PIO_SODR |= cdPinSet; // Signals are ACTIVE LOW 74 | wrPort->PIO_SODR |= wrPinSet; 75 | rdPort->PIO_SODR |= rdPinSet; 76 | #endif 77 | pinMode(cs, OUTPUT); // Enable outputs 78 | pinMode(cd, OUTPUT); 79 | pinMode(wr, OUTPUT); 80 | pinMode(rd, OUTPUT); 81 | if (reset) { 82 | digitalWrite(reset, HIGH); 83 | pinMode(reset, OUTPUT); 84 | } 85 | #endif 86 | 87 | init(); 88 | } 89 | 90 | // Constructor for shield (fixed LCD control lines) 91 | Adafruit_TFTLCD::Adafruit_TFTLCD(void) : Adafruit_GFX(TFTWIDTH, TFTHEIGHT) { 92 | init(); 93 | } 94 | 95 | // Initialization common to both shield & breakout configs 96 | void Adafruit_TFTLCD::init(void) { 97 | 98 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 99 | CS_IDLE; // Set all control bits to idle state 100 | WR_IDLE; 101 | RD_IDLE; 102 | CD_DATA; 103 | digitalWrite(5, HIGH); // Reset line 104 | pinMode(A3, OUTPUT); // Enable outputs 105 | pinMode(A2, OUTPUT); 106 | pinMode(A1, OUTPUT); 107 | pinMode(A0, OUTPUT); 108 | pinMode(5, OUTPUT); 109 | #endif 110 | 111 | setWriteDir(); // Set up LCD data port(s) for WRITE operations 112 | 113 | rotation = 0; 114 | cursor_y = cursor_x = 0; 115 | textcolor = 0xFFFF; 116 | _width = TFTWIDTH; 117 | _height = TFTHEIGHT; 118 | } 119 | 120 | // Initialization command tables for different LCD controllers 121 | #define TFTLCD_DELAY 0xFF 122 | static const uint8_t HX8347G_regValues[] PROGMEM = { 123 | 0x2E, 0x89, 0x29, 0x8F, 0x2B, 0x02, 0xE2, 0x00, 0xE4, 0x01, 0xE5, 0x10, 124 | 0xE6, 0x01, 0xE7, 0x10, 0xE8, 0x70, 0xF2, 0x00, 0xEA, 0x00, 0xEB, 0x20, 125 | 0xEC, 0x3C, 0xED, 0xC8, 0xE9, 0x38, 0xF1, 0x01, 126 | 127 | // skip gamma, do later 128 | 129 | 0x1B, 0x1A, 0x1A, 0x02, 0x24, 0x61, 0x25, 0x5C, 130 | 131 | 0x18, 0x36, 0x19, 0x01, 0x1F, 0x88, TFTLCD_DELAY, 5, // delay 5 ms 132 | 0x1F, 0x80, TFTLCD_DELAY, 5, 0x1F, 0x90, TFTLCD_DELAY, 5, 0x1F, 0xD4, 133 | TFTLCD_DELAY, 5, 0x17, 0x05, 134 | 135 | 0x36, 0x09, 0x28, 0x38, TFTLCD_DELAY, 40, 0x28, 0x3C, 136 | 137 | 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0xEF, 0x06, 0x00, 0x07, 0x00, 138 | 0x08, 0x01, 0x09, 0x3F}; 139 | 140 | static const uint8_t HX8357D_regValues[] PROGMEM = { 141 | HX8357_SWRESET, 142 | 0, 143 | HX8357D_SETC, 144 | 3, 145 | 0xFF, 146 | 0x83, 147 | 0x57, 148 | TFTLCD_DELAY, 149 | 250, 150 | HX8357_SETRGB, 151 | 4, 152 | 0x00, 153 | 0x00, 154 | 0x06, 155 | 0x06, 156 | HX8357D_SETCOM, 157 | 1, 158 | 0x25, // -1.52V 159 | HX8357_SETOSC, 160 | 1, 161 | 0x68, // Normal mode 70Hz, Idle mode 55 Hz 162 | HX8357_SETPANEL, 163 | 1, 164 | 0x05, // BGR, Gate direction swapped 165 | HX8357_SETPWR1, 166 | 6, 167 | 0x00, 168 | 0x15, 169 | 0x1C, 170 | 0x1C, 171 | 0x83, 172 | 0xAA, 173 | HX8357D_SETSTBA, 174 | 6, 175 | 0x50, 176 | 0x50, 177 | 0x01, 178 | 0x3C, 179 | 0x1E, 180 | 0x08, 181 | // MEME GAMMA HERE 182 | HX8357D_SETCYC, 183 | 7, 184 | 0x02, 185 | 0x40, 186 | 0x00, 187 | 0x2A, 188 | 0x2A, 189 | 0x0D, 190 | 0x78, 191 | HX8357_COLMOD, 192 | 1, 193 | 0x55, 194 | HX8357_MADCTL, 195 | 1, 196 | 0xC0, 197 | HX8357_TEON, 198 | 1, 199 | 0x00, 200 | HX8357_TEARLINE, 201 | 2, 202 | 0x00, 203 | 0x02, 204 | HX8357_SLPOUT, 205 | 0, 206 | TFTLCD_DELAY, 207 | 150, 208 | HX8357_DISPON, 209 | 0, 210 | TFTLCD_DELAY, 211 | 50, 212 | }; 213 | 214 | static const uint16_t ILI932x_regValues[] PROGMEM = { 215 | ILI932X_START_OSC, 216 | 0x0001, // Start oscillator 217 | TFTLCD_DELAY, 218 | 50, // 50 millisecond delay 219 | ILI932X_DRIV_OUT_CTRL, 220 | 0x0100, 221 | ILI932X_DRIV_WAV_CTRL, 222 | 0x0700, 223 | ILI932X_ENTRY_MOD, 224 | 0x1030, 225 | ILI932X_RESIZE_CTRL, 226 | 0x0000, 227 | ILI932X_DISP_CTRL2, 228 | 0x0202, 229 | ILI932X_DISP_CTRL3, 230 | 0x0000, 231 | ILI932X_DISP_CTRL4, 232 | 0x0000, 233 | ILI932X_RGB_DISP_IF_CTRL1, 234 | 0x0, 235 | ILI932X_FRM_MARKER_POS, 236 | 0x0, 237 | ILI932X_RGB_DISP_IF_CTRL2, 238 | 0x0, 239 | ILI932X_POW_CTRL1, 240 | 0x0000, 241 | ILI932X_POW_CTRL2, 242 | 0x0007, 243 | ILI932X_POW_CTRL3, 244 | 0x0000, 245 | ILI932X_POW_CTRL4, 246 | 0x0000, 247 | TFTLCD_DELAY, 248 | 200, 249 | ILI932X_POW_CTRL1, 250 | 0x1690, 251 | ILI932X_POW_CTRL2, 252 | 0x0227, 253 | TFTLCD_DELAY, 254 | 50, 255 | ILI932X_POW_CTRL3, 256 | 0x001A, 257 | TFTLCD_DELAY, 258 | 50, 259 | ILI932X_POW_CTRL4, 260 | 0x1800, 261 | ILI932X_POW_CTRL7, 262 | 0x002A, 263 | TFTLCD_DELAY, 264 | 50, 265 | ILI932X_GAMMA_CTRL1, 266 | 0x0000, 267 | ILI932X_GAMMA_CTRL2, 268 | 0x0000, 269 | ILI932X_GAMMA_CTRL3, 270 | 0x0000, 271 | ILI932X_GAMMA_CTRL4, 272 | 0x0206, 273 | ILI932X_GAMMA_CTRL5, 274 | 0x0808, 275 | ILI932X_GAMMA_CTRL6, 276 | 0x0007, 277 | ILI932X_GAMMA_CTRL7, 278 | 0x0201, 279 | ILI932X_GAMMA_CTRL8, 280 | 0x0000, 281 | ILI932X_GAMMA_CTRL9, 282 | 0x0000, 283 | ILI932X_GAMMA_CTRL10, 284 | 0x0000, 285 | ILI932X_GRAM_HOR_AD, 286 | 0x0000, 287 | ILI932X_GRAM_VER_AD, 288 | 0x0000, 289 | ILI932X_HOR_START_AD, 290 | 0x0000, 291 | ILI932X_HOR_END_AD, 292 | 0x00EF, 293 | ILI932X_VER_START_AD, 294 | 0X0000, 295 | ILI932X_VER_END_AD, 296 | 0x013F, 297 | ILI932X_GATE_SCAN_CTRL1, 298 | 0xA700, // Driver Output Control (R60h) 299 | ILI932X_GATE_SCAN_CTRL2, 300 | 0x0003, // Driver Output Control (R61h) 301 | ILI932X_GATE_SCAN_CTRL3, 302 | 0x0000, // Driver Output Control (R62h) 303 | ILI932X_PANEL_IF_CTRL1, 304 | 0X0010, // Panel Interface Control 1 (R90h) 305 | ILI932X_PANEL_IF_CTRL2, 306 | 0X0000, 307 | ILI932X_PANEL_IF_CTRL3, 308 | 0X0003, 309 | ILI932X_PANEL_IF_CTRL4, 310 | 0X1100, 311 | ILI932X_PANEL_IF_CTRL5, 312 | 0X0000, 313 | ILI932X_PANEL_IF_CTRL6, 314 | 0X0000, 315 | ILI932X_DISP_CTRL1, 316 | 0x0133, // Main screen turn on 317 | }; 318 | 319 | void Adafruit_TFTLCD::begin(uint16_t id) { 320 | uint8_t i = 0; 321 | 322 | reset(); 323 | 324 | delay(200); 325 | 326 | if ((id == 0x9325) || (id == 0x9328)) { 327 | 328 | uint16_t a, d; 329 | driver = ID_932X; 330 | CS_ACTIVE; 331 | while (i < sizeof(ILI932x_regValues) / sizeof(uint16_t)) { 332 | a = pgm_read_word(&ILI932x_regValues[i++]); 333 | d = pgm_read_word(&ILI932x_regValues[i++]); 334 | if (a == TFTLCD_DELAY) 335 | delay(d); 336 | else 337 | writeRegister16(a, d); 338 | } 339 | setRotation(rotation); 340 | setAddrWindow(0, 0, TFTWIDTH - 1, TFTHEIGHT - 1); 341 | 342 | } else if (id == 0x9341) { 343 | 344 | driver = ID_9341; 345 | CS_ACTIVE; 346 | writeRegister8(ILI9341_SOFTRESET, 0); 347 | delay(50); 348 | writeRegister8(ILI9341_DISPLAYOFF, 0); 349 | 350 | writeRegister8(ILI9341_POWERCONTROL1, 0x23); 351 | writeRegister8(ILI9341_POWERCONTROL2, 0x10); 352 | writeRegister16(ILI9341_VCOMCONTROL1, 0x2B2B); 353 | writeRegister8(ILI9341_VCOMCONTROL2, 0xC0); 354 | writeRegister8(ILI9341_MEMCONTROL, ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR); 355 | writeRegister8(ILI9341_PIXELFORMAT, 0x55); 356 | writeRegister16(ILI9341_FRAMECONTROL, 0x001B); 357 | 358 | writeRegister8(ILI9341_ENTRYMODE, 0x07); 359 | /* writeRegister32(ILI9341_DISPLAYFUNC, 0x0A822700);*/ 360 | 361 | writeRegister8(ILI9341_SLEEPOUT, 0); 362 | delay(150); 363 | writeRegister8(ILI9341_DISPLAYON, 0); 364 | delay(500); 365 | setAddrWindow(0, 0, TFTWIDTH - 1, TFTHEIGHT - 1); 366 | return; 367 | 368 | } else if (id == 0x8357) { 369 | // HX8357D 370 | driver = ID_HX8357D; 371 | CS_ACTIVE; 372 | while (i < sizeof(HX8357D_regValues)) { 373 | uint8_t r = pgm_read_byte(&HX8357D_regValues[i++]); 374 | uint8_t len = pgm_read_byte(&HX8357D_regValues[i++]); 375 | if (r == TFTLCD_DELAY) { 376 | delay(len); 377 | } else { 378 | // Serial.print("Register $"); Serial.print(r, HEX); 379 | // Serial.print(" datalen "); Serial.println(len); 380 | 381 | CS_ACTIVE; 382 | CD_COMMAND; 383 | write8(r); 384 | CD_DATA; 385 | for (uint8_t d = 0; d < len; d++) { 386 | uint8_t x = pgm_read_byte(&HX8357D_regValues[i++]); 387 | write8(x); 388 | } 389 | CS_IDLE; 390 | } 391 | } 392 | return; 393 | 394 | } else if (id == 0x7575) { 395 | 396 | uint8_t a, d; 397 | driver = ID_7575; 398 | CS_ACTIVE; 399 | while (i < sizeof(HX8347G_regValues)) { 400 | a = pgm_read_byte(&HX8347G_regValues[i++]); 401 | d = pgm_read_byte(&HX8347G_regValues[i++]); 402 | if (a == TFTLCD_DELAY) 403 | delay(d); 404 | else 405 | writeRegister8(a, d); 406 | } 407 | setRotation(rotation); 408 | setLR(); // Lower-right corner of address window 409 | 410 | } else { 411 | driver = ID_UNKNOWN; 412 | return; 413 | } 414 | } 415 | 416 | void Adafruit_TFTLCD::reset(void) { 417 | 418 | CS_IDLE; 419 | // CD_DATA; 420 | WR_IDLE; 421 | RD_IDLE; 422 | 423 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 424 | digitalWrite(5, LOW); 425 | delay(2); 426 | digitalWrite(5, HIGH); 427 | #else 428 | if (_reset) { 429 | digitalWrite(_reset, LOW); 430 | delay(2); 431 | digitalWrite(_reset, HIGH); 432 | } 433 | #endif 434 | 435 | // Data transfer sync 436 | CS_ACTIVE; 437 | CD_COMMAND; 438 | write8(0x00); 439 | for (uint8_t i = 0; i < 3; i++) 440 | WR_STROBE; // Three extra 0x00s 441 | CS_IDLE; 442 | } 443 | 444 | // Sets the LCD address window (and address counter, on 932X). 445 | // Relevant to rect/screen fills and H/V lines. Input coordinates are 446 | // assumed pre-sorted (e.g. x2 >= x1). 447 | void Adafruit_TFTLCD::setAddrWindow(int x1, int y1, int x2, int y2) { 448 | CS_ACTIVE; 449 | if (driver == ID_932X) { 450 | 451 | // Values passed are in current (possibly rotated) coordinate 452 | // system. 932X requires hardware-native coords regardless of 453 | // MADCTL, so rotate inputs as needed. The address counter is 454 | // set to the top-left corner -- although fill operations can be 455 | // done in any direction, the current screen rotation is applied 456 | // because some users find it disconcerting when a fill does not 457 | // occur top-to-bottom. 458 | int x, y, t; 459 | switch (rotation) { 460 | default: 461 | x = x1; 462 | y = y1; 463 | break; 464 | case 1: 465 | t = y1; 466 | y1 = x1; 467 | x1 = TFTWIDTH - 1 - y2; 468 | y2 = x2; 469 | x2 = TFTWIDTH - 1 - t; 470 | x = x2; 471 | y = y1; 472 | break; 473 | case 2: 474 | t = x1; 475 | x1 = TFTWIDTH - 1 - x2; 476 | x2 = TFTWIDTH - 1 - t; 477 | t = y1; 478 | y1 = TFTHEIGHT - 1 - y2; 479 | y2 = TFTHEIGHT - 1 - t; 480 | x = x2; 481 | y = y2; 482 | break; 483 | case 3: 484 | t = x1; 485 | x1 = y1; 486 | y1 = TFTHEIGHT - 1 - x2; 487 | x2 = y2; 488 | y2 = TFTHEIGHT - 1 - t; 489 | x = x1; 490 | y = y2; 491 | break; 492 | } 493 | writeRegister16(0x0050, x1); // Set address window 494 | writeRegister16(0x0051, x2); 495 | writeRegister16(0x0052, y1); 496 | writeRegister16(0x0053, y2); 497 | writeRegister16(0x0020, x); // Set address counter to top left 498 | writeRegister16(0x0021, y); 499 | 500 | } else if (driver == ID_7575) { 501 | 502 | writeRegisterPair(HX8347G_COLADDRSTART_HI, HX8347G_COLADDRSTART_LO, x1); 503 | writeRegisterPair(HX8347G_ROWADDRSTART_HI, HX8347G_ROWADDRSTART_LO, y1); 504 | writeRegisterPair(HX8347G_COLADDREND_HI, HX8347G_COLADDREND_LO, x2); 505 | writeRegisterPair(HX8347G_ROWADDREND_HI, HX8347G_ROWADDREND_LO, y2); 506 | 507 | } else if ((driver == ID_9341) || (driver == ID_HX8357D)) { 508 | uint32_t t; 509 | 510 | t = x1; 511 | t <<= 16; 512 | t |= x2; 513 | writeRegister32(ILI9341_COLADDRSET, t); // HX8357D uses same registers! 514 | t = y1; 515 | t <<= 16; 516 | t |= y2; 517 | writeRegister32(ILI9341_PAGEADDRSET, t); // HX8357D uses same registers! 518 | } 519 | CS_IDLE; 520 | } 521 | 522 | // Unlike the 932X drivers that set the address window to the full screen 523 | // by default (using the address counter for drawPixel operations), the 524 | // 7575 needs the address window set on all graphics operations. In order 525 | // to save a few register writes on each pixel drawn, the lower-right 526 | // corner of the address window is reset after most fill operations, so 527 | // that drawPixel only needs to change the upper left each time. 528 | void Adafruit_TFTLCD::setLR(void) { 529 | CS_ACTIVE; 530 | writeRegisterPair(HX8347G_COLADDREND_HI, HX8347G_COLADDREND_LO, _width - 1); 531 | writeRegisterPair(HX8347G_ROWADDREND_HI, HX8347G_ROWADDREND_LO, _height - 1); 532 | CS_IDLE; 533 | } 534 | 535 | // Fast block fill operation for fillScreen, fillRect, H/V line, etc. 536 | // Requires setAddrWindow() has previously been called to set the fill 537 | // bounds. 'len' is inclusive, MUST be >= 1. 538 | void Adafruit_TFTLCD::flood(uint16_t color, uint32_t len) { 539 | uint16_t blocks; 540 | uint8_t i, hi = color >> 8, lo = color; 541 | 542 | CS_ACTIVE; 543 | CD_COMMAND; 544 | if (driver == ID_9341) { 545 | write8(0x2C); 546 | } else if (driver == ID_932X) { 547 | write8(0x00); // High byte of GRAM register... 548 | write8(0x22); // Write data to GRAM 549 | } else if (driver == ID_HX8357D) { 550 | write8(HX8357_RAMWR); 551 | } else { 552 | write8(0x22); // Write data to GRAM 553 | } 554 | 555 | // Write first pixel normally, decrement counter by 1 556 | CD_DATA; 557 | write8(hi); 558 | write8(lo); 559 | len--; 560 | 561 | blocks = (uint16_t)(len / 64); // 64 pixels/block 562 | if (hi == lo) { 563 | // High and low bytes are identical. Leave prior data 564 | // on the port(s) and just toggle the write strobe. 565 | while (blocks--) { 566 | i = 16; // 64 pixels/block / 4 pixels/pass 567 | do { 568 | WR_STROBE; 569 | WR_STROBE; 570 | WR_STROBE; 571 | WR_STROBE; // 2 bytes/pixel 572 | WR_STROBE; 573 | WR_STROBE; 574 | WR_STROBE; 575 | WR_STROBE; // x 4 pixels 576 | } while (--i); 577 | } 578 | // Fill any remaining pixels (1 to 64) 579 | for (i = (uint8_t)len & 63; i--;) { 580 | WR_STROBE; 581 | WR_STROBE; 582 | } 583 | } else { 584 | while (blocks--) { 585 | i = 16; // 64 pixels/block / 4 pixels/pass 586 | do { 587 | write8(hi); 588 | write8(lo); 589 | write8(hi); 590 | write8(lo); 591 | write8(hi); 592 | write8(lo); 593 | write8(hi); 594 | write8(lo); 595 | } while (--i); 596 | } 597 | for (i = (uint8_t)len & 63; i--;) { 598 | write8(hi); 599 | write8(lo); 600 | } 601 | } 602 | CS_IDLE; 603 | } 604 | 605 | void Adafruit_TFTLCD::drawFastHLine(int16_t x, int16_t y, int16_t length, 606 | uint16_t color) { 607 | int16_t x2; 608 | 609 | // Initial off-screen clipping 610 | if ((length <= 0) || (y < 0) || (y >= _height) || (x >= _width) || 611 | ((x2 = (x + length - 1)) < 0)) 612 | return; 613 | 614 | if (x < 0) { // Clip left 615 | length += x; 616 | x = 0; 617 | } 618 | if (x2 >= _width) { // Clip right 619 | x2 = _width - 1; 620 | length = x2 - x + 1; 621 | } 622 | 623 | setAddrWindow(x, y, x2, y); 624 | flood(color, length); 625 | if (driver == ID_932X) 626 | setAddrWindow(0, 0, _width - 1, _height - 1); 627 | else 628 | setLR(); 629 | } 630 | 631 | void Adafruit_TFTLCD::drawFastVLine(int16_t x, int16_t y, int16_t length, 632 | uint16_t color) { 633 | int16_t y2; 634 | 635 | // Initial off-screen clipping 636 | if ((length <= 0) || (x < 0) || (x >= _width) || (y >= _height) || 637 | ((y2 = (y + length - 1)) < 0)) 638 | return; 639 | if (y < 0) { // Clip top 640 | length += y; 641 | y = 0; 642 | } 643 | if (y2 >= _height) { // Clip bottom 644 | y2 = _height - 1; 645 | length = y2 - y + 1; 646 | } 647 | 648 | setAddrWindow(x, y, x, y2); 649 | flood(color, length); 650 | if (driver == ID_932X) 651 | setAddrWindow(0, 0, _width - 1, _height - 1); 652 | else 653 | setLR(); 654 | } 655 | 656 | void Adafruit_TFTLCD::fillRect(int16_t x1, int16_t y1, int16_t w, int16_t h, 657 | uint16_t fillcolor) { 658 | int16_t x2, y2; 659 | 660 | // Initial off-screen clipping 661 | if ((w <= 0) || (h <= 0) || (x1 >= _width) || (y1 >= _height) || 662 | ((x2 = x1 + w - 1) < 0) || ((y2 = y1 + h - 1) < 0)) 663 | return; 664 | if (x1 < 0) { // Clip left 665 | w += x1; 666 | x1 = 0; 667 | } 668 | if (y1 < 0) { // Clip top 669 | h += y1; 670 | y1 = 0; 671 | } 672 | if (x2 >= _width) { // Clip right 673 | x2 = _width - 1; 674 | w = x2 - x1 + 1; 675 | } 676 | if (y2 >= _height) { // Clip bottom 677 | y2 = _height - 1; 678 | h = y2 - y1 + 1; 679 | } 680 | 681 | setAddrWindow(x1, y1, x2, y2); 682 | flood(fillcolor, (uint32_t)w * (uint32_t)h); 683 | if (driver == ID_932X) 684 | setAddrWindow(0, 0, _width - 1, _height - 1); 685 | else 686 | setLR(); 687 | } 688 | 689 | void Adafruit_TFTLCD::fillScreen(uint16_t color) { 690 | 691 | if (driver == ID_932X) { 692 | 693 | // For the 932X, a full-screen address window is already the default 694 | // state, just need to set the address pointer to the top-left corner. 695 | // Although we could fill in any direction, the code uses the current 696 | // screen rotation because some users find it disconcerting when a 697 | // fill does not occur top-to-bottom. 698 | uint16_t x, y; 699 | switch (rotation) { 700 | default: 701 | x = 0; 702 | y = 0; 703 | break; 704 | case 1: 705 | x = TFTWIDTH - 1; 706 | y = 0; 707 | break; 708 | case 2: 709 | x = TFTWIDTH - 1; 710 | y = TFTHEIGHT - 1; 711 | break; 712 | case 3: 713 | x = 0; 714 | y = TFTHEIGHT - 1; 715 | break; 716 | } 717 | CS_ACTIVE; 718 | writeRegister16(0x0020, x); 719 | writeRegister16(0x0021, y); 720 | 721 | } else if ((driver == ID_9341) || (driver == ID_7575) || 722 | (driver == ID_HX8357D)) { 723 | // For these, there is no settable address pointer, instead the 724 | // address window must be set for each drawing operation. However, 725 | // this display takes rotation into account for the parameters, no 726 | // need to do extra rotation math here. 727 | setAddrWindow(0, 0, _width - 1, _height - 1); 728 | } 729 | flood(color, (long)TFTWIDTH * (long)TFTHEIGHT); 730 | } 731 | 732 | void Adafruit_TFTLCD::drawPixel(int16_t x, int16_t y, uint16_t color) { 733 | 734 | // Clip 735 | if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) 736 | return; 737 | 738 | CS_ACTIVE; 739 | if (driver == ID_932X) { 740 | int16_t t; 741 | switch (rotation) { 742 | case 1: 743 | t = x; 744 | x = TFTWIDTH - 1 - y; 745 | y = t; 746 | break; 747 | case 2: 748 | x = TFTWIDTH - 1 - x; 749 | y = TFTHEIGHT - 1 - y; 750 | break; 751 | case 3: 752 | t = x; 753 | x = y; 754 | y = TFTHEIGHT - 1 - t; 755 | break; 756 | } 757 | writeRegister16(0x0020, x); 758 | writeRegister16(0x0021, y); 759 | writeRegister16(0x0022, color); 760 | 761 | } else if (driver == ID_7575) { 762 | 763 | uint8_t hi, lo; 764 | switch (rotation) { 765 | default: 766 | lo = 0; 767 | break; 768 | case 1: 769 | lo = 0x60; 770 | break; 771 | case 2: 772 | lo = 0xc0; 773 | break; 774 | case 3: 775 | lo = 0xa0; 776 | break; 777 | } 778 | writeRegister8(HX8347G_MEMACCESS, lo); 779 | // Only upper-left is set -- bottom-right is full screen default 780 | writeRegisterPair(HX8347G_COLADDRSTART_HI, HX8347G_COLADDRSTART_LO, x); 781 | writeRegisterPair(HX8347G_ROWADDRSTART_HI, HX8347G_ROWADDRSTART_LO, y); 782 | hi = color >> 8; 783 | lo = color; 784 | CD_COMMAND; 785 | write8(0x22); 786 | CD_DATA; 787 | write8(hi); 788 | write8(lo); 789 | 790 | } else if ((driver == ID_9341) || (driver == ID_HX8357D)) { 791 | setAddrWindow(x, y, _width - 1, _height - 1); 792 | CS_ACTIVE; 793 | CD_COMMAND; 794 | write8(0x2C); 795 | CD_DATA; 796 | write8(color >> 8); 797 | write8(color); 798 | } 799 | 800 | CS_IDLE; 801 | } 802 | 803 | // Issues 'raw' an array of 16-bit color values to the LCD; used 804 | // externally by BMP examples. Assumes that setWindowAddr() has 805 | // previously been set to define the bounds. Max 255 pixels at 806 | // a time (BMP examples read in small chunks due to limited RAM). 807 | void Adafruit_TFTLCD::pushColors(uint16_t *data, uint8_t len, boolean first) { 808 | uint16_t color; 809 | uint8_t hi, lo; 810 | CS_ACTIVE; 811 | if (first == true) { // Issue GRAM write command only on first call 812 | CD_COMMAND; 813 | if (driver == ID_932X) 814 | write8(0x00); 815 | if ((driver == ID_9341) || (driver == ID_HX8357D)) { 816 | write8(0x2C); 817 | } else { 818 | write8(0x22); 819 | } 820 | } 821 | CD_DATA; 822 | while (len--) { 823 | color = *data++; 824 | hi = color >> 8; // Don't simplify or merge these 825 | lo = color; // lines, there's macro shenanigans 826 | write8(hi); // going on. 827 | write8(lo); 828 | } 829 | CS_IDLE; 830 | } 831 | 832 | void Adafruit_TFTLCD::setRotation(uint8_t x) { 833 | 834 | // Call parent rotation func first -- sets up rotation flags, etc. 835 | Adafruit_GFX::setRotation(x); 836 | // Then perform hardware-specific rotation operations... 837 | 838 | CS_ACTIVE; 839 | if (driver == ID_932X) { 840 | 841 | uint16_t t; 842 | switch (rotation) { 843 | default: 844 | t = 0x1030; 845 | break; 846 | case 1: 847 | t = 0x1028; 848 | break; 849 | case 2: 850 | t = 0x1000; 851 | break; 852 | case 3: 853 | t = 0x1018; 854 | break; 855 | } 856 | writeRegister16(0x0003, t); // MADCTL 857 | // For 932X, init default full-screen address window: 858 | setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here 859 | } 860 | if (driver == ID_7575) { 861 | 862 | uint8_t t; 863 | switch (rotation) { 864 | default: 865 | t = 0; 866 | break; 867 | case 1: 868 | t = 0x60; 869 | break; 870 | case 2: 871 | t = 0xc0; 872 | break; 873 | case 3: 874 | t = 0xa0; 875 | break; 876 | } 877 | writeRegister8(HX8347G_MEMACCESS, t); 878 | // 7575 has to set the address window on most drawing operations. 879 | // drawPixel() cheats by setting only the top left...by default, 880 | // the lower right is always reset to the corner. 881 | setLR(); // CS_IDLE happens here 882 | } 883 | 884 | if (driver == ID_9341) { 885 | // MEME, HX8357D uses same registers as 9341 but different values 886 | uint16_t t = 0; 887 | 888 | switch (rotation) { 889 | case 2: 890 | t = ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR; 891 | break; 892 | case 3: 893 | t = ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR; 894 | break; 895 | case 0: 896 | t = ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR; 897 | break; 898 | case 1: 899 | t = ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | 900 | ILI9341_MADCTL_BGR; 901 | break; 902 | } 903 | writeRegister8(ILI9341_MADCTL, t); // MADCTL 904 | // For 9341, init default full-screen address window: 905 | setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here 906 | } 907 | 908 | if (driver == ID_HX8357D) { 909 | // MEME, HX8357D uses same registers as 9341 but different values 910 | uint16_t t = 0; 911 | 912 | switch (rotation) { 913 | case 2: 914 | t = HX8357B_MADCTL_RGB; 915 | break; 916 | case 3: 917 | t = HX8357B_MADCTL_MX | HX8357B_MADCTL_MV | HX8357B_MADCTL_RGB; 918 | break; 919 | case 0: 920 | t = HX8357B_MADCTL_MX | HX8357B_MADCTL_MY | HX8357B_MADCTL_RGB; 921 | break; 922 | case 1: 923 | t = HX8357B_MADCTL_MY | HX8357B_MADCTL_MV | HX8357B_MADCTL_RGB; 924 | break; 925 | } 926 | writeRegister8(ILI9341_MADCTL, t); // MADCTL 927 | // For 8357, init default full-screen address window: 928 | setAddrWindow(0, 0, _width - 1, _height - 1); // CS_IDLE happens here 929 | } 930 | } 931 | 932 | #ifdef read8isFunctionalized 933 | #define read8(x) x = read8fn() 934 | #endif 935 | 936 | // Because this function is used infrequently, it configures the ports for 937 | // the read operation, reads the data, then restores the ports to the write 938 | // configuration. Write operations happen a LOT, so it's advantageous to 939 | // leave the ports in that state as a default. 940 | uint16_t Adafruit_TFTLCD::readPixel(int16_t x, int16_t y) { 941 | 942 | if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) 943 | return 0; 944 | 945 | CS_ACTIVE; 946 | if (driver == ID_932X) { 947 | 948 | uint8_t hi, lo; 949 | int16_t t; 950 | switch (rotation) { 951 | case 1: 952 | t = x; 953 | x = TFTWIDTH - 1 - y; 954 | y = t; 955 | break; 956 | case 2: 957 | x = TFTWIDTH - 1 - x; 958 | y = TFTHEIGHT - 1 - y; 959 | break; 960 | case 3: 961 | t = x; 962 | x = y; 963 | y = TFTHEIGHT - 1 - t; 964 | break; 965 | } 966 | writeRegister16(0x0020, x); 967 | writeRegister16(0x0021, y); 968 | // Inexplicable thing: sometimes pixel read has high/low bytes 969 | // reversed. A second read fixes this. Unsure of reason. Have 970 | // tried adjusting timing in read8() etc. to no avail. 971 | for (uint8_t pass = 0; pass < 2; pass++) { 972 | CD_COMMAND; 973 | write8(0x00); 974 | write8(0x22); // Read data from GRAM 975 | CD_DATA; 976 | setReadDir(); // Set up LCD data port(s) for READ operations 977 | read8(hi); // First 2 bytes back are a dummy read 978 | read8(hi); 979 | read8(hi); // Bytes 3, 4 are actual pixel value 980 | read8(lo); 981 | setWriteDir(); // Restore LCD data port(s) to WRITE configuration 982 | } 983 | CS_IDLE; 984 | return ((uint16_t)hi << 8) | lo; 985 | 986 | } else if (driver == ID_7575) { 987 | 988 | uint8_t r, g, b; 989 | writeRegisterPair(HX8347G_COLADDRSTART_HI, HX8347G_COLADDRSTART_LO, x); 990 | writeRegisterPair(HX8347G_ROWADDRSTART_HI, HX8347G_ROWADDRSTART_LO, y); 991 | CD_COMMAND; 992 | write8(0x22); // Read data from GRAM 993 | setReadDir(); // Set up LCD data port(s) for READ operations 994 | CD_DATA; 995 | read8(r); // First byte back is a dummy read 996 | read8(r); 997 | read8(g); 998 | read8(b); 999 | setWriteDir(); // Restore LCD data port(s) to WRITE configuration 1000 | CS_IDLE; 1001 | return (((uint16_t)r & B11111000) << 8) | (((uint16_t)g & B11111100) << 3) | 1002 | (b >> 3); 1003 | } else 1004 | return 0; 1005 | } 1006 | 1007 | // Ditto with the read/write port directions, as above. 1008 | uint16_t Adafruit_TFTLCD::readID(void) { 1009 | uint16_t id; 1010 | 1011 | // retry a bunch! 1012 | for (int i = 0; i < 5; i++) { 1013 | id = (uint16_t)readReg(0xD3); 1014 | delayMicroseconds(50); 1015 | if (id == 0x9341) { 1016 | return id; 1017 | } 1018 | } 1019 | 1020 | uint8_t hi, lo; 1021 | 1022 | /* 1023 | for (uint8_t i=0; i<128; i++) { 1024 | Serial.print("$"); Serial.print(i, HEX); 1025 | Serial.print(" = 0x"); Serial.println(readReg(i), HEX); 1026 | } 1027 | */ 1028 | 1029 | if (readReg(0x04) == 0x8000) { // eh close enough 1030 | // setc! 1031 | /* 1032 | Serial.println("!"); 1033 | for (uint8_t i=0; i<254; i++) { 1034 | Serial.print("$"); Serial.print(i, HEX); 1035 | Serial.print(" = 0x"); Serial.println(readReg(i), HEX); 1036 | } 1037 | */ 1038 | writeRegister24(HX8357D_SETC, 0xFF8357); 1039 | delay(300); 1040 | // Serial.println(readReg(0xD0), HEX); 1041 | if (readReg(0xD0) == 0x990000) { 1042 | return 0x8357; 1043 | } 1044 | } 1045 | 1046 | CS_ACTIVE; 1047 | CD_COMMAND; 1048 | write8(0x00); 1049 | WR_STROBE; // Repeat prior byte (0x00) 1050 | setReadDir(); // Set up LCD data port(s) for READ operations 1051 | CD_DATA; 1052 | read8(hi); 1053 | read8(lo); 1054 | setWriteDir(); // Restore LCD data port(s) to WRITE configuration 1055 | CS_IDLE; 1056 | 1057 | id = hi; 1058 | id <<= 8; 1059 | id |= lo; 1060 | return id; 1061 | } 1062 | 1063 | uint32_t Adafruit_TFTLCD::readReg(uint8_t r) { 1064 | uint32_t id; 1065 | uint8_t x; 1066 | 1067 | // try reading register #4 1068 | CS_ACTIVE; 1069 | CD_COMMAND; 1070 | write8(r); 1071 | setReadDir(); // Set up LCD data port(s) for READ operations 1072 | CD_DATA; 1073 | delayMicroseconds(50); 1074 | read8(x); 1075 | id = x; // Do not merge or otherwise simplify 1076 | id <<= 8; // these lines. It's an unfortunate 1077 | read8(x); 1078 | id |= x; // shenanigans that are going on. 1079 | id <<= 8; // these lines. It's an unfortunate 1080 | read8(x); 1081 | id |= x; // shenanigans that are going on. 1082 | id <<= 8; // these lines. It's an unfortunate 1083 | read8(x); 1084 | id |= x; // shenanigans that are going on. 1085 | CS_IDLE; 1086 | setWriteDir(); // Restore LCD data port(s) to WRITE configuration 1087 | 1088 | // Serial.print("Read $"); Serial.print(r, HEX); 1089 | // Serial.print(":\t0x"); Serial.println(id, HEX); 1090 | return id; 1091 | } 1092 | 1093 | // Pass 8-bit (each) R,G,B, get back 16-bit packed color 1094 | uint16_t Adafruit_TFTLCD::color565(uint8_t r, uint8_t g, uint8_t b) { 1095 | return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); 1096 | } 1097 | 1098 | // For I/O macros that were left undefined, declare function 1099 | // versions that reference the inline macros just once: 1100 | 1101 | #ifndef write8 1102 | void Adafruit_TFTLCD::write8(uint8_t value) { write8inline(value); } 1103 | #endif 1104 | 1105 | #ifdef read8isFunctionalized 1106 | uint8_t Adafruit_TFTLCD::read8fn(void) { 1107 | uint8_t result; 1108 | read8inline(result); 1109 | return result; 1110 | } 1111 | #endif 1112 | 1113 | #ifndef setWriteDir 1114 | void Adafruit_TFTLCD::setWriteDir(void) { setWriteDirInline(); } 1115 | #endif 1116 | 1117 | #ifndef setReadDir 1118 | void Adafruit_TFTLCD::setReadDir(void) { setReadDirInline(); } 1119 | #endif 1120 | 1121 | #ifndef writeRegister8 1122 | void Adafruit_TFTLCD::writeRegister8(uint8_t a, uint8_t d) { 1123 | writeRegister8inline(a, d); 1124 | } 1125 | #endif 1126 | 1127 | #ifndef writeRegister16 1128 | void Adafruit_TFTLCD::writeRegister16(uint16_t a, uint16_t d) { 1129 | writeRegister16inline(a, d); 1130 | } 1131 | #endif 1132 | 1133 | #ifndef writeRegisterPair 1134 | void Adafruit_TFTLCD::writeRegisterPair(uint8_t aH, uint8_t aL, uint16_t d) { 1135 | writeRegisterPairInline(aH, aL, d); 1136 | } 1137 | #endif 1138 | 1139 | void Adafruit_TFTLCD::writeRegister24(uint8_t r, uint32_t d) { 1140 | CS_ACTIVE; 1141 | CD_COMMAND; 1142 | write8(r); 1143 | CD_DATA; 1144 | delayMicroseconds(10); 1145 | write8(d >> 16); 1146 | delayMicroseconds(10); 1147 | write8(d >> 8); 1148 | delayMicroseconds(10); 1149 | write8(d); 1150 | CS_IDLE; 1151 | } 1152 | 1153 | void Adafruit_TFTLCD::writeRegister32(uint8_t r, uint32_t d) { 1154 | CS_ACTIVE; 1155 | CD_COMMAND; 1156 | write8(r); 1157 | CD_DATA; 1158 | delayMicroseconds(10); 1159 | write8(d >> 24); 1160 | delayMicroseconds(10); 1161 | write8(d >> 16); 1162 | delayMicroseconds(10); 1163 | write8(d >> 8); 1164 | delayMicroseconds(10); 1165 | write8(d); 1166 | CS_IDLE; 1167 | } 1168 | -------------------------------------------------------------------------------- /Adafruit_TFTLCD.h: -------------------------------------------------------------------------------- 1 | // IMPORTANT: SEE COMMENTS @ LINE 15 REGARDING SHIELD VS BREAKOUT BOARD USAGE. 2 | 3 | // Graphics library by ladyada/adafruit with init code from Rossum 4 | // MIT license 5 | 6 | #ifndef _ADAFRUIT_TFTLCD_H_ 7 | #define _ADAFRUIT_TFTLCD_H_ 8 | 9 | #if ARDUINO >= 100 10 | #include "Arduino.h" 11 | #else 12 | #include "WProgram.h" 13 | #endif 14 | 15 | #include 16 | 17 | // **** IF USING THE LCD BREAKOUT BOARD, COMMENT OUT THIS NEXT LINE. **** 18 | // **** IF USING THE LCD SHIELD, LEAVE THE LINE ENABLED: **** 19 | 20 | //#define USE_ADAFRUIT_SHIELD_PINOUT 1 21 | 22 | class Adafruit_TFTLCD : public Adafruit_GFX { 23 | 24 | public: 25 | Adafruit_TFTLCD(uint8_t cs, uint8_t cd, uint8_t wr, uint8_t rd, uint8_t rst); 26 | Adafruit_TFTLCD(void); 27 | 28 | void begin(uint16_t id = 0x9325); 29 | void drawPixel(int16_t x, int16_t y, uint16_t color); 30 | void drawFastHLine(int16_t x0, int16_t y0, int16_t w, uint16_t color); 31 | void drawFastVLine(int16_t x0, int16_t y0, int16_t h, uint16_t color); 32 | void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t c); 33 | void fillScreen(uint16_t color); 34 | void reset(void); 35 | void setRegisters8(uint8_t *ptr, uint8_t n); 36 | void setRegisters16(uint16_t *ptr, uint8_t n); 37 | void setRotation(uint8_t x); 38 | // These methods are public in order for BMP examples to work: 39 | void setAddrWindow(int x1, int y1, int x2, int y2); 40 | void pushColors(uint16_t *data, uint8_t len, boolean first); 41 | 42 | uint16_t color565(uint8_t r, uint8_t g, uint8_t b), 43 | readPixel(int16_t x, int16_t y), readID(void); 44 | uint32_t readReg(uint8_t r); 45 | 46 | private: 47 | void init(), 48 | // These items may have previously been defined as macros 49 | // in pin_magic.h. If not, function versions are declared: 50 | #ifndef write8 51 | write8(uint8_t value), 52 | #endif 53 | #ifndef setWriteDir 54 | setWriteDir(void), 55 | #endif 56 | #ifndef setReadDir 57 | setReadDir(void), 58 | #endif 59 | #ifndef writeRegister8 60 | writeRegister8(uint8_t a, uint8_t d), 61 | #endif 62 | #ifndef writeRegister16 63 | writeRegister16(uint16_t a, uint16_t d), 64 | #endif 65 | writeRegister24(uint8_t a, uint32_t d), 66 | writeRegister32(uint8_t a, uint32_t d), 67 | #ifndef writeRegisterPair 68 | writeRegisterPair(uint8_t aH, uint8_t aL, uint16_t d), 69 | #endif 70 | setLR(void), flood(uint16_t color, uint32_t len); 71 | uint8_t driver; 72 | 73 | #ifndef read8 74 | uint8_t read8fn(void); 75 | #define read8isFunctionalized 76 | #endif 77 | 78 | #ifndef USE_ADAFRUIT_SHIELD_PINOUT 79 | 80 | #ifdef __AVR__ 81 | volatile uint8_t *csPort, *cdPort, *wrPort, *rdPort; 82 | uint8_t csPinSet, cdPinSet, wrPinSet, rdPinSet, csPinUnset, cdPinUnset, 83 | wrPinUnset, rdPinUnset, _reset; 84 | #endif 85 | #if defined(__SAM3X8E__) 86 | Pio *csPort, *cdPort, *wrPort, *rdPort; 87 | uint32_t csPinSet, cdPinSet, wrPinSet, rdPinSet, csPinUnset, cdPinUnset, 88 | wrPinUnset, rdPinUnset, _reset; 89 | #endif 90 | 91 | #endif 92 | }; 93 | 94 | // For compatibility with sketches written for older versions of library. 95 | // Color function name was changed to 'color565' for parity with 2.2" LCD 96 | // library. 97 | #define Color565 color565 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit library for 8-bit TFT LCDs such as ILI9325, ILI9328, etc 2 | 3 | This is a library for our Adafruit 16-channel PWM & Servo driver, shield or FeatherWing 4 | 5 | 6 | 7 | Pick one up today in the adafruit shop! 8 | * https://www.adafruit.com/product/335 9 | * https://www.adafruit.com/product/376 10 | 11 | These displays use 8-bit parallel to communicate, 12 or 13 pins are required to interface (RST is optional). 12 | 13 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 14 | 15 | Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, check license.txt for more information. 16 | 17 | All text above must be included in any redistribution 18 | 19 | To install, use the Arduino Library Manager and search for "Adafruit 2.8" TFT display Library" and install the library. 20 | -------------------------------------------------------------------------------- /assets/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/TFTLCD-Library/2f917ad72bf9d2c39cb741d2435df537770e8eca/assets/image.jpg -------------------------------------------------------------------------------- /bitmaps/miniwoof.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/TFTLCD-Library/2f917ad72bf9d2c39cb741d2435df537770e8eca/bitmaps/miniwoof.bmp -------------------------------------------------------------------------------- /bitmaps/test.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/TFTLCD-Library/2f917ad72bf9d2c39cb741d2435df537770e8eca/bitmaps/test.bmp -------------------------------------------------------------------------------- /bitmaps/woof.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/TFTLCD-Library/2f917ad72bf9d2c39cb741d2435df537770e8eca/bitmaps/woof.bmp -------------------------------------------------------------------------------- /examples/graphicstest/graphicstest.ino: -------------------------------------------------------------------------------- 1 | // IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY 2 | // CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD. 3 | // SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP. 4 | 5 | #include // Core graphics library 6 | #include // Hardware-specific library 7 | 8 | // The control pins for the LCD can be assigned to any digital or 9 | // analog pins...but we'll use the analog pins as this allows us to 10 | // double up the pins with the touch screen (see the TFT paint example). 11 | #define LCD_CS A3 // Chip Select goes to Analog 3 12 | #define LCD_CD A2 // Command/Data goes to Analog 2 13 | #define LCD_WR A1 // LCD Write goes to Analog 1 14 | #define LCD_RD A0 // LCD Read goes to Analog 0 15 | 16 | #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin 17 | 18 | // When using the BREAKOUT BOARD only, use these 8 data lines to the LCD: 19 | // For the Arduino Uno, Duemilanove, Diecimila, etc.: 20 | // D0 connects to digital pin 8 (Notice these are 21 | // D1 connects to digital pin 9 NOT in order!) 22 | // D2 connects to digital pin 2 23 | // D3 connects to digital pin 3 24 | // D4 connects to digital pin 4 25 | // D5 connects to digital pin 5 26 | // D6 connects to digital pin 6 27 | // D7 connects to digital pin 7 28 | // For the Arduino Mega, use digital pins 22 through 29 29 | // (on the 2-row header at the end of the board). 30 | 31 | // Assign human-readable names to some common 16-bit color values: 32 | #define BLACK 0x0000 33 | #define BLUE 0x001F 34 | #define RED 0xF800 35 | #define GREEN 0x07E0 36 | #define CYAN 0x07FF 37 | #define MAGENTA 0xF81F 38 | #define YELLOW 0xFFE0 39 | #define WHITE 0xFFFF 40 | 41 | Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); 42 | // If using the shield, all control and data lines are fixed, and 43 | // a simpler declaration can optionally be used: 44 | // Adafruit_TFTLCD tft; 45 | 46 | void setup(void) { 47 | Serial.begin(9600); 48 | Serial.println(F("TFT LCD test")); 49 | 50 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 51 | Serial.println(F("Using Adafruit 2.8\" TFT Arduino Shield Pinout")); 52 | #else 53 | Serial.println(F("Using Adafruit 2.8\" TFT Breakout Board Pinout")); 54 | #endif 55 | 56 | Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height()); 57 | 58 | tft.reset(); 59 | 60 | uint16_t identifier = tft.readID(); 61 | 62 | if(identifier == 0x9325) { 63 | Serial.println(F("Found ILI9325 LCD driver")); 64 | } else if(identifier == 0x9328) { 65 | Serial.println(F("Found ILI9328 LCD driver")); 66 | } else if(identifier == 0x7575) { 67 | Serial.println(F("Found HX8347G LCD driver")); 68 | } else if(identifier == 0x9341) { 69 | Serial.println(F("Found ILI9341 LCD driver")); 70 | } else if(identifier == 0x8357) { 71 | Serial.println(F("Found HX8357D LCD driver")); 72 | } else { 73 | Serial.print(F("Unknown LCD driver chip: ")); 74 | Serial.println(identifier, HEX); 75 | Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:")); 76 | Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT")); 77 | Serial.println(F("should appear in the library header (Adafruit_TFT.h).")); 78 | Serial.println(F("If using the breakout board, it should NOT be #defined!")); 79 | Serial.println(F("Also if using the breakout, double-check that all wiring")); 80 | Serial.println(F("matches the tutorial.")); 81 | return; 82 | } 83 | 84 | tft.begin(identifier); 85 | 86 | Serial.println(F("Benchmark Time (microseconds)")); 87 | 88 | Serial.print(F("Screen fill ")); 89 | Serial.println(testFillScreen()); 90 | delay(500); 91 | 92 | Serial.print(F("Text ")); 93 | Serial.println(testText()); 94 | delay(3000); 95 | 96 | Serial.print(F("Lines ")); 97 | Serial.println(testLines(CYAN)); 98 | delay(500); 99 | 100 | Serial.print(F("Horiz/Vert Lines ")); 101 | Serial.println(testFastLines(RED, BLUE)); 102 | delay(500); 103 | 104 | Serial.print(F("Rectangles (outline) ")); 105 | Serial.println(testRects(GREEN)); 106 | delay(500); 107 | 108 | Serial.print(F("Rectangles (filled) ")); 109 | Serial.println(testFilledRects(YELLOW, MAGENTA)); 110 | delay(500); 111 | 112 | Serial.print(F("Circles (filled) ")); 113 | Serial.println(testFilledCircles(10, MAGENTA)); 114 | 115 | Serial.print(F("Circles (outline) ")); 116 | Serial.println(testCircles(10, WHITE)); 117 | delay(500); 118 | 119 | Serial.print(F("Triangles (outline) ")); 120 | Serial.println(testTriangles()); 121 | delay(500); 122 | 123 | Serial.print(F("Triangles (filled) ")); 124 | Serial.println(testFilledTriangles()); 125 | delay(500); 126 | 127 | Serial.print(F("Rounded rects (outline) ")); 128 | Serial.println(testRoundRects()); 129 | delay(500); 130 | 131 | Serial.print(F("Rounded rects (filled) ")); 132 | Serial.println(testFilledRoundRects()); 133 | delay(500); 134 | 135 | Serial.println(F("Done!")); 136 | } 137 | 138 | void loop(void) { 139 | for(uint8_t rotation=0; rotation<4; rotation++) { 140 | tft.setRotation(rotation); 141 | testText(); 142 | delay(2000); 143 | } 144 | } 145 | 146 | unsigned long testFillScreen() { 147 | unsigned long start = micros(); 148 | tft.fillScreen(BLACK); 149 | tft.fillScreen(RED); 150 | tft.fillScreen(GREEN); 151 | tft.fillScreen(BLUE); 152 | tft.fillScreen(BLACK); 153 | return micros() - start; 154 | } 155 | 156 | unsigned long testText() { 157 | tft.fillScreen(BLACK); 158 | unsigned long start = micros(); 159 | tft.setCursor(0, 0); 160 | tft.setTextColor(WHITE); tft.setTextSize(1); 161 | tft.println("Hello World!"); 162 | tft.setTextColor(YELLOW); tft.setTextSize(2); 163 | tft.println(1234.56); 164 | tft.setTextColor(RED); tft.setTextSize(3); 165 | tft.println(0xDEADBEEF, HEX); 166 | tft.println(); 167 | tft.setTextColor(GREEN); 168 | tft.setTextSize(5); 169 | tft.println("Groop"); 170 | tft.setTextSize(2); 171 | tft.println("I implore thee,"); 172 | tft.setTextSize(1); 173 | tft.println("my foonting turlingdromes."); 174 | tft.println("And hooptiously drangle me"); 175 | tft.println("with crinkly bindlewurdles,"); 176 | tft.println("Or I will rend thee"); 177 | tft.println("in the gobberwarts"); 178 | tft.println("with my blurglecruncheon,"); 179 | tft.println("see if I don't!"); 180 | return micros() - start; 181 | } 182 | 183 | unsigned long testLines(uint16_t color) { 184 | unsigned long start, t; 185 | int x1, y1, x2, y2, 186 | w = tft.width(), 187 | h = tft.height(); 188 | 189 | tft.fillScreen(BLACK); 190 | 191 | x1 = y1 = 0; 192 | y2 = h - 1; 193 | start = micros(); 194 | for(x2=0; x20; i-=6) { 272 | i2 = i / 2; 273 | start = micros(); 274 | tft.fillRect(cx-i2, cy-i2, i, i, color1); 275 | t += micros() - start; 276 | // Outlines are not included in timing results 277 | tft.drawRect(cx-i2, cy-i2, i, i, color2); 278 | } 279 | 280 | return t; 281 | } 282 | 283 | unsigned long testFilledCircles(uint8_t radius, uint16_t color) { 284 | unsigned long start; 285 | int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; 286 | 287 | tft.fillScreen(BLACK); 288 | start = micros(); 289 | for(x=radius; x10; i-=5) { 343 | start = micros(); 344 | tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 345 | tft.color565(0, i, i)); 346 | t += micros() - start; 347 | tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 348 | tft.color565(i, i, 0)); 349 | } 350 | 351 | return t; 352 | } 353 | 354 | unsigned long testRoundRects() { 355 | unsigned long start; 356 | int w, i, i2, 357 | cx = tft.width() / 2 - 1, 358 | cy = tft.height() / 2 - 1; 359 | 360 | tft.fillScreen(BLACK); 361 | w = min(tft.width(), tft.height()); 362 | start = micros(); 363 | for(i=0; i20; i-=6) { 380 | i2 = i / 2; 381 | tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0)); 382 | } 383 | 384 | return micros() - start; 385 | } 386 | -------------------------------------------------------------------------------- /examples/rotationtest/rotationtest.ino: -------------------------------------------------------------------------------- 1 | // IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY 2 | // CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD. 3 | // SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP. 4 | 5 | #include // Core graphics library 6 | #include // Hardware-specific library 7 | 8 | // The control pins for the LCD can be assigned to any digital or 9 | // analog pins...but we'll use the analog pins as this allows us to 10 | // double up the pins with the touch screen (see the TFT paint example). 11 | #define LCD_CS A3 // Chip Select goes to Analog 3 12 | #define LCD_CD A2 // Command/Data goes to Analog 2 13 | #define LCD_WR A1 // LCD Write goes to Analog 1 14 | #define LCD_RD A0 // LCD Read goes to Analog 0 15 | 16 | #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin 17 | 18 | // When using the BREAKOUT BOARD only, use these 8 data lines to the LCD: 19 | // For the Arduino Uno, Duemilanove, Diecimila, etc.: 20 | // D0 connects to digital pin 8 (Notice these are 21 | // D1 connects to digital pin 9 NOT in order!) 22 | // D2 connects to digital pin 2 23 | // D3 connects to digital pin 3 24 | // D4 connects to digital pin 4 25 | // D5 connects to digital pin 5 26 | // D6 connects to digital pin 6 27 | // D7 connects to digital pin 7 28 | // For the Arduino Mega, use digital pins 22 through 29 29 | // (on the 2-row header at the end of the board). 30 | 31 | // Assign human-readable names to some common 16-bit color values: 32 | #define BLACK 0x0000 33 | #define BLUE 0x001F 34 | #define RED 0xF800 35 | #define GREEN 0x07E0 36 | #define CYAN 0x07FF 37 | #define MAGENTA 0xF81F 38 | #define YELLOW 0xFFE0 39 | #define WHITE 0xFFFF 40 | 41 | Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); 42 | // If using the shield, all control and data lines are fixed, and 43 | // a simpler declaration can optionally be used: 44 | // Adafruit_TFTLCD tft; 45 | 46 | void setup(void) { 47 | Serial.begin(9600); 48 | Serial.println(F("TFT LCD test")); 49 | 50 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 51 | Serial.println(F("Using Adafruit 2.8\" TFT Arduino Shield Pinout")); 52 | #else 53 | Serial.println(F("Using Adafruit 2.8\" TFT Breakout Board Pinout")); 54 | #endif 55 | 56 | tft.reset(); 57 | 58 | uint16_t identifier = tft.readID(); 59 | 60 | if(identifier == 0x9325) { 61 | Serial.println(F("Found ILI9325 LCD driver")); 62 | } else if(identifier == 0x9328) { 63 | Serial.println(F("Found ILI9328 LCD driver")); 64 | } else if(identifier == 0x7575) { 65 | Serial.println(F("Found HX8347G LCD driver")); 66 | } else if(identifier == 0x9341) { 67 | Serial.println(F("Found ILI9341 LCD driver")); 68 | } else if(identifier == 0x8357) { 69 | Serial.println(F("Found HX8357D LCD driver")); 70 | } else { 71 | Serial.print(F("Unknown LCD driver chip: ")); 72 | Serial.println(identifier, HEX); 73 | Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:")); 74 | Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT")); 75 | Serial.println(F("should appear in the library header (Adafruit_TFT.h).")); 76 | Serial.println(F("If using the breakout board, it should NOT be #defined!")); 77 | Serial.println(F("Also if using the breakout, double-check that all wiring")); 78 | Serial.println(F("matches the tutorial.")); 79 | return; 80 | } 81 | 82 | tft.begin(identifier); 83 | 84 | tft.fillScreen(BLACK); 85 | 86 | Serial.println(F("This is a test of the rotation capabilities of the TFT library!")); 87 | Serial.println(F("Press (or type a character) to advance")); 88 | } 89 | 90 | void loop(void) { 91 | rotatePixel(); 92 | rotateLine(); 93 | rotateFastline(); 94 | rotateDrawrect(); 95 | rotateFillrect(); 96 | rotateDrawcircle(); 97 | rotateFillcircle(); 98 | rotateText(); 99 | } 100 | 101 | void rotateText() { 102 | for (uint8_t i=0; i<4; i++) { 103 | tft.fillScreen(BLACK); 104 | Serial.println(tft.getRotation(), DEC); 105 | 106 | tft.setCursor(0, 30); 107 | tft.setTextColor(RED); 108 | tft.setTextSize(1); 109 | tft.println("Hello World!"); 110 | tft.setTextColor(YELLOW); 111 | tft.setTextSize(2); 112 | tft.println("Hello World!"); 113 | tft.setTextColor(GREEN); 114 | tft.setTextSize(3); 115 | tft.println("Hello World!"); 116 | tft.setTextColor(BLUE); 117 | tft.setTextSize(4); 118 | tft.print(1234.567); 119 | 120 | while (!Serial.available()); 121 | Serial.read(); Serial.read(); Serial.read(); 122 | 123 | tft.setRotation(tft.getRotation()+1); 124 | } 125 | } 126 | 127 | void rotateFillcircle(void) { 128 | for (uint8_t i=0; i<4; i++) { 129 | tft.fillScreen(BLACK); 130 | Serial.println(tft.getRotation(), DEC); 131 | 132 | tft.fillCircle(10, 30, 10, YELLOW); 133 | 134 | while (!Serial.available()); 135 | Serial.read(); Serial.read(); Serial.read(); 136 | 137 | tft.setRotation(tft.getRotation()+1); 138 | } 139 | } 140 | 141 | void rotateDrawcircle(void) { 142 | for (uint8_t i=0; i<4; i++) { 143 | tft.fillScreen(BLACK); 144 | Serial.println(tft.getRotation(), DEC); 145 | 146 | tft.drawCircle(10, 30, 10, YELLOW); 147 | 148 | while (!Serial.available()); 149 | Serial.read(); Serial.read(); Serial.read(); 150 | 151 | tft.setRotation(tft.getRotation()+1); 152 | } 153 | } 154 | 155 | void rotateFillrect(void) { 156 | for (uint8_t i=0; i<4; i++) { 157 | tft.fillScreen(BLACK); 158 | Serial.println(tft.getRotation(), DEC); 159 | 160 | tft.fillRect(10, 20, 10, 20, GREEN); 161 | 162 | while (!Serial.available()); 163 | Serial.read(); Serial.read(); Serial.read(); 164 | 165 | tft.setRotation(tft.getRotation()+1); 166 | } 167 | } 168 | 169 | void rotateDrawrect(void) { 170 | for (uint8_t i=0; i<4; i++) { 171 | tft.fillScreen(BLACK); 172 | Serial.println(tft.getRotation(), DEC); 173 | 174 | tft.drawRect(10, 20, 10, 20, GREEN); 175 | 176 | while (!Serial.available()); 177 | Serial.read(); Serial.read(); Serial.read(); 178 | 179 | tft.setRotation(tft.getRotation()+1); 180 | } 181 | } 182 | 183 | void rotateFastline(void) { 184 | for (uint8_t i=0; i<4; i++) { 185 | tft.fillScreen(BLACK); 186 | Serial.println(tft.getRotation(), DEC); 187 | 188 | tft.drawFastHLine(0, 20, tft.width(), RED); 189 | tft.drawFastVLine(20, 0, tft.height(), BLUE); 190 | 191 | while (!Serial.available()); 192 | Serial.read(); Serial.read(); Serial.read(); 193 | 194 | tft.setRotation(tft.getRotation()+1); 195 | } 196 | } 197 | 198 | void rotateLine(void) { 199 | for (uint8_t i=0; i<4; i++) { 200 | tft.fillScreen(BLACK); 201 | Serial.println(tft.getRotation(), DEC); 202 | 203 | tft.drawLine(tft.width()/2, tft.height()/2, 0, 0, RED); 204 | while (!Serial.available()); 205 | Serial.read(); Serial.read(); Serial.read(); 206 | 207 | tft.setRotation(tft.getRotation()+1); 208 | } 209 | } 210 | 211 | void rotatePixel(void) { 212 | for (uint8_t i=0; i<4; i++) { 213 | tft.fillScreen(BLACK); 214 | Serial.println(tft.getRotation(), DEC); 215 | 216 | tft.drawPixel(10,20, RED); 217 | while (!Serial.available()); 218 | Serial.read(); Serial.read(); Serial.read(); 219 | 220 | tft.setRotation(tft.getRotation()+1); 221 | } 222 | } 223 | 224 | -------------------------------------------------------------------------------- /examples/tftbmp/tftbmp.ino: -------------------------------------------------------------------------------- 1 | // BMP-loading example specifically for the TFTLCD breakout board. 2 | // If using the Arduino shield, use the tftbmp_shield.pde sketch instead! 3 | // If using an Arduino Mega make sure to use its hardware SPI pins, OR make 4 | // sure the SD library is configured for 'soft' SPI in the file Sd2Card.h. 5 | 6 | #include // Core graphics library 7 | #include // Hardware-specific library 8 | #include 9 | #include 10 | 11 | // The control pins for the LCD can be assigned to any digital or 12 | // analog pins...but we'll use the analog pins as this allows us to 13 | // double up the pins with the touch screen (see the TFT paint example). 14 | #define LCD_CS A3 // Chip Select goes to Analog 3 15 | #define LCD_CD A2 // Command/Data goes to Analog 2 16 | #define LCD_WR A1 // LCD Write goes to Analog 1 17 | #define LCD_RD A0 // LCD Read goes to Analog 0 18 | 19 | // When using the BREAKOUT BOARD only, use these 8 data lines to the LCD: 20 | // For the Arduino Uno, Duemilanove, Diecimila, etc.: 21 | // D0 connects to digital pin 8 (Notice these are 22 | // D1 connects to digital pin 9 NOT in order!) 23 | // D2 connects to digital pin 2 24 | // D3 connects to digital pin 3 25 | // D4 connects to digital pin 4 26 | // D5 connects to digital pin 5 27 | // D6 connects to digital pin 6 28 | // D7 connects to digital pin 7 29 | // For the Arduino Mega, use digital pins 22 through 29 30 | // (on the 2-row header at the end of the board). 31 | 32 | // For Arduino Uno/Duemilanove, etc 33 | // connect the SD card with DI going to pin 11, DO going to pin 12 and SCK going to pin 13 (standard) 34 | // Then pin 10 goes to CS (or whatever you have set up) 35 | #define SD_CS 10 // Set the chip select line to whatever you use (10 doesnt conflict with the library) 36 | 37 | // In the SD card, place 24 bit color BMP files (be sure they are 24-bit!) 38 | // There are examples in the sketch folder 39 | 40 | // our TFT wiring 41 | Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4); 42 | 43 | void setup() 44 | { 45 | Serial.begin(9600); 46 | 47 | tft.reset(); 48 | 49 | uint16_t identifier = tft.readID(); 50 | 51 | if(identifier == 0x9325) { 52 | Serial.println(F("Found ILI9325 LCD driver")); 53 | } else if(identifier == 0x9328) { 54 | Serial.println(F("Found ILI9328 LCD driver")); 55 | } else if(identifier == 0x7575) { 56 | Serial.println(F("Found HX8347G LCD driver")); 57 | } else if(identifier == 0x9341) { 58 | Serial.println(F("Found ILI9341 LCD driver")); 59 | } else if(identifier == 0x8357) { 60 | Serial.println(F("Found HX8357D LCD driver")); 61 | } else { 62 | Serial.print(F("Unknown LCD driver chip: ")); 63 | Serial.println(identifier, HEX); 64 | Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:")); 65 | Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT")); 66 | Serial.println(F("should appear in the library header (Adafruit_TFT.h).")); 67 | Serial.println(F("If using the breakout board, it should NOT be #defined!")); 68 | Serial.println(F("Also if using the breakout, double-check that all wiring")); 69 | Serial.println(F("matches the tutorial.")); 70 | return; 71 | } 72 | 73 | tft.begin(identifier); 74 | 75 | Serial.print(F("Initializing SD card...")); 76 | if (!SD.begin(SD_CS)) { 77 | Serial.println(F("failed!")); 78 | return; 79 | } 80 | Serial.println(F("OK!")); 81 | 82 | bmpDraw("woof.bmp", 0, 0); 83 | delay(1000); 84 | } 85 | 86 | void loop() 87 | { 88 | for(int i = 0; i<4; i++) { 89 | tft.setRotation(i); 90 | tft.fillScreen(0); 91 | for(int j=0; j <= 200; j += 50) { 92 | bmpDraw("miniwoof.bmp", j, j); 93 | } 94 | delay(1000); 95 | } 96 | } 97 | 98 | // This function opens a Windows Bitmap (BMP) file and 99 | // displays it at the given coordinates. It's sped up 100 | // by reading many pixels worth of data at a time 101 | // (rather than pixel by pixel). Increasing the buffer 102 | // size takes more of the Arduino's precious RAM but 103 | // makes loading a little faster. 20 pixels seems a 104 | // good balance. 105 | 106 | #define BUFFPIXEL 20 107 | 108 | void bmpDraw(char *filename, int x, int y) { 109 | 110 | File bmpFile; 111 | int bmpWidth, bmpHeight; // W+H in pixels 112 | uint8_t bmpDepth; // Bit depth (currently must be 24) 113 | uint32_t bmpImageoffset; // Start of image data in file 114 | uint32_t rowSize; // Not always = bmpWidth; may have padding 115 | uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel) 116 | uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel) 117 | uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer 118 | boolean goodBmp = false; // Set to true on valid header parse 119 | boolean flip = true; // BMP is stored bottom-to-top 120 | int w, h, row, col; 121 | uint8_t r, g, b; 122 | uint32_t pos = 0, startTime = millis(); 123 | uint8_t lcdidx = 0; 124 | boolean first = true; 125 | 126 | if((x >= tft.width()) || (y >= tft.height())) return; 127 | 128 | Serial.println(); 129 | Serial.print(F("Loading image '")); 130 | Serial.print(filename); 131 | Serial.println('\''); 132 | // Open requested file on SD card 133 | if ((bmpFile = SD.open(filename)) == NULL) { 134 | Serial.println(F("File not found")); 135 | return; 136 | } 137 | 138 | // Parse BMP header 139 | if(read16(bmpFile) == 0x4D42) { // BMP signature 140 | Serial.println(F("File size: ")); Serial.println(read32(bmpFile)); 141 | (void)read32(bmpFile); // Read & ignore creator bytes 142 | bmpImageoffset = read32(bmpFile); // Start of image data 143 | Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC); 144 | // Read DIB header 145 | Serial.print(F("Header size: ")); Serial.println(read32(bmpFile)); 146 | bmpWidth = read32(bmpFile); 147 | bmpHeight = read32(bmpFile); 148 | if(read16(bmpFile) == 1) { // # planes -- must be '1' 149 | bmpDepth = read16(bmpFile); // bits per pixel 150 | Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth); 151 | if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed 152 | 153 | goodBmp = true; // Supported BMP format -- proceed! 154 | Serial.print(F("Image size: ")); 155 | Serial.print(bmpWidth); 156 | Serial.print('x'); 157 | Serial.println(bmpHeight); 158 | 159 | // BMP rows are padded (if needed) to 4-byte boundary 160 | rowSize = (bmpWidth * 3 + 3) & ~3; 161 | 162 | // If bmpHeight is negative, image is in top-down order. 163 | // This is not canon but has been observed in the wild. 164 | if(bmpHeight < 0) { 165 | bmpHeight = -bmpHeight; 166 | flip = false; 167 | } 168 | 169 | // Crop area to be loaded 170 | w = bmpWidth; 171 | h = bmpHeight; 172 | if((x+w-1) >= tft.width()) w = tft.width() - x; 173 | if((y+h-1) >= tft.height()) h = tft.height() - y; 174 | 175 | // Set TFT address window to clipped image bounds 176 | tft.setAddrWindow(x, y, x+w-1, y+h-1); 177 | 178 | for (row=0; row= sizeof(sdbuffer)) { // Indeed 197 | // Push LCD buffer to the display first 198 | if(lcdidx > 0) { 199 | tft.pushColors(lcdbuffer, lcdidx, first); 200 | lcdidx = 0; 201 | first = false; 202 | } 203 | bmpFile.read(sdbuffer, sizeof(sdbuffer)); 204 | buffidx = 0; // Set index to beginning 205 | } 206 | 207 | // Convert pixel from BMP to TFT format 208 | b = sdbuffer[buffidx++]; 209 | g = sdbuffer[buffidx++]; 210 | r = sdbuffer[buffidx++]; 211 | lcdbuffer[lcdidx++] = tft.color565(r,g,b); 212 | } // end pixel 213 | } // end scanline 214 | // Write any remaining data to LCD 215 | if(lcdidx > 0) { 216 | tft.pushColors(lcdbuffer, lcdidx, first); 217 | } 218 | Serial.print(F("Loaded in ")); 219 | Serial.print(millis() - startTime); 220 | Serial.println(" ms"); 221 | } // end goodBmp 222 | } 223 | } 224 | 225 | bmpFile.close(); 226 | if(!goodBmp) Serial.println(F("BMP format not recognized.")); 227 | } 228 | 229 | // These read 16- and 32-bit types from the SD card file. 230 | // BMP data is stored little-endian, Arduino is little-endian too. 231 | // May need to reverse subscript order if porting elsewhere. 232 | 233 | uint16_t read16(File f) { 234 | uint16_t result; 235 | ((uint8_t *)&result)[0] = f.read(); // LSB 236 | ((uint8_t *)&result)[1] = f.read(); // MSB 237 | return result; 238 | } 239 | 240 | uint32_t read32(File f) { 241 | uint32_t result; 242 | ((uint8_t *)&result)[0] = f.read(); // LSB 243 | ((uint8_t *)&result)[1] = f.read(); 244 | ((uint8_t *)&result)[2] = f.read(); 245 | ((uint8_t *)&result)[3] = f.read(); // MSB 246 | return result; 247 | } 248 | 249 | -------------------------------------------------------------------------------- /examples/tftbmp_shield/tftbmp_shield.ino: -------------------------------------------------------------------------------- 1 | // BMP-loading example specifically for the TFTLCD Arduino shield. 2 | // If using the breakout board, use the tftbmp.pde sketch instead! 3 | // If using an Arduino Mega and your sheild does not use the ICSP header for 4 | // SPI, make sure the SD library is configured for 'soft' SPI in the file Sd2Card.h. 5 | // If in doubt, update the library to use 'soft' SPI. 6 | 7 | #include // Core graphics library 8 | #include // Hardware-specific library 9 | #include 10 | 11 | // In the SD card, place 24 bit color BMP files (be sure they are 24-bit!) 12 | // There are examples in the sketch folder 13 | 14 | #define SD_CS 5 // Card select for shield use 15 | 16 | Adafruit_TFTLCD tft; 17 | uint8_t spi_save; 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | 23 | tft.reset(); 24 | 25 | uint16_t identifier = tft.readID(); 26 | 27 | if(identifier == 0x9325) { 28 | Serial.println(F("Found ILI9325 LCD driver")); 29 | } else if(identifier == 0x9328) { 30 | Serial.println(F("Found ILI9328 LCD driver")); 31 | } else if(identifier == 0x7575) { 32 | Serial.println(F("Found HX8347G LCD driver")); 33 | } else if(identifier == 0x9341) { 34 | Serial.println(F("Found ILI9341 LCD driver")); 35 | } else { 36 | Serial.print(F("Unknown LCD driver chip: ")); 37 | Serial.println(identifier, HEX); 38 | Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:")); 39 | Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT")); 40 | Serial.println(F("should appear in the library header (Adafruit_TFT.h).")); 41 | Serial.println(F("If using the breakout board, it should NOT be #defined!")); 42 | Serial.println(F("Also if using the breakout, double-check that all wiring")); 43 | Serial.println(F("matches the tutorial.")); 44 | return; 45 | } 46 | 47 | tft.begin(identifier); 48 | 49 | Serial.print(F("Initializing SD card...")); 50 | if (!SD.begin(SD_CS)) { 51 | Serial.println(F("failed!")); 52 | return; 53 | } 54 | Serial.println(F("OK!")); 55 | spi_save = SPCR; 56 | 57 | bmpDraw("woof.bmp", 0, 0); 58 | delay(1000); 59 | } 60 | 61 | void loop() 62 | { 63 | for(int i = 0; i<4; i++) { 64 | tft.setRotation(i); 65 | tft.fillScreen(0); 66 | for(int j=0; j <= 200; j += 50) { 67 | bmpDraw("miniwoof.bmp", j, j); 68 | } 69 | delay(1000); 70 | } 71 | } 72 | 73 | // This function opens a Windows Bitmap (BMP) file and 74 | // displays it at the given coordinates. It's sped up 75 | // by reading many pixels worth of data at a time 76 | // (rather than pixel by pixel). Increasing the buffer 77 | // size takes more of the Arduino's precious RAM but 78 | // makes loading a little faster. 20 pixels seems a 79 | // good balance. 80 | 81 | #define BUFFPIXEL 20 82 | 83 | void bmpDraw(char *filename, int x, int y) { 84 | File bmpFile; 85 | int bmpWidth, bmpHeight; // W+H in pixels 86 | uint8_t bmpDepth; // Bit depth (currently must be 24) 87 | uint32_t bmpImageoffset; // Start of image data in file 88 | uint32_t rowSize; // Not always = bmpWidth; may have padding 89 | uint8_t sdbuffer[3*BUFFPIXEL]; // pixel in buffer (R+G+B per pixel) 90 | uint16_t lcdbuffer[BUFFPIXEL]; // pixel out buffer (16-bit per pixel) 91 | uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer 92 | boolean goodBmp = false; // Set to true on valid header parse 93 | boolean flip = true; // BMP is stored bottom-to-top 94 | int w, h, row, col; 95 | uint8_t r, g, b; 96 | uint32_t pos = 0, startTime = millis(); 97 | uint8_t lcdidx = 0; 98 | boolean first = true; 99 | 100 | if((x >= tft.width()) || (y >= tft.height())) return; 101 | 102 | Serial.println(); 103 | Serial.print("Loading image '"); 104 | Serial.print(filename); 105 | Serial.println('\''); 106 | // Open requested file on SD card 107 | SPCR = spi_save; 108 | if ((bmpFile = SD.open(filename)) == NULL) { 109 | Serial.print("File not found"); 110 | return; 111 | } 112 | 113 | // Parse BMP header 114 | if(read16(bmpFile) == 0x4D42) { // BMP signature 115 | Serial.print(F("File size: ")); Serial.println(read32(bmpFile)); 116 | (void)read32(bmpFile); // Read & ignore creator bytes 117 | bmpImageoffset = read32(bmpFile); // Start of image data 118 | Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC); 119 | // Read DIB header 120 | Serial.print(F("Header size: ")); Serial.println(read32(bmpFile)); 121 | bmpWidth = read32(bmpFile); 122 | bmpHeight = read32(bmpFile); 123 | if(read16(bmpFile) == 1) { // # planes -- must be '1' 124 | bmpDepth = read16(bmpFile); // bits per pixel 125 | Serial.print(F("Bit Depth: ")); Serial.println(bmpDepth); 126 | if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed 127 | 128 | goodBmp = true; // Supported BMP format -- proceed! 129 | Serial.print(F("Image size: ")); 130 | Serial.print(bmpWidth); 131 | Serial.print('x'); 132 | Serial.println(bmpHeight); 133 | 134 | // BMP rows are padded (if needed) to 4-byte boundary 135 | rowSize = (bmpWidth * 3 + 3) & ~3; 136 | 137 | // If bmpHeight is negative, image is in top-down order. 138 | // This is not canon but has been observed in the wild. 139 | if(bmpHeight < 0) { 140 | bmpHeight = -bmpHeight; 141 | flip = false; 142 | } 143 | 144 | // Crop area to be loaded 145 | w = bmpWidth; 146 | h = bmpHeight; 147 | if((x+w-1) >= tft.width()) w = tft.width() - x; 148 | if((y+h-1) >= tft.height()) h = tft.height() - y; 149 | 150 | // Set TFT address window to clipped image bounds 151 | SPCR = 0; 152 | tft.setAddrWindow(x, y, x+w-1, y+h-1); 153 | 154 | for (row=0; row= sizeof(sdbuffer)) { // Indeed 174 | // Push LCD buffer to the display first 175 | if(lcdidx > 0) { 176 | SPCR = 0; 177 | tft.pushColors(lcdbuffer, lcdidx, first); 178 | lcdidx = 0; 179 | first = false; 180 | } 181 | SPCR = spi_save; 182 | bmpFile.read(sdbuffer, sizeof(sdbuffer)); 183 | buffidx = 0; // Set index to beginning 184 | } 185 | 186 | // Convert pixel from BMP to TFT format 187 | b = sdbuffer[buffidx++]; 188 | g = sdbuffer[buffidx++]; 189 | r = sdbuffer[buffidx++]; 190 | lcdbuffer[lcdidx++] = tft.color565(r,g,b); 191 | } // end pixel 192 | } // end scanline 193 | // Write any remaining data to LCD 194 | if(lcdidx > 0) { 195 | SPCR = 0; 196 | tft.pushColors(lcdbuffer, lcdidx, first); 197 | } 198 | Serial.print(F("Loaded in ")); 199 | Serial.print(millis() - startTime); 200 | Serial.println(" ms"); 201 | } // end goodBmp 202 | } 203 | } 204 | 205 | bmpFile.close(); 206 | if(!goodBmp) Serial.println("BMP format not recognized."); 207 | } 208 | 209 | // These read 16- and 32-bit types from the SD card file. 210 | // BMP data is stored little-endian, Arduino is little-endian too. 211 | // May need to reverse subscript order if porting elsewhere. 212 | 213 | uint16_t read16(File f) { 214 | uint16_t result; 215 | ((uint8_t *)&result)[0] = f.read(); // LSB 216 | ((uint8_t *)&result)[1] = f.read(); // MSB 217 | return result; 218 | } 219 | 220 | uint32_t read32(File f) { 221 | uint32_t result; 222 | ((uint8_t *)&result)[0] = f.read(); // LSB 223 | ((uint8_t *)&result)[1] = f.read(); 224 | ((uint8_t *)&result)[2] = f.read(); 225 | ((uint8_t *)&result)[3] = f.read(); // MSB 226 | return result; 227 | } 228 | 229 | -------------------------------------------------------------------------------- /examples/tftpaint/tftpaint.ino: -------------------------------------------------------------------------------- 1 | // Paint example specifically for the TFTLCD breakout board. 2 | // If using the Arduino shield, use the tftpaint_shield.pde sketch instead! 3 | // DOES NOT CURRENTLY WORK ON ARDUINO LEONARDO 4 | 5 | #include // Core graphics library 6 | #include // Hardware-specific library 7 | #include 8 | 9 | #if defined(__SAM3X8E__) 10 | #undef __FlashStringHelper::F(string_literal) 11 | #define F(string_literal) string_literal 12 | #endif 13 | 14 | // When using the BREAKOUT BOARD only, use these 8 data lines to the LCD: 15 | // For the Arduino Uno, Duemilanove, Diecimila, etc.: 16 | // D0 connects to digital pin 8 (Notice these are 17 | // D1 connects to digital pin 9 NOT in order!) 18 | // D2 connects to digital pin 2 19 | // D3 connects to digital pin 3 20 | // D4 connects to digital pin 4 21 | // D5 connects to digital pin 5 22 | // D6 connects to digital pin 6 23 | // D7 connects to digital pin 7 24 | 25 | // For the Arduino Mega, use digital pins 22 through 29 26 | // (on the 2-row header at the end of the board). 27 | // D0 connects to digital pin 22 28 | // D1 connects to digital pin 23 29 | // D2 connects to digital pin 24 30 | // D3 connects to digital pin 25 31 | // D4 connects to digital pin 26 32 | // D5 connects to digital pin 27 33 | // D6 connects to digital pin 28 34 | // D7 connects to digital pin 29 35 | 36 | // For the Arduino Due, use digital pins 33 through 40 37 | // (on the 2-row header at the end of the board). 38 | // D0 connects to digital pin 33 39 | // D1 connects to digital pin 34 40 | // D2 connects to digital pin 35 41 | // D3 connects to digital pin 36 42 | // D4 connects to digital pin 37 43 | // D5 connects to digital pin 38 44 | // D6 connects to digital pin 39 45 | // D7 connects to digital pin 40 46 | 47 | #define YP A3 // must be an analog pin, use "An" notation! 48 | #define XM A2 // must be an analog pin, use "An" notation! 49 | #define YM 9 // can be a digital pin 50 | #define XP 8 // can be a digital pin 51 | 52 | #define TS_MINX 150 53 | #define TS_MINY 120 54 | #define TS_MAXX 920 55 | #define TS_MAXY 940 56 | 57 | // For better pressure precision, we need to know the resistance 58 | // between X+ and X- Use any multimeter to read it 59 | // For the one we're using, its 300 ohms across the X plate 60 | TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); 61 | 62 | #define LCD_CS A3 63 | #define LCD_CD A2 64 | #define LCD_WR A1 65 | #define LCD_RD A0 66 | // optional 67 | #define LCD_RESET A4 68 | 69 | // Assign human-readable names to some common 16-bit color values: 70 | #define BLACK 0x0000 71 | #define BLUE 0x001F 72 | #define RED 0xF800 73 | #define GREEN 0x07E0 74 | #define CYAN 0x07FF 75 | #define MAGENTA 0xF81F 76 | #define YELLOW 0xFFE0 77 | #define WHITE 0xFFFF 78 | 79 | 80 | Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); 81 | 82 | #define BOXSIZE 40 83 | #define PENRADIUS 3 84 | int oldcolor, currentcolor; 85 | 86 | void setup(void) { 87 | Serial.begin(9600); 88 | Serial.println(F("Paint!")); 89 | 90 | tft.reset(); 91 | 92 | uint16_t identifier = tft.readID(); 93 | 94 | if(identifier == 0x9325) { 95 | Serial.println(F("Found ILI9325 LCD driver")); 96 | } else if(identifier == 0x9328) { 97 | Serial.println(F("Found ILI9328 LCD driver")); 98 | } else if(identifier == 0x7575) { 99 | Serial.println(F("Found HX8347G LCD driver")); 100 | } else if(identifier == 0x9341) { 101 | Serial.println(F("Found ILI9341 LCD driver")); 102 | } else if(identifier == 0x8357) { 103 | Serial.println(F("Found HX8357D LCD driver")); 104 | } else { 105 | Serial.print(F("Unknown LCD driver chip: ")); 106 | Serial.println(identifier, HEX); 107 | Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:")); 108 | Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT")); 109 | Serial.println(F("should appear in the library header (Adafruit_TFT.h).")); 110 | Serial.println(F("If using the breakout board, it should NOT be #defined!")); 111 | Serial.println(F("Also if using the breakout, double-check that all wiring")); 112 | Serial.println(F("matches the tutorial.")); 113 | return; 114 | } 115 | 116 | tft.begin(identifier); 117 | 118 | tft.fillScreen(BLACK); 119 | 120 | tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); 121 | tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW); 122 | tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN); 123 | tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN); 124 | tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE); 125 | tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA); 126 | // tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, WHITE); 127 | 128 | tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); 129 | currentcolor = RED; 130 | 131 | pinMode(13, OUTPUT); 132 | } 133 | 134 | #define MINPRESSURE 10 135 | #define MAXPRESSURE 1000 136 | 137 | void loop() 138 | { 139 | digitalWrite(13, HIGH); 140 | TSPoint p = ts.getPoint(); 141 | digitalWrite(13, LOW); 142 | 143 | // if sharing pins, you'll need to fix the directions of the touchscreen pins 144 | //pinMode(XP, OUTPUT); 145 | pinMode(XM, OUTPUT); 146 | pinMode(YP, OUTPUT); 147 | //pinMode(YM, OUTPUT); 148 | 149 | // we have some minimum pressure we consider 'valid' 150 | // pressure of 0 means no pressing! 151 | 152 | if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { 153 | /* 154 | Serial.print("X = "); Serial.print(p.x); 155 | Serial.print("\tY = "); Serial.print(p.y); 156 | Serial.print("\tPressure = "); Serial.println(p.z); 157 | */ 158 | 159 | if (p.y < (TS_MINY-5)) { 160 | Serial.println("erase"); 161 | // press the bottom of the screen to erase 162 | tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK); 163 | } 164 | // scale from 0->1023 to tft.width 165 | p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0); 166 | p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0); 167 | /* 168 | Serial.print("("); Serial.print(p.x); 169 | Serial.print(", "); Serial.print(p.y); 170 | Serial.println(")"); 171 | */ 172 | if (p.y < BOXSIZE) { 173 | oldcolor = currentcolor; 174 | 175 | if (p.x < BOXSIZE) { 176 | currentcolor = RED; 177 | tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); 178 | } else if (p.x < BOXSIZE*2) { 179 | currentcolor = YELLOW; 180 | tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); 181 | } else if (p.x < BOXSIZE*3) { 182 | currentcolor = GREEN; 183 | tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, WHITE); 184 | } else if (p.x < BOXSIZE*4) { 185 | currentcolor = CYAN; 186 | tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, WHITE); 187 | } else if (p.x < BOXSIZE*5) { 188 | currentcolor = BLUE; 189 | tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, WHITE); 190 | } else if (p.x < BOXSIZE*6) { 191 | currentcolor = MAGENTA; 192 | tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, WHITE); 193 | } 194 | 195 | if (oldcolor != currentcolor) { 196 | if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); 197 | if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW); 198 | if (oldcolor == GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN); 199 | if (oldcolor == CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN); 200 | if (oldcolor == BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE); 201 | if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA); 202 | } 203 | } 204 | if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) { 205 | tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor); 206 | } 207 | } 208 | } 209 | 210 | -------------------------------------------------------------------------------- /examples/tftpaint_shield/glcdfont.c: -------------------------------------------------------------------------------- 1 | 2 | #ifndef FONT5X7_H 3 | #define FONT5X7_H 4 | 5 | // standard ascii 5x7 font 6 | 7 | static unsigned char font[] = { 8 | 0x00, 0x00, 0x00, 0x00, 0x00, 9 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 10 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 11 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 12 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 13 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 14 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 15 | 0x00, 0x18, 0x3C, 0x18, 0x00, 16 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 17 | 0x00, 0x18, 0x24, 0x18, 0x00, 18 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 19 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 20 | 0x26, 0x29, 0x79, 0x29, 0x26, 21 | 0x40, 0x7F, 0x05, 0x05, 0x07, 22 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 23 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 24 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 25 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 26 | 0x14, 0x22, 0x7F, 0x22, 0x14, 27 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 28 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 29 | 0x00, 0x66, 0x89, 0x95, 0x6A, 30 | 0x60, 0x60, 0x60, 0x60, 0x60, 31 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 32 | 0x08, 0x04, 0x7E, 0x04, 0x08, 33 | 0x10, 0x20, 0x7E, 0x20, 0x10, 34 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 35 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 36 | 0x1E, 0x10, 0x10, 0x10, 0x10, 37 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 38 | 0x30, 0x38, 0x3E, 0x38, 0x30, 39 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x5F, 0x00, 0x00, 42 | 0x00, 0x07, 0x00, 0x07, 0x00, 43 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 44 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 45 | 0x23, 0x13, 0x08, 0x64, 0x62, 46 | 0x36, 0x49, 0x56, 0x20, 0x50, 47 | 0x00, 0x08, 0x07, 0x03, 0x00, 48 | 0x00, 0x1C, 0x22, 0x41, 0x00, 49 | 0x00, 0x41, 0x22, 0x1C, 0x00, 50 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 51 | 0x08, 0x08, 0x3E, 0x08, 0x08, 52 | 0x00, 0x80, 0x70, 0x30, 0x00, 53 | 0x08, 0x08, 0x08, 0x08, 0x08, 54 | 0x00, 0x00, 0x60, 0x60, 0x00, 55 | 0x20, 0x10, 0x08, 0x04, 0x02, 56 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 57 | 0x00, 0x42, 0x7F, 0x40, 0x00, 58 | 0x72, 0x49, 0x49, 0x49, 0x46, 59 | 0x21, 0x41, 0x49, 0x4D, 0x33, 60 | 0x18, 0x14, 0x12, 0x7F, 0x10, 61 | 0x27, 0x45, 0x45, 0x45, 0x39, 62 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 63 | 0x41, 0x21, 0x11, 0x09, 0x07, 64 | 0x36, 0x49, 0x49, 0x49, 0x36, 65 | 0x46, 0x49, 0x49, 0x29, 0x1E, 66 | 0x00, 0x00, 0x14, 0x00, 0x00, 67 | 0x00, 0x40, 0x34, 0x00, 0x00, 68 | 0x00, 0x08, 0x14, 0x22, 0x41, 69 | 0x14, 0x14, 0x14, 0x14, 0x14, 70 | 0x00, 0x41, 0x22, 0x14, 0x08, 71 | 0x02, 0x01, 0x59, 0x09, 0x06, 72 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 73 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 74 | 0x7F, 0x49, 0x49, 0x49, 0x36, 75 | 0x3E, 0x41, 0x41, 0x41, 0x22, 76 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 77 | 0x7F, 0x49, 0x49, 0x49, 0x41, 78 | 0x7F, 0x09, 0x09, 0x09, 0x01, 79 | 0x3E, 0x41, 0x41, 0x51, 0x73, 80 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 81 | 0x00, 0x41, 0x7F, 0x41, 0x00, 82 | 0x20, 0x40, 0x41, 0x3F, 0x01, 83 | 0x7F, 0x08, 0x14, 0x22, 0x41, 84 | 0x7F, 0x40, 0x40, 0x40, 0x40, 85 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 86 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 87 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 88 | 0x7F, 0x09, 0x09, 0x09, 0x06, 89 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 90 | 0x7F, 0x09, 0x19, 0x29, 0x46, 91 | 0x26, 0x49, 0x49, 0x49, 0x32, 92 | 0x03, 0x01, 0x7F, 0x01, 0x03, 93 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 94 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 95 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 96 | 0x63, 0x14, 0x08, 0x14, 0x63, 97 | 0x03, 0x04, 0x78, 0x04, 0x03, 98 | 0x61, 0x59, 0x49, 0x4D, 0x43, 99 | 0x00, 0x7F, 0x41, 0x41, 0x41, 100 | 0x02, 0x04, 0x08, 0x10, 0x20, 101 | 0x00, 0x41, 0x41, 0x41, 0x7F, 102 | 0x04, 0x02, 0x01, 0x02, 0x04, 103 | 0x40, 0x40, 0x40, 0x40, 0x40, 104 | 0x00, 0x03, 0x07, 0x08, 0x00, 105 | 0x20, 0x54, 0x54, 0x78, 0x40, 106 | 0x7F, 0x28, 0x44, 0x44, 0x38, 107 | 0x38, 0x44, 0x44, 0x44, 0x28, 108 | 0x38, 0x44, 0x44, 0x28, 0x7F, 109 | 0x38, 0x54, 0x54, 0x54, 0x18, 110 | 0x00, 0x08, 0x7E, 0x09, 0x02, 111 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 112 | 0x7F, 0x08, 0x04, 0x04, 0x78, 113 | 0x00, 0x44, 0x7D, 0x40, 0x00, 114 | 0x20, 0x40, 0x40, 0x3D, 0x00, 115 | 0x7F, 0x10, 0x28, 0x44, 0x00, 116 | 0x00, 0x41, 0x7F, 0x40, 0x00, 117 | 0x7C, 0x04, 0x78, 0x04, 0x78, 118 | 0x7C, 0x08, 0x04, 0x04, 0x78, 119 | 0x38, 0x44, 0x44, 0x44, 0x38, 120 | 0xFC, 0x18, 0x24, 0x24, 0x18, 121 | 0x18, 0x24, 0x24, 0x18, 0xFC, 122 | 0x7C, 0x08, 0x04, 0x04, 0x08, 123 | 0x48, 0x54, 0x54, 0x54, 0x24, 124 | 0x04, 0x04, 0x3F, 0x44, 0x24, 125 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 126 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 127 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 128 | 0x44, 0x28, 0x10, 0x28, 0x44, 129 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 130 | 0x44, 0x64, 0x54, 0x4C, 0x44, 131 | 0x00, 0x08, 0x36, 0x41, 0x00, 132 | 0x00, 0x00, 0x77, 0x00, 0x00, 133 | 0x00, 0x41, 0x36, 0x08, 0x00, 134 | 0x02, 0x01, 0x02, 0x04, 0x02, 135 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 136 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 137 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 138 | 0x38, 0x54, 0x54, 0x55, 0x59, 139 | 0x21, 0x55, 0x55, 0x79, 0x41, 140 | 0x21, 0x54, 0x54, 0x78, 0x41, 141 | 0x21, 0x55, 0x54, 0x78, 0x40, 142 | 0x20, 0x54, 0x55, 0x79, 0x40, 143 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 144 | 0x39, 0x55, 0x55, 0x55, 0x59, 145 | 0x39, 0x54, 0x54, 0x54, 0x59, 146 | 0x39, 0x55, 0x54, 0x54, 0x58, 147 | 0x00, 0x00, 0x45, 0x7C, 0x41, 148 | 0x00, 0x02, 0x45, 0x7D, 0x42, 149 | 0x00, 0x01, 0x45, 0x7C, 0x40, 150 | 0xF0, 0x29, 0x24, 0x29, 0xF0, 151 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 152 | 0x7C, 0x54, 0x55, 0x45, 0x00, 153 | 0x20, 0x54, 0x54, 0x7C, 0x54, 154 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 155 | 0x32, 0x49, 0x49, 0x49, 0x32, 156 | 0x32, 0x48, 0x48, 0x48, 0x32, 157 | 0x32, 0x4A, 0x48, 0x48, 0x30, 158 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 159 | 0x3A, 0x42, 0x40, 0x20, 0x78, 160 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 161 | 0x39, 0x44, 0x44, 0x44, 0x39, 162 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 163 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 164 | 0x48, 0x7E, 0x49, 0x43, 0x66, 165 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 166 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 167 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 168 | 0x20, 0x54, 0x54, 0x79, 0x41, 169 | 0x00, 0x00, 0x44, 0x7D, 0x41, 170 | 0x30, 0x48, 0x48, 0x4A, 0x32, 171 | 0x38, 0x40, 0x40, 0x22, 0x7A, 172 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 173 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 174 | 0x26, 0x29, 0x29, 0x2F, 0x28, 175 | 0x26, 0x29, 0x29, 0x29, 0x26, 176 | 0x30, 0x48, 0x4D, 0x40, 0x20, 177 | 0x38, 0x08, 0x08, 0x08, 0x08, 178 | 0x08, 0x08, 0x08, 0x08, 0x38, 179 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 180 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 181 | 0x00, 0x00, 0x7B, 0x00, 0x00, 182 | 0x08, 0x14, 0x2A, 0x14, 0x22, 183 | 0x22, 0x14, 0x2A, 0x14, 0x08, 184 | 0xAA, 0x00, 0x55, 0x00, 0xAA, 185 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, 186 | 0x00, 0x00, 0x00, 0xFF, 0x00, 187 | 0x10, 0x10, 0x10, 0xFF, 0x00, 188 | 0x14, 0x14, 0x14, 0xFF, 0x00, 189 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 190 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 191 | 0x14, 0x14, 0x14, 0xFC, 0x00, 192 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 193 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 194 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 195 | 0x14, 0x14, 0x17, 0x10, 0x1F, 196 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 197 | 0x14, 0x14, 0x14, 0x1F, 0x00, 198 | 0x10, 0x10, 0x10, 0xF0, 0x00, 199 | 0x00, 0x00, 0x00, 0x1F, 0x10, 200 | 0x10, 0x10, 0x10, 0x1F, 0x10, 201 | 0x10, 0x10, 0x10, 0xF0, 0x10, 202 | 0x00, 0x00, 0x00, 0xFF, 0x10, 203 | 0x10, 0x10, 0x10, 0x10, 0x10, 204 | 0x10, 0x10, 0x10, 0xFF, 0x10, 205 | 0x00, 0x00, 0x00, 0xFF, 0x14, 206 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 207 | 0x00, 0x00, 0x1F, 0x10, 0x17, 208 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 209 | 0x14, 0x14, 0x17, 0x10, 0x17, 210 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 211 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 212 | 0x14, 0x14, 0x14, 0x14, 0x14, 213 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 214 | 0x14, 0x14, 0x14, 0x17, 0x14, 215 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 216 | 0x14, 0x14, 0x14, 0xF4, 0x14, 217 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 218 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 219 | 0x00, 0x00, 0x00, 0x1F, 0x14, 220 | 0x00, 0x00, 0x00, 0xFC, 0x14, 221 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 222 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 223 | 0x14, 0x14, 0x14, 0xFF, 0x14, 224 | 0x10, 0x10, 0x10, 0x1F, 0x00, 225 | 0x00, 0x00, 0x00, 0xF0, 0x10, 226 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 227 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 228 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 229 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 230 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 231 | 0x38, 0x44, 0x44, 0x38, 0x44, 232 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14, 233 | 0x7E, 0x02, 0x02, 0x06, 0x06, 234 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 235 | 0x63, 0x55, 0x49, 0x41, 0x63, 236 | 0x38, 0x44, 0x44, 0x3C, 0x04, 237 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 238 | 0x06, 0x02, 0x7E, 0x02, 0x02, 239 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 240 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 241 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 242 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 243 | 0x30, 0x48, 0x78, 0x48, 0x30, 244 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 245 | 0x3E, 0x49, 0x49, 0x49, 0x00, 246 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 247 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 248 | 0x44, 0x44, 0x5F, 0x44, 0x44, 249 | 0x40, 0x51, 0x4A, 0x44, 0x40, 250 | 0x40, 0x44, 0x4A, 0x51, 0x40, 251 | 0x00, 0x00, 0xFF, 0x01, 0x03, 252 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 253 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 254 | 0x36, 0x12, 0x36, 0x24, 0x36, 255 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 256 | 0x00, 0x00, 0x18, 0x18, 0x00, 257 | 0x00, 0x00, 0x10, 0x10, 0x00, 258 | 0x30, 0x40, 0xFF, 0x01, 0x01, 259 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 260 | 0x00, 0x19, 0x1D, 0x17, 0x12, 261 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 262 | 0x00, 0x00, 0x00, 0x00, 0x00, 263 | }; 264 | #endif 265 | -------------------------------------------------------------------------------- /examples/tftpaint_shield/tftpaint_shield.ino: -------------------------------------------------------------------------------- 1 | // Paint example specifically for the TFTLCD Arduino shield. 2 | // If using the breakout board, use the tftpaint.pde sketch instead! 3 | 4 | #include // Core graphics library 5 | #include // Hardware-specific library 6 | #include 7 | 8 | #if defined(__SAM3X8E__) 9 | #undef __FlashStringHelper::F(string_literal) 10 | #define F(string_literal) string_literal 11 | #endif 12 | 13 | #ifndef USE_ADAFRUIT_SHIELD_PINOUT 14 | #error "This sketch is intended for use with the TFT LCD Shield. Make sure that USE_ADAFRUIT_SHIELD_PINOUT is #defined in the Adafruit_TFTLCD.h library file." 15 | #endif 16 | 17 | // These are the pins for the shield! 18 | #define YP A1 // must be an analog pin, use "An" notation! 19 | #define XM A2 // must be an analog pin, use "An" notation! 20 | #define YM 7 // can be a digital pin 21 | #define XP 6 // can be a digital pin 22 | 23 | #ifdef __SAM3X8E__ 24 | #define TS_MINX 125 25 | #define TS_MINY 170 26 | #define TS_MAXX 880 27 | #define TS_MAXY 940 28 | #else 29 | #define TS_MINX 150 30 | #define TS_MINY 120 31 | #define TS_MAXX 920 32 | #define TS_MAXY 940 33 | #endif 34 | 35 | // For better pressure precision, we need to know the resistance 36 | // between X+ and X- Use any multimeter to read it 37 | // For the one we're using, its 300 ohms across the X plate 38 | TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); 39 | 40 | #define LCD_CS A3 41 | #define LCD_CD A2 42 | #define LCD_WR A1 43 | #define LCD_RD A0 44 | 45 | // Assign human-readable names to some common 16-bit color values: 46 | #define BLACK 0x0000 47 | #define BLUE 0x001F 48 | #define RED 0xF800 49 | #define GREEN 0x07E0 50 | #define CYAN 0x07FF 51 | #define MAGENTA 0xF81F 52 | #define YELLOW 0xFFE0 53 | #define WHITE 0xFFFF 54 | 55 | 56 | Adafruit_TFTLCD tft; 57 | 58 | #define BOXSIZE 40 59 | #define PENRADIUS 4 60 | int oldcolor, currentcolor; 61 | 62 | void setup(void) { 63 | Serial.begin(9600); 64 | Serial.println(F("Paint!")); 65 | 66 | tft.reset(); 67 | 68 | uint16_t identifier = tft.readID(); 69 | 70 | if(identifier == 0x9325) { 71 | Serial.println(F("Found ILI9325 LCD driver")); 72 | } else if(identifier == 0x9328) { 73 | Serial.println(F("Found ILI9328 LCD driver")); 74 | } else if(identifier == 0x7575) { 75 | Serial.println(F("Found HX8347G LCD driver")); 76 | } else { 77 | Serial.print(F("Unknown LCD driver chip: ")); 78 | Serial.println(identifier, HEX); 79 | return; 80 | } 81 | 82 | tft.begin(identifier); 83 | 84 | tft.fillScreen(BLACK); 85 | 86 | tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); 87 | tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW); 88 | tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN); 89 | tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN); 90 | tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE); 91 | tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA); 92 | // tft.fillRect(BOXSIZE*6, 0, BOXSIZE, BOXSIZE, WHITE); 93 | 94 | tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); 95 | currentcolor = RED; 96 | 97 | pinMode(13, OUTPUT); 98 | } 99 | 100 | #define MINPRESSURE 10 101 | #define MAXPRESSURE 1000 102 | 103 | void loop() 104 | { 105 | digitalWrite(13, HIGH); 106 | TSPoint p = ts.getPoint(); 107 | digitalWrite(13, LOW); 108 | 109 | // if sharing pins, you'll need to fix the directions of the touchscreen pins 110 | //pinMode(XP, OUTPUT); 111 | pinMode(XM, OUTPUT); 112 | pinMode(YP, OUTPUT); 113 | //pinMode(YM, OUTPUT); 114 | 115 | // we have some minimum pressure we consider 'valid' 116 | // pressure of 0 means no pressing! 117 | 118 | if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { 119 | /* 120 | Serial.print("X = "); Serial.print(p.x); 121 | Serial.print("\tY = "); Serial.print(p.y); 122 | Serial.print("\tPressure = "); Serial.println(p.z); 123 | */ 124 | 125 | if (p.y < (TS_MINY-5)) { 126 | Serial.println("erase"); 127 | // press the bottom of the screen to erase 128 | tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, BLACK); 129 | } 130 | // scale from 0->1023 to tft.width 131 | p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0); 132 | p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0); 133 | /* 134 | Serial.print("("); Serial.print(p.x); 135 | Serial.print(", "); Serial.print(p.y); 136 | Serial.println(")"); 137 | */ 138 | if (p.y < BOXSIZE) { 139 | oldcolor = currentcolor; 140 | 141 | if (p.x < BOXSIZE) { 142 | currentcolor = RED; 143 | tft.drawRect(0, 0, BOXSIZE, BOXSIZE, WHITE); 144 | } else if (p.x < BOXSIZE*2) { 145 | currentcolor = YELLOW; 146 | tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, WHITE); 147 | } else if (p.x < BOXSIZE*3) { 148 | currentcolor = GREEN; 149 | tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, WHITE); 150 | } else if (p.x < BOXSIZE*4) { 151 | currentcolor = CYAN; 152 | tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, WHITE); 153 | } else if (p.x < BOXSIZE*5) { 154 | currentcolor = BLUE; 155 | tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, WHITE); 156 | } else if (p.x < BOXSIZE*6) { 157 | currentcolor = MAGENTA; 158 | tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, WHITE); 159 | } 160 | 161 | if (oldcolor != currentcolor) { 162 | if (oldcolor == RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, RED); 163 | if (oldcolor == YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, YELLOW); 164 | if (oldcolor == GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, GREEN); 165 | if (oldcolor == CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, CYAN); 166 | if (oldcolor == BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, BLUE); 167 | if (oldcolor == MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, MAGENTA); 168 | } 169 | } 170 | if (((p.y-PENRADIUS) > BOXSIZE) && ((p.y+PENRADIUS) < tft.height())) { 171 | tft.fillCircle(p.x, p.y, PENRADIUS, currentcolor); 172 | } 173 | } 174 | } 175 | 176 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit TFTLCD Library 2 | version=1.0.3 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Adafruit 2.8" TFT display Library 6 | paragraph=Adafruit 2.8" TFT display Library 7 | category=Display 8 | url=https://github.com/adafruit/TFTLCD-Library 9 | architectures=* 10 | depends=Adafruit GFX Library 11 | -------------------------------------------------------------------------------- /pin_magic.h: -------------------------------------------------------------------------------- 1 | #ifndef _pin_magic_ 2 | #define _pin_magic_ 3 | 4 | // This header file serves two purposes: 5 | // 6 | // 1) Isolate non-portable MCU port- and pin-specific identifiers and 7 | // operations so the library code itself remains somewhat agnostic 8 | // (PORTs and pin numbers are always referenced through macros). 9 | // 10 | // 2) GCC doesn't always respect the "inline" keyword, so this is a 11 | // ham-fisted manner of forcing the issue to minimize function calls. 12 | // This sometimes makes the library a bit bigger than before, but fast++. 13 | // However, because they're macros, we need to be SUPER CAREFUL about 14 | // parameters -- for example, write8(x) may expand to multiple PORT 15 | // writes that all refer to x, so it needs to be a constant or fixed 16 | // variable and not something like *ptr++ (which, after macro 17 | // expansion, may increment the pointer repeatedly and run off into 18 | // la-la land). Macros also give us fine-grained control over which 19 | // operations are inlined on which boards (balancing speed against 20 | // available program space). 21 | 22 | // When using the TFT shield, control and data pins exist in set physical 23 | // locations, but the ports and bitmasks corresponding to each vary among 24 | // boards. A separate set of pin definitions is given for each supported 25 | // board type. 26 | // When using the TFT breakout board, control pins are configurable but 27 | // the data pins are still fixed -- making every data pin configurable 28 | // would be much too slow. The data pin layouts are not the same between 29 | // the shield and breakout configurations -- for the latter, pins were 30 | // chosen to keep the tutorial wiring manageable more than making optimal 31 | // use of ports and bitmasks. So there's a second set of pin definitions 32 | // given for each supported board. 33 | 34 | // Shield pin usage: 35 | // LCD Data Bit : 7 6 5 4 3 2 1 0 36 | // Digital pin #: 7 6 13 4 11 10 9 8 37 | // Uno port/pin : PD7 PD6 PB5 PD4 PB3 PB2 PB1 PB0 38 | // Mega port/pin: PH4 PH3 PB7 PG5 PB5 PB4 PH6 PH5 39 | // Leo port/pin : PE6 PD7 PC7 PD4 PB7 PB6 PB5 PB4 40 | // Due port/pin : PC23 PC24 PB27 PC26 PD7 PC29 PC21 PC22 41 | // Breakout pin usage: 42 | // LCD Data Bit : 7 6 5 4 3 2 1 0 43 | // Uno dig. pin : 7 6 5 4 3 2 9 8 44 | // Uno port/pin : PD7 PD6 PD5 PD4 PD3 PD2 PB1 PB0 45 | // Mega dig. pin: 29 28 27 26 25 24 23 22 46 | // Mega port/pin: PA7 PA6 PA5 PA4 PA3 PA2 PA1 PA0 (one contiguous PORT) 47 | // Leo dig. pin : 7 6 5 4 3 2 9 8 48 | // Leo port/pin : PE6 PD7 PC6 PD4 PD0 PD1 PB5 PB4 49 | // Due dig. pin : 40 39 38 37 36 35 34 33 50 | // Due port/pin : PC8 PC7 PC6 PC5 PC4 PC3 PC2 PC1 (one contiguous PORT. -ish…) 51 | 52 | // Pixel read operations require a minimum 400 nS delay from RD_ACTIVE 53 | // to polling the input pins. At 16 MHz, one machine cycle is 62.5 nS. 54 | // This code burns 7 cycles (437.5 nS) doing nothing; the RJMPs are 55 | // equivalent to two NOPs each, final NOP burns the 7th cycle, and the 56 | // last line is a radioactive mutant emoticon. 57 | #define DELAY7 \ 58 | asm volatile("rjmp .+0" \ 59 | "\n\t" \ 60 | "rjmp .+0" \ 61 | "\n\t" \ 62 | "rjmp .+0" \ 63 | "\n\t" \ 64 | "nop" \ 65 | "\n" ::); 66 | 67 | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || \ 68 | defined(__AVR_ATmega328__) || defined(__AVR_ATmega8__) 69 | 70 | // Arduino Uno, Duemilanove, etc. 71 | 72 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 73 | 74 | // LCD control lines: 75 | // RD (read), WR (write), CD (command/data), CS (chip select) 76 | #define RD_PORT PORTC /*pin A0 */ 77 | #define WR_PORT PORTC /*pin A1 */ 78 | #define CD_PORT PORTC /*pin A2 */ 79 | #define CS_PORT PORTC /*pin A3 */ 80 | #define RD_MASK B00000001 81 | #define WR_MASK B00000010 82 | #define CD_MASK B00000100 83 | #define CS_MASK B00001000 84 | 85 | // These are macros for I/O operations... 86 | 87 | // Write 8-bit value to LCD data lines 88 | #define write8inline(d) \ 89 | { \ 90 | PORTD = (PORTD & B00101111) | ((d)&B11010000); \ 91 | PORTB = (PORTB & B11010000) | ((d)&B00101111); \ 92 | WR_STROBE; \ 93 | } // STROBEs are defined later 94 | 95 | // Read 8-bit value from LCD data lines. The signle argument 96 | // is a destination variable; this isn't a function and doesn't 97 | // return a value in the conventional sense. 98 | #define read8inline(result) \ 99 | { \ 100 | RD_ACTIVE; \ 101 | DELAY7; \ 102 | result = (PIND & B11010000) | (PINB & B00101111); \ 103 | RD_IDLE; \ 104 | } 105 | 106 | // These set the PORT directions as required before the write and read 107 | // operations. Because write operations are much more common than reads, 108 | // the data-reading functions in the library code set the PORT(s) to 109 | // input before a read, and restore them back to the write state before 110 | // returning. This avoids having to set it for output inside every 111 | // drawing method. The default state has them initialized for writes. 112 | #define setWriteDirInline() \ 113 | { \ 114 | DDRD |= B11010000; \ 115 | DDRB |= B00101111; \ 116 | } 117 | #define setReadDirInline() \ 118 | { \ 119 | DDRD &= ~B11010000; \ 120 | DDRB &= ~B00101111; \ 121 | } 122 | 123 | #else // Uno w/Breakout board 124 | 125 | #define write8inline(d) \ 126 | { \ 127 | PORTD = (PORTD & B00000011) | ((d)&B11111100); \ 128 | PORTB = (PORTB & B11111100) | ((d)&B00000011); \ 129 | WR_STROBE; \ 130 | } 131 | #define read8inline(result) \ 132 | { \ 133 | RD_ACTIVE; \ 134 | DELAY7; \ 135 | result = (PIND & B11111100) | (PINB & B00000011); \ 136 | RD_IDLE; \ 137 | } 138 | #define setWriteDirInline() \ 139 | { \ 140 | DDRD |= B11111100; \ 141 | DDRB |= B00000011; \ 142 | } 143 | #define setReadDirInline() \ 144 | { \ 145 | DDRD &= ~B11111100; \ 146 | DDRB &= ~B00000011; \ 147 | } 148 | 149 | #endif 150 | 151 | // As part of the inline control, macros reference other macros...if any 152 | // of these are left undefined, an equivalent function version (non-inline) 153 | // is declared later. The Uno has a moderate amount of program space, so 154 | // only write8() is inlined -- that one provides the most performance 155 | // benefit, but unfortunately also generates the most bloat. This is 156 | // why only certain cases are inlined for each board. 157 | #define write8 write8inline 158 | 159 | #elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) || \ 160 | defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) 161 | 162 | // Arduino Mega, ADK, etc. 163 | 164 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 165 | 166 | #define RD_PORT PORTF 167 | #define WR_PORT PORTF 168 | #define CD_PORT PORTF 169 | #define CS_PORT PORTF 170 | #define RD_MASK B00000001 171 | #define WR_MASK B00000010 172 | #define CD_MASK B00000100 173 | #define CS_MASK B00001000 174 | 175 | #define write8inline(d) \ 176 | { \ 177 | PORTH = \ 178 | (PORTH & B10000111) | (((d)&B11000000) >> 3) | (((d)&B00000011) << 5); \ 179 | PORTB = (PORTB & B01001111) | (((d)&B00101100) << 2); \ 180 | PORTG = (PORTG & B11011111) | (((d)&B00010000) << 1); \ 181 | WR_STROBE; \ 182 | } 183 | #define read8inline(result) \ 184 | { \ 185 | RD_ACTIVE; \ 186 | DELAY7; \ 187 | result = ((PINH & B00011000) << 3) | ((PINB & B10110000) >> 2) | \ 188 | ((PING & B00100000) >> 1) | ((PINH & B01100000) >> 5); \ 189 | RD_IDLE; \ 190 | } 191 | #define setWriteDirInline() \ 192 | { \ 193 | DDRH |= B01111000; \ 194 | DDRB |= B10110000; \ 195 | DDRG |= B00100000; \ 196 | } 197 | #define setReadDirInline() \ 198 | { \ 199 | DDRH &= ~B01111000; \ 200 | DDRB &= ~B10110000; \ 201 | DDRG &= ~B00100000; \ 202 | } 203 | 204 | #else // Mega w/Breakout board 205 | 206 | #define write8inline(d) \ 207 | { \ 208 | PORTA = (d); \ 209 | WR_STROBE; \ 210 | } 211 | #define read8inline(result) \ 212 | { \ 213 | RD_ACTIVE; \ 214 | DELAY7; \ 215 | result = PINA; \ 216 | RD_IDLE; \ 217 | } 218 | #define setWriteDirInline() DDRA = 0xff 219 | #define setReadDirInline() DDRA = 0 220 | 221 | #endif 222 | 223 | // All of the functions are inlined on the Arduino Mega. When using the 224 | // breakout board, the macro versions aren't appreciably larger than the 225 | // function equivalents, and they're super simple and fast. When using 226 | // the shield, the macros become pretty complicated...but this board has 227 | // so much code space, the macros are used anyway. If you need to free 228 | // up program space, some macros can be removed, at a minor cost in speed. 229 | #define write8 write8inline 230 | #define read8 read8inline 231 | #define setWriteDir setWriteDirInline 232 | #define setReadDir setReadDirInline 233 | #define writeRegister8 writeRegister8inline 234 | #define writeRegister16 writeRegister16inline 235 | #define writeRegisterPair writeRegisterPairInline 236 | 237 | #elif defined(__AVR_ATmega32U4__) 238 | 239 | // Arduino Leonardo 240 | 241 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 242 | 243 | #define RD_PORT PORTF 244 | #define WR_PORT PORTF 245 | #define CD_PORT PORTF 246 | #define CS_PORT PORTF 247 | #define RD_MASK B10000000 248 | #define WR_MASK B01000000 249 | #define CD_MASK B00100000 250 | #define CS_MASK B00010000 251 | 252 | #define write8inline(d) \ 253 | { \ 254 | PORTE = (PORTE & B10111111) | (((d)&B10000000) >> 1); \ 255 | PORTD = (PORTD & B01101111) | (((d)&B01000000) << 1) | ((d)&B00010000); \ 256 | PORTC = (PORTC & B01111111) | (((d)&B00100000) << 2); \ 257 | PORTB = (PORTB & B00001111) | (((d)&B00001111) << 4); \ 258 | WR_STROBE; \ 259 | } 260 | #define read8inline(result) \ 261 | { \ 262 | RD_ACTIVE; \ 263 | DELAY7; \ 264 | result = ((PINE & B01000000) << 1) | ((PIND & B10000000) >> 1) | \ 265 | ((PINC & B10000000) >> 2) | ((PINB & B11110000) >> 4) | \ 266 | (PIND & B00010000); \ 267 | RD_IDLE; \ 268 | } 269 | #define setWriteDirInline() \ 270 | { \ 271 | DDRE |= B01000000; \ 272 | DDRD |= B10010000; \ 273 | DDRC |= B10000000; \ 274 | DDRB |= B11110000; \ 275 | } 276 | #define setReadDirInline() \ 277 | { \ 278 | DDRE &= ~B01000000; \ 279 | DDRD &= ~B10010000; \ 280 | DDRC &= ~B10000000; \ 281 | DDRB &= ~B11110000; \ 282 | } 283 | 284 | #else // Leonardo w/Breakout board 285 | 286 | #define write8inline(d) \ 287 | { \ 288 | uint8_t dr1 = (d) >> 1, dl1 = (d) << 1; \ 289 | PORTE = (PORTE & B10111111) | (dr1 & B01000000); \ 290 | PORTD = (PORTD & B01101100) | (dl1 & B10000000) | (((d)&B00001000) >> 3) | \ 291 | (dr1 & B00000010) | ((d)&B00010000); \ 292 | PORTC = (PORTC & B10111111) | (dl1 & B01000000); \ 293 | PORTB = (PORTB & B11001111) | (((d)&B00000011) << 4); \ 294 | WR_STROBE; \ 295 | } 296 | #define read8inline(result) \ 297 | { \ 298 | RD_ACTIVE; \ 299 | DELAY7; \ 300 | result = (((PINE & B01000000) | (PIND & B00000010)) << 1) | \ 301 | (((PINC & B01000000) | (PIND & B10000000)) >> 1) | \ 302 | ((PIND & B00000001) << 3) | ((PINB & B00110000) >> 4) | \ 303 | (PIND & B00010000); \ 304 | RD_IDLE; \ 305 | } 306 | #define setWriteDirInline() \ 307 | { \ 308 | DDRE |= B01000000; \ 309 | DDRD |= B10010011; \ 310 | DDRC |= B01000000; \ 311 | DDRB |= B00110000; \ 312 | } 313 | #define setReadDirInline() \ 314 | { \ 315 | DDRE &= ~B01000000; \ 316 | DDRD &= ~B10010011; \ 317 | DDRC &= ~B01000000; \ 318 | DDRB &= ~B00110000; \ 319 | } 320 | 321 | #endif 322 | 323 | // On the Leonardo, only the write8() macro is used -- though even that 324 | // might be excessive given the code size and available program space 325 | // on this board. You may need to disable this to get any sizable 326 | // program to compile. 327 | #define write8 write8inline 328 | 329 | #elif defined(__SAM3X8E__) 330 | 331 | // Arduino Due 332 | 333 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 334 | 335 | #define RD_PORT PIOA /*pin A0 */ 336 | #define WR_PORT PIOA /*pin A1 */ 337 | #define CD_PORT PIOA /*pin A2 */ 338 | #define CS_PORT PIOA /*pin A3 */ 339 | #define RD_MASK 0x00010000 340 | #define WR_MASK 0x01000000 341 | #define CD_MASK 0x00800000 342 | #define CS_MASK 0x00400000 343 | 344 | #define write8inline(d) \ 345 | { \ 346 | PIO_Set(PIOD, (((d)&0x08) << (7 - 3))); \ 347 | PIO_Clear(PIOD, (((~d) & 0x08) << (7 - 3))); \ 348 | PIO_Set(PIOC, (((d)&0x01) << (22 - 0)) | (((d)&0x02) << (21 - 1)) | \ 349 | (((d)&0x04) << (29 - 2)) | (((d)&0x10) << (26 - 4)) | \ 350 | (((d)&0x40) << (24 - 6)) | (((d)&0x80) << (23 - 7))); \ 351 | PIO_Clear(PIOC, \ 352 | (((~d) & 0x01) << (22 - 0)) | (((~d) & 0x02) << (21 - 1)) | \ 353 | (((~d) & 0x04) << (29 - 2)) | (((~d) & 0x10) << (26 - 4)) | \ 354 | (((~d) & 0x40) << (24 - 6)) | (((~d) & 0x80) << (23 - 7))); \ 355 | PIO_Set(PIOB, (((d)&0x20) << (27 - 5))); \ 356 | PIO_Clear(PIOB, (((~d) & 0x20) << (27 - 5))); \ 357 | WR_STROBE; \ 358 | } 359 | 360 | #define read8inline(result) \ 361 | { \ 362 | \ 363 | RD_ACTIVE; \ 364 | delayMicroseconds(1); \ 365 | result = (((PIOC->PIO_PDSR & (1 << 23)) >> (23 - 7)) | \ 366 | ((PIOC->PIO_PDSR & (1 << 24)) >> (24 - 6)) | \ 367 | ((PIOB->PIO_PDSR & (1 << 27)) >> (27 - 5)) | \ 368 | ((PIOC->PIO_PDSR & (1 << 26)) >> (26 - 4)) | \ 369 | ((PIOD->PIO_PDSR & (1 << 7)) >> (7 - 3)) | \ 370 | ((PIOC->PIO_PDSR & (1 << 29)) >> (29 - 2)) | \ 371 | ((PIOC->PIO_PDSR & (1 << 21)) >> (21 - 1)) | \ 372 | ((PIOC->PIO_PDSR & (1 << 22)) >> (22 - 0))); \ 373 | RD_IDLE; \ 374 | } 375 | 376 | #define setWriteDirInline() \ 377 | { \ 378 | PIOD->PIO_MDDR |= 0x00000080; /*PIOD->PIO_SODR = 0x00000080;*/ \ 379 | PIOD->PIO_OER |= 0x00000080; \ 380 | PIOD->PIO_PER |= 0x00000080; \ 381 | PIOC->PIO_MDDR |= 0x25E00000; /*PIOC->PIO_SODR = 0x25E00000;*/ \ 382 | PIOC->PIO_OER |= 0x25E00000; \ 383 | PIOC->PIO_PER |= 0x25E00000; \ 384 | PIOB->PIO_MDDR |= 0x08000000; /*PIOB->PIO_SODR = 0x08000000;*/ \ 385 | PIOB->PIO_OER |= 0x08000000; \ 386 | PIOB->PIO_PER |= 0x08000000; \ 387 | } 388 | 389 | #define setReadDirInline() \ 390 | { \ 391 | pmc_enable_periph_clk(ID_PIOD); \ 392 | pmc_enable_periph_clk(ID_PIOC); \ 393 | pmc_enable_periph_clk(ID_PIOB); \ 394 | PIOD->PIO_PUDR |= 0x00000080; \ 395 | PIOD->PIO_IFDR |= 0x00000080; \ 396 | PIOD->PIO_ODR |= 0x00000080; \ 397 | PIOD->PIO_PER |= 0x00000080; \ 398 | PIOC->PIO_PUDR |= 0x25E00000; \ 399 | PIOC->PIO_IFDR |= 0x25E00000; \ 400 | PIOC->PIO_ODR |= 0x25E00000; \ 401 | PIOC->PIO_PER |= 0x25E00000; \ 402 | PIOB->PIO_PUDR |= 0x08000000; \ 403 | PIOB->PIO_IFDR |= 0x08000000; \ 404 | PIOB->PIO_ODR |= 0x08000000; \ 405 | PIOB->PIO_PER |= 0x08000000; \ 406 | } 407 | 408 | // Control signals are ACTIVE LOW (idle is HIGH) 409 | // Command/Data: LOW = command, HIGH = data 410 | // These are single-instruction operations and always inline 411 | #define RD_ACTIVE RD_PORT->PIO_CODR |= RD_MASK 412 | #define RD_IDLE RD_PORT->PIO_SODR |= RD_MASK 413 | #define WR_ACTIVE WR_PORT->PIO_CODR |= WR_MASK 414 | #define WR_IDLE WR_PORT->PIO_SODR |= WR_MASK 415 | #define CD_COMMAND CD_PORT->PIO_CODR |= CD_MASK 416 | #define CD_DATA CD_PORT->PIO_SODR |= CD_MASK 417 | #define CS_ACTIVE CS_PORT->PIO_CODR |= CS_MASK 418 | #define CS_IDLE CS_PORT->PIO_SODR |= CS_MASK 419 | 420 | #else // Due w/Breakout board 421 | 422 | #define write8inline(d) \ 423 | { \ 424 | PIO_Set(PIOC, (((d)&0xFF) << 1)); \ 425 | PIO_Clear(PIOC, (((~d) & 0xFF) << 1)); \ 426 | WR_STROBE; \ 427 | } 428 | 429 | #define read8inline(result) \ 430 | { \ 431 | RD_ACTIVE; \ 432 | delayMicroseconds(1); \ 433 | result = ((PIOC->PIO_PDSR & 0x1FE) >> 1); \ 434 | RD_IDLE; \ 435 | } 436 | 437 | #define setWriteDirInline() \ 438 | { \ 439 | PIOC->PIO_MDDR |= 0x000001FE; /*PIOC->PIO_SODR |= 0x000001FE;*/ \ 440 | PIOC->PIO_OER |= 0x000001FE; \ 441 | PIOC->PIO_PER |= 0x000001FE; \ 442 | } 443 | 444 | #define setReadDirInline() \ 445 | { \ 446 | pmc_enable_periph_clk(ID_PIOC); \ 447 | PIOC->PIO_PUDR |= 0x000001FE; \ 448 | PIOC->PIO_IFDR |= 0x000001FE; \ 449 | PIOC->PIO_ODR |= 0x000001FE; \ 450 | PIOC->PIO_PER |= 0x000001FE; \ 451 | } 452 | 453 | // When using the TFT breakout board, control pins are configurable. 454 | #define RD_ACTIVE rdPort->PIO_CODR |= rdPinSet // PIO_Clear(rdPort, rdPinSet) 455 | #define RD_IDLE rdPort->PIO_SODR |= rdPinSet // PIO_Set(rdPort, rdPinSet) 456 | #define WR_ACTIVE wrPort->PIO_CODR |= wrPinSet // PIO_Clear(wrPort, wrPinSet) 457 | #define WR_IDLE wrPort->PIO_SODR |= wrPinSet // PIO_Set(wrPort, wrPinSet) 458 | #define CD_COMMAND cdPort->PIO_CODR |= cdPinSet // PIO_Clear(cdPort, cdPinSet) 459 | #define CD_DATA cdPort->PIO_SODR |= cdPinSet // PIO_Set(cdPort, cdPinSet) 460 | #define CS_ACTIVE csPort->PIO_CODR |= csPinSet // PIO_Clear(csPort, csPinSet) 461 | #define CS_IDLE csPort->PIO_SODR |= csPinSet // PIO_Set(csPort, csPinSet) 462 | 463 | #endif 464 | 465 | #else 466 | 467 | #error "Board type unsupported / not recognized" 468 | 469 | #endif 470 | 471 | #if !defined(__SAM3X8E__) 472 | // Stuff common to all Arduino AVR board types: 473 | 474 | #ifdef USE_ADAFRUIT_SHIELD_PINOUT 475 | 476 | // Control signals are ACTIVE LOW (idle is HIGH) 477 | // Command/Data: LOW = command, HIGH = data 478 | // These are single-instruction operations and always inline 479 | #define RD_ACTIVE RD_PORT &= ~RD_MASK 480 | #define RD_IDLE RD_PORT |= RD_MASK 481 | #define WR_ACTIVE WR_PORT &= ~WR_MASK 482 | #define WR_IDLE WR_PORT |= WR_MASK 483 | #define CD_COMMAND CD_PORT &= ~CD_MASK 484 | #define CD_DATA CD_PORT |= CD_MASK 485 | #define CS_ACTIVE CS_PORT &= ~CS_MASK 486 | #define CS_IDLE CS_PORT |= CS_MASK 487 | 488 | #else // Breakout board 489 | 490 | // When using the TFT breakout board, control pins are configurable. 491 | #define RD_ACTIVE *rdPort &= rdPinUnset 492 | #define RD_IDLE *rdPort |= rdPinSet 493 | #define WR_ACTIVE *wrPort &= wrPinUnset 494 | #define WR_IDLE *wrPort |= wrPinSet 495 | #define CD_COMMAND *cdPort &= cdPinUnset 496 | #define CD_DATA *cdPort |= cdPinSet 497 | #define CS_ACTIVE *csPort &= csPinUnset 498 | #define CS_IDLE *csPort |= csPinSet 499 | 500 | #endif 501 | #endif 502 | 503 | // Data write strobe, ~2 instructions and always inline 504 | #define WR_STROBE \ 505 | { \ 506 | WR_ACTIVE; \ 507 | WR_IDLE; \ 508 | } 509 | 510 | // These higher-level operations are usually functionalized, 511 | // except on Mega where's there's gobs and gobs of program space. 512 | 513 | // Set value of TFT register: 8-bit address, 8-bit value 514 | #define writeRegister8inline(a, d) \ 515 | { \ 516 | CD_COMMAND; \ 517 | write8(a); \ 518 | CD_DATA; \ 519 | write8(d); \ 520 | } 521 | 522 | // Set value of TFT register: 16-bit address, 16-bit value 523 | // See notes at top about macro expansion, hence hi & lo temp vars 524 | #define writeRegister16inline(a, d) \ 525 | { \ 526 | uint8_t hi, lo; \ 527 | hi = (a) >> 8; \ 528 | lo = (a); \ 529 | CD_COMMAND; \ 530 | write8(hi); \ 531 | write8(lo); \ 532 | hi = (d) >> 8; \ 533 | lo = (d); \ 534 | CD_DATA; \ 535 | write8(hi); \ 536 | write8(lo); \ 537 | } 538 | 539 | // Set value of 2 TFT registers: Two 8-bit addresses (hi & lo), 16-bit value 540 | #define writeRegisterPairInline(aH, aL, d) \ 541 | { \ 542 | uint8_t hi = (d) >> 8, lo = (d); \ 543 | CD_COMMAND; \ 544 | write8(aH); \ 545 | CD_DATA; \ 546 | write8(hi); \ 547 | CD_COMMAND; \ 548 | write8(aL); \ 549 | CD_DATA; \ 550 | write8(lo); \ 551 | } 552 | 553 | #endif // _pin_magic_ 554 | -------------------------------------------------------------------------------- /registers.h: -------------------------------------------------------------------------------- 1 | // Register names from Peter Barrett's Microtouch code 2 | #define ILI932X_START_OSC 0x00 3 | #define ILI932X_DRIV_OUT_CTRL 0x01 4 | #define ILI932X_DRIV_WAV_CTRL 0x02 5 | #define ILI932X_ENTRY_MOD 0x03 6 | #define ILI932X_RESIZE_CTRL 0x04 7 | #define ILI932X_DISP_CTRL1 0x07 8 | #define ILI932X_DISP_CTRL2 0x08 9 | #define ILI932X_DISP_CTRL3 0x09 10 | #define ILI932X_DISP_CTRL4 0x0A 11 | #define ILI932X_RGB_DISP_IF_CTRL1 0x0C 12 | #define ILI932X_FRM_MARKER_POS 0x0D 13 | #define ILI932X_RGB_DISP_IF_CTRL2 0x0F 14 | #define ILI932X_POW_CTRL1 0x10 15 | #define ILI932X_POW_CTRL2 0x11 16 | #define ILI932X_POW_CTRL3 0x12 17 | #define ILI932X_POW_CTRL4 0x13 18 | #define ILI932X_GRAM_HOR_AD 0x20 19 | #define ILI932X_GRAM_VER_AD 0x21 20 | #define ILI932X_RW_GRAM 0x22 21 | #define ILI932X_POW_CTRL7 0x29 22 | #define ILI932X_FRM_RATE_COL_CTRL 0x2B 23 | #define ILI932X_GAMMA_CTRL1 0x30 24 | #define ILI932X_GAMMA_CTRL2 0x31 25 | #define ILI932X_GAMMA_CTRL3 0x32 26 | #define ILI932X_GAMMA_CTRL4 0x35 27 | #define ILI932X_GAMMA_CTRL5 0x36 28 | #define ILI932X_GAMMA_CTRL6 0x37 29 | #define ILI932X_GAMMA_CTRL7 0x38 30 | #define ILI932X_GAMMA_CTRL8 0x39 31 | #define ILI932X_GAMMA_CTRL9 0x3C 32 | #define ILI932X_GAMMA_CTRL10 0x3D 33 | #define ILI932X_HOR_START_AD 0x50 34 | #define ILI932X_HOR_END_AD 0x51 35 | #define ILI932X_VER_START_AD 0x52 36 | #define ILI932X_VER_END_AD 0x53 37 | #define ILI932X_GATE_SCAN_CTRL1 0x60 38 | #define ILI932X_GATE_SCAN_CTRL2 0x61 39 | #define ILI932X_GATE_SCAN_CTRL3 0x6A 40 | #define ILI932X_PART_IMG1_DISP_POS 0x80 41 | #define ILI932X_PART_IMG1_START_AD 0x81 42 | #define ILI932X_PART_IMG1_END_AD 0x82 43 | #define ILI932X_PART_IMG2_DISP_POS 0x83 44 | #define ILI932X_PART_IMG2_START_AD 0x84 45 | #define ILI932X_PART_IMG2_END_AD 0x85 46 | #define ILI932X_PANEL_IF_CTRL1 0x90 47 | #define ILI932X_PANEL_IF_CTRL2 0x92 48 | #define ILI932X_PANEL_IF_CTRL3 0x93 49 | #define ILI932X_PANEL_IF_CTRL4 0x95 50 | #define ILI932X_PANEL_IF_CTRL5 0x97 51 | #define ILI932X_PANEL_IF_CTRL6 0x98 52 | 53 | #define HX8347G_COLADDRSTART_HI 0x02 54 | #define HX8347G_COLADDRSTART_LO 0x03 55 | #define HX8347G_COLADDREND_HI 0x04 56 | #define HX8347G_COLADDREND_LO 0x05 57 | #define HX8347G_ROWADDRSTART_HI 0x06 58 | #define HX8347G_ROWADDRSTART_LO 0x07 59 | #define HX8347G_ROWADDREND_HI 0x08 60 | #define HX8347G_ROWADDREND_LO 0x09 61 | #define HX8347G_MEMACCESS 0x16 62 | 63 | #define ILI9341_SOFTRESET 0x01 64 | #define ILI9341_SLEEPIN 0x10 65 | #define ILI9341_SLEEPOUT 0x11 66 | #define ILI9341_NORMALDISP 0x13 67 | #define ILI9341_INVERTOFF 0x20 68 | #define ILI9341_INVERTON 0x21 69 | #define ILI9341_GAMMASET 0x26 70 | #define ILI9341_DISPLAYOFF 0x28 71 | #define ILI9341_DISPLAYON 0x29 72 | #define ILI9341_COLADDRSET 0x2A 73 | #define ILI9341_PAGEADDRSET 0x2B 74 | #define ILI9341_MEMORYWRITE 0x2C 75 | #define ILI9341_PIXELFORMAT 0x3A 76 | #define ILI9341_FRAMECONTROL 0xB1 77 | #define ILI9341_DISPLAYFUNC 0xB6 78 | #define ILI9341_ENTRYMODE 0xB7 79 | #define ILI9341_POWERCONTROL1 0xC0 80 | #define ILI9341_POWERCONTROL2 0xC1 81 | #define ILI9341_VCOMCONTROL1 0xC5 82 | #define ILI9341_VCOMCONTROL2 0xC7 83 | #define ILI9341_MEMCONTROL 0x36 84 | #define ILI9341_MADCTL 0x36 85 | 86 | #define ILI9341_MADCTL_MY 0x80 87 | #define ILI9341_MADCTL_MX 0x40 88 | #define ILI9341_MADCTL_MV 0x20 89 | #define ILI9341_MADCTL_ML 0x10 90 | #define ILI9341_MADCTL_RGB 0x00 91 | #define ILI9341_MADCTL_BGR 0x08 92 | #define ILI9341_MADCTL_MH 0x04 93 | 94 | #define HX8357_NOP 0x00 95 | #define HX8357_SWRESET 0x01 96 | #define HX8357_RDDID 0x04 97 | #define HX8357_RDDST 0x09 98 | 99 | #define HX8357B_RDPOWMODE 0x0A 100 | #define HX8357B_RDMADCTL 0x0B 101 | #define HX8357B_RDCOLMOD 0x0C 102 | #define HX8357B_RDDIM 0x0D 103 | #define HX8357B_RDDSDR 0x0F 104 | 105 | #define HX8357_SLPIN 0x10 106 | #define HX8357_SLPOUT 0x11 107 | #define HX8357B_PTLON 0x12 108 | #define HX8357B_NORON 0x13 109 | 110 | #define HX8357_INVOFF 0x20 111 | #define HX8357_INVON 0x21 112 | #define HX8357_DISPOFF 0x28 113 | #define HX8357_DISPON 0x29 114 | 115 | #define HX8357_CASET 0x2A 116 | #define HX8357_PASET 0x2B 117 | #define HX8357_RAMWR 0x2C 118 | #define HX8357_RAMRD 0x2E 119 | 120 | #define HX8357B_PTLAR 0x30 121 | #define HX8357_TEON 0x35 122 | #define HX8357_TEARLINE 0x44 123 | #define HX8357_MADCTL 0x36 124 | #define HX8357_COLMOD 0x3A 125 | 126 | #define HX8357_SETOSC 0xB0 127 | #define HX8357_SETPWR1 0xB1 128 | #define HX8357B_SETDISPLAY 0xB2 129 | #define HX8357_SETRGB 0xB3 130 | #define HX8357D_SETCOM 0xB6 131 | 132 | #define HX8357B_SETDISPMODE 0xB4 133 | #define HX8357D_SETCYC 0xB4 134 | #define HX8357B_SETOTP 0xB7 135 | #define HX8357D_SETC 0xB9 136 | 137 | #define HX8357B_SET_PANEL_DRIVING 0xC0 138 | #define HX8357D_SETSTBA 0xC0 139 | #define HX8357B_SETDGC 0xC1 140 | #define HX8357B_SETID 0xC3 141 | #define HX8357B_SETDDB 0xC4 142 | #define HX8357B_SETDISPLAYFRAME 0xC5 143 | #define HX8357B_GAMMASET 0xC8 144 | #define HX8357B_SETCABC 0xC9 145 | #define HX8357_SETPANEL 0xCC 146 | 147 | #define HX8357B_SETPOWER 0xD0 148 | #define HX8357B_SETVCOM 0xD1 149 | #define HX8357B_SETPWRNORMAL 0xD2 150 | 151 | #define HX8357B_RDID1 0xDA 152 | #define HX8357B_RDID2 0xDB 153 | #define HX8357B_RDID3 0xDC 154 | #define HX8357B_RDID4 0xDD 155 | 156 | #define HX8357D_SETGAMMA 0xE0 157 | 158 | #define HX8357B_SETGAMMA 0xC8 159 | #define HX8357B_SETPANELRELATED 0xE9 160 | 161 | #define HX8357B_MADCTL_MY 0x80 162 | #define HX8357B_MADCTL_MX 0x40 163 | #define HX8357B_MADCTL_MV 0x20 164 | #define HX8357B_MADCTL_ML 0x10 165 | #define HX8357B_MADCTL_RGB 0x00 166 | #define HX8357B_MADCTL_BGR 0x08 167 | #define HX8357B_MADCTL_MH 0x04 168 | --------------------------------------------------------------------------------